parse.y revision 69194
189099Sfjoe%{
289099Sfjoe/*-
389099Sfjoe * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
489099Sfjoe *		at Electronni Visti IA, Kiev, Ukraine.
589099Sfjoe *			All rights reserved.
689099Sfjoe *
789099Sfjoe * Redistribution and use in source and binary forms, with or without
889099Sfjoe * modification, are permitted provided that the following conditions
989099Sfjoe * are met:
1089099Sfjoe * 1. Redistributions of source code must retain the above copyright
1189099Sfjoe *    notice, this list of conditions and the following disclaimer.
1289099Sfjoe * 2. Redistributions in binary form must reproduce the above copyright
1389099Sfjoe *    notice, this list of conditions and the following disclaimer in the
1489099Sfjoe *    documentation and/or other materials provided with the distribution.
1589099Sfjoe *
1689099Sfjoe * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
1789099Sfjoe * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1889099Sfjoe * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1989099Sfjoe * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
2089099Sfjoe * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2189099Sfjoe * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2289099Sfjoe * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2389099Sfjoe * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2489099Sfjoe * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2589099Sfjoe * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2689099Sfjoe * SUCH DAMAGE.
2789099Sfjoe *
2889099Sfjoe * $FreeBSD: head/usr.bin/colldef/parse.y 69194 2000-11-26 08:14:55Z kris $
2989099Sfjoe */
3089099Sfjoe
3189099Sfjoe#include <err.h>
3289099Sfjoe#include <stdarg.h>
3389099Sfjoe#include <stdio.h>
3489099Sfjoe#include <string.h>
3589099Sfjoe#include <stdlib.h>
3689099Sfjoe#include <unistd.h>
3789099Sfjoe#include <sysexits.h>
3889099Sfjoe#include "collate.h"
3989099Sfjoe
4089099Sfjoeextern int line_no;
4189099Sfjoeextern FILE *yyin;
4289099Sfjoevoid yyerror(char *fmt, ...);
43109771Sfjoeint yyparse(void);
4489099Sfjoeint yylex(void);
4589099Sfjoestatic void usage __P((void));
4689099Sfjoe
4789099Sfjoechar map_name[FILENAME_MAX] = ".";
48129880Sphk
4989099Sfjoechar __collate_version[STR_LEN];
5089099Sfjoeu_char charmap_table[UCHAR_MAX + 1][STR_LEN];
5189099Sfjoeu_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN];
5289099Sfjoestruct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1];
5389099Sfjoestruct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE];
5489099Sfjoeint chain_index;
5589099Sfjoeint prim_pri = 1, sec_pri = 1;
5689099Sfjoe#ifdef COLLATE_DEBUG
5789099Sfjoeint debug;
5889099Sfjoe#endif
5989099Sfjoe
6089099Sfjoechar *out_file = "LC_COLLATE";
6189099Sfjoe%}
6289099Sfjoe%union {
6389099Sfjoe	u_char ch;
6489099Sfjoe	u_char str[STR_LEN];
6589099Sfjoe}
6689099Sfjoe%token SUBSTITUTE WITH ORDER RANGE
6789099Sfjoe%token <str> STRING
6889099Sfjoe%token <str> CHAIN
6989099Sfjoe%token <str> DEFN
7089099Sfjoe%token <ch> CHAR
7189099Sfjoe%%
7289099Sfjoecollate : statment_list
7389099Sfjoe;
7489099Sfjoestatment_list : statment
7589099Sfjoe	| statment_list '\n' statment
7689099Sfjoe;
7789099Sfjoestatment :
78109771Sfjoe	| charmap
79109771Sfjoe	| substitute
80109771Sfjoe	| order
81109771Sfjoe;
82109771Sfjoecharmap : DEFN CHAR {
8389099Sfjoe	strcpy(charmap_table[$2], $1);
8489099Sfjoe}
8589099Sfjoe;
8689099Sfjoesubstitute : SUBSTITUTE CHAR WITH STRING {
8792725Salfred	if ($2 == '\0')
88109771Sfjoe		yyerror("NUL character can't be substituted");
89109771Sfjoe	if (strchr($4, $2) != NULL)
9089099Sfjoe		yyerror("Char 0x%02x substitution is recursive", $2);
9189099Sfjoe	strcpy(__collate_substitute_table[$2], $4);
9289099Sfjoe}
93110106Sfjoe;
94110106Sfjoeorder : ORDER order_list {
9589099Sfjoe	FILE *fp;
96109771Sfjoe	int ch, substed, ordered;
97109771Sfjoe
9889099Sfjoe	for (ch = 0; ch < UCHAR_MAX + 1; ch++) {
9989099Sfjoe		substed = (__collate_substitute_table[ch][0] != ch);
10089099Sfjoe		ordered = !!__collate_char_pri_table[ch].prim;
10189099Sfjoe		if (!ordered && !substed)
10289099Sfjoe			yyerror("Char 0x%02x not found", ch);
10389099Sfjoe		if (substed && ordered)
10489099Sfjoe			yyerror("Char 0x%02x can't be ordered since substituted", ch);
10589099Sfjoe	}
10689099Sfjoe
10789099Sfjoe	fp = fopen(out_file, "w");
10889099Sfjoe	if(!fp)
10989099Sfjoe		err(EX_UNAVAILABLE, "can't open destination file %s",
11089099Sfjoe		    out_file);
11189099Sfjoe
11289099Sfjoe	strcpy(__collate_version, COLLATE_VERSION);
11389099Sfjoe	fwrite(__collate_version, sizeof(__collate_version), 1, fp);
114109771Sfjoe	fwrite(__collate_substitute_table, sizeof(__collate_substitute_table), 1, fp);
115110106Sfjoe	fwrite(__collate_char_pri_table, sizeof(__collate_char_pri_table), 1, fp);
11689099Sfjoe	fwrite(__collate_chain_pri_table, sizeof(__collate_chain_pri_table), 1, fp);
11789099Sfjoe	if (fflush(fp))
11889099Sfjoe		err(EX_UNAVAILABLE, "IO error writting to destination file %s",
11989099Sfjoe		    out_file);
12089099Sfjoe	fclose(fp);
12189099Sfjoe#ifdef COLLATE_DEBUG
12289099Sfjoe	if (debug)
12389099Sfjoe		collate_print_tables();
12489099Sfjoe#endif
12589099Sfjoe	exit(EX_OK);
12689099Sfjoe}
12789099Sfjoe;
12889099Sfjoeorder_list : item
12989099Sfjoe	| order_list ';' item
13089099Sfjoe;
13189099Sfjoeitem :  CHAR {
13289099Sfjoe	if (__collate_char_pri_table[$1].prim)
133128636Sluigi		yyerror("Char 0x%02x duplicated", $1);
134128636Sluigi	__collate_char_pri_table[$1].prim = prim_pri++;
135128636Sluigi}
136128636Sluigi	| CHAIN {
137128636Sluigi	if (chain_index >= TABLE_SIZE - 1)
13889099Sfjoe		yyerror("__collate_chain_pri_table overflow");
13989099Sfjoe	strcpy(__collate_chain_pri_table[chain_index].str, $1);
14089099Sfjoe	__collate_chain_pri_table[chain_index++].prim = prim_pri++;
14189099Sfjoe}
142127260Smdodd	| CHAR RANGE CHAR {
143127260Smdodd	u_int i;
144127260Smdodd
145127260Smdodd	if ($3 <= $1)
146127260Smdodd		yyerror("Illegal range 0x%02x -- 0x%02x", $1, $3);
147127260Smdodd
148127260Smdodd	for (i = $1; i <= $3; i++) {
149127260Smdodd		if (__collate_char_pri_table[(u_char)i].prim)
150127260Smdodd			yyerror("Char 0x%02x duplicated", (u_char)i);
151127260Smdodd		__collate_char_pri_table[(u_char)i].prim = prim_pri++;
152127260Smdodd	}
153127275Smdodd}
154127260Smdodd	| '{' prim_order_list '}' {
155127260Smdodd	prim_pri++;
156127260Smdodd}
157127260Smdodd	| '(' sec_order_list ')' {
158127275Smdodd	prim_pri++;
159127260Smdodd	sec_pri = 1;
160127260Smdodd}
161127260Smdodd;
162127260Smdoddprim_order_list : prim_sub_item
163127290Smdodd	| prim_order_list ',' prim_sub_item
164127260Smdodd;
165127290Smdoddsec_order_list : sec_sub_item
166127260Smdodd	| sec_order_list ',' sec_sub_item
167127260Smdodd;
168127260Smdoddprim_sub_item : CHAR {
16989099Sfjoe	if (__collate_char_pri_table[$1].prim)
17089099Sfjoe		yyerror("Char 0x%02x duplicated", $1);
17189099Sfjoe	__collate_char_pri_table[$1].prim = prim_pri;
172128636Sluigi}
173128636Sluigi	| CHAR RANGE CHAR {
174128636Sluigi	u_int i;
17589099Sfjoe
17689099Sfjoe	if ($3 <= $1)
17789099Sfjoe		yyerror("Illegal range 0x%02x -- 0x%02x",
178109771Sfjoe			$1, $3);
179109771Sfjoe
180109771Sfjoe	for (i = $1; i <= $3; i++) {
181109771Sfjoe		if (__collate_char_pri_table[(u_char)i].prim)
182109771Sfjoe			yyerror("Char 0x%02x duplicated", (u_char)i);
183109771Sfjoe		__collate_char_pri_table[(u_char)i].prim = prim_pri;
184109771Sfjoe	}
185109771Sfjoe}
18689099Sfjoe	| CHAIN {
18789099Sfjoe	if (chain_index >= TABLE_SIZE - 1)
188109771Sfjoe		yyerror("__collate_chain_pri_table overflow");
18989099Sfjoe	strcpy(__collate_chain_pri_table[chain_index].str, $1);
19089099Sfjoe	__collate_chain_pri_table[chain_index++].prim = prim_pri;
19189099Sfjoe}
19289099Sfjoe;
19389099Sfjoesec_sub_item : CHAR {
19489099Sfjoe	if (__collate_char_pri_table[$1].prim)
19589099Sfjoe		yyerror("Char 0x%02x duplicated", $1);
19689099Sfjoe	__collate_char_pri_table[$1].prim = prim_pri;
19789099Sfjoe	__collate_char_pri_table[$1].sec = sec_pri++;
19889099Sfjoe}
19989099Sfjoe	| CHAR RANGE CHAR {
20089099Sfjoe	u_int i;
20189099Sfjoe
20289099Sfjoe	if ($3 <= $1)
20389099Sfjoe		yyerror("Illegal range 0x%02x -- 0x%02x",
20489099Sfjoe			$1, $3);
205109771Sfjoe
20689099Sfjoe	for (i = $1; i <= $3; i++) {
20789099Sfjoe		if (__collate_char_pri_table[(u_char)i].prim)
20889099Sfjoe			yyerror("Char 0x%02x duplicated", (u_char)i);
20989099Sfjoe		__collate_char_pri_table[(u_char)i].prim = prim_pri;
21089099Sfjoe		__collate_char_pri_table[(u_char)i].sec = sec_pri++;
211105598Sbrooks	}
21289099Sfjoe}
21389099Sfjoe	| CHAIN {
21489099Sfjoe	if (chain_index >= TABLE_SIZE - 1)
215110106Sfjoe		yyerror("__collate_chain_pri_table overflow");
216111119Simp	strcpy(__collate_chain_pri_table[chain_index].str, $1);
21789099Sfjoe	__collate_chain_pri_table[chain_index].prim = prim_pri;
21889099Sfjoe	__collate_chain_pri_table[chain_index++].sec = sec_pri++;
21989099Sfjoe}
22089099Sfjoe;
22189099Sfjoe%%
222110106Sfjoeint
223110106Sfjoemain(ac, av)
224110106Sfjoe	char **av;
225110106Sfjoe{
226110106Sfjoe	int ch;
22789099Sfjoe
228109771Sfjoe#ifdef COLLATE_DEBUG
229109771Sfjoe	while((ch = getopt(ac, av, ":do:I:")) != EOF) {
230109771Sfjoe#else
231109771Sfjoe	while((ch = getopt(ac, av, ":o:I:")) != EOF) {
232109771Sfjoe#endif
233109771Sfjoe		switch (ch)
234109771Sfjoe		{
235109771Sfjoe#ifdef COLLATE_DEBUG
236109771Sfjoe		  case 'd':
237109771Sfjoe			debug++;
238109771Sfjoe			break;
239106939Ssam#endif
24089099Sfjoe		  case 'o':
241130549Smlaier			out_file = optarg;
24289099Sfjoe			break;
24389099Sfjoe
24489099Sfjoe		  case 'I':
24589099Sfjoe			strcpy(map_name, optarg);
24689099Sfjoe			break;
24789099Sfjoe
24889099Sfjoe		  default:
24989099Sfjoe			usage();
25089099Sfjoe		}
25189099Sfjoe	}
25289099Sfjoe	ac -= optind;
25389099Sfjoe	av += optind;
25489099Sfjoe	if(ac > 0) {
25589099Sfjoe		if((yyin = fopen(*av, "r")) == 0)
25689099Sfjoe			err(EX_UNAVAILABLE, "can't open source file %s", *av);
25789099Sfjoe	}
25889099Sfjoe	for(ch = 0; ch <= UCHAR_MAX; ch++)
25989099Sfjoe		__collate_substitute_table[ch][0] = ch;
26089099Sfjoe	yyparse();
26189099Sfjoe	return 0;
26289099Sfjoe}
26389099Sfjoe
26489099Sfjoestatic void
26589099Sfjoeusage()
26689099Sfjoe{
26789099Sfjoe	fprintf(stderr, "usage: colldef [-o out_file] [-I map_dir] [filename]\n");
26889099Sfjoe	exit(EX_USAGE);
26989099Sfjoe}
27089099Sfjoe
27189099Sfjoevoid yyerror(char *fmt, ...)
27289099Sfjoe{
27389099Sfjoe	va_list ap;
27489099Sfjoe	char msg[128];
27589099Sfjoe
27689099Sfjoe	va_start(ap, fmt);
27789099Sfjoe	vsnprintf(msg, sizeof(msg), fmt, ap);
27889099Sfjoe	va_end(ap);
27989099Sfjoe	errx(EX_UNAVAILABLE, "%s near line %d", msg, line_no);
28089099Sfjoe}
28189099Sfjoe
28289099Sfjoe#ifdef COLLATE_DEBUG
283109771Sfjoevoid
28489099Sfjoecollate_print_tables()
28589099Sfjoe{
28689099Sfjoe	int i;
28789099Sfjoe	struct __collate_st_chain_pri *p2;
28889099Sfjoe
28989099Sfjoe	printf("Substitute table:\n");
29089099Sfjoe	for (i = 0; i < UCHAR_MAX + 1; i++)
291110106Sfjoe	    if (i != *__collate_substitute_table[i])
29289099Sfjoe		printf("\t'%c' --> \"%s\"\n", i,
29389099Sfjoe		       __collate_substitute_table[i]);
29489099Sfjoe	printf("Chain priority table:\n");
29589099Sfjoe	for (p2 = __collate_chain_pri_table; p2->str[0]; p2++)
29689099Sfjoe		printf("\t\"%s\" : %d %d\n\n", p2->str, p2->prim, p2->sec);
29789099Sfjoe	printf("Char priority table:\n");
298111119Simp	for (i = 0; i < UCHAR_MAX + 1; i++)
29989099Sfjoe		printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim,
30093750Sluigi		       __collate_char_pri_table[i].sec);
30189099Sfjoe}
30289099Sfjoe#endif
30389099Sfjoe