parse.y revision 87052
16527Sache%{
26527Sache/*-
36527Sache * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
46527Sache *		at Electronni Visti IA, Kiev, Ukraine.
56527Sache *			All rights reserved.
66527Sache *
76527Sache * Redistribution and use in source and binary forms, with or without
86527Sache * modification, are permitted provided that the following conditions
96527Sache * are met:
106527Sache * 1. Redistributions of source code must retain the above copyright
116527Sache *    notice, this list of conditions and the following disclaimer.
126527Sache * 2. Redistributions in binary form must reproduce the above copyright
136527Sache *    notice, this list of conditions and the following disclaimer in the
146527Sache *    documentation and/or other materials provided with the distribution.
156527Sache *
166527Sache * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
176527Sache * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
186527Sache * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
196527Sache * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
206527Sache * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
216527Sache * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
226527Sache * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
236527Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
246527Sache * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
256527Sache * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
266527Sache * SUCH DAMAGE.
276527Sache *
2850477Speter * $FreeBSD: head/usr.bin/colldef/parse.y 87052 2001-11-28 09:50:24Z ache $
296527Sache */
306527Sache
316527Sache#include <err.h>
3218950Sache#include <stdarg.h>
336527Sache#include <stdio.h>
346527Sache#include <string.h>
356527Sache#include <stdlib.h>
3623706Speter#include <unistd.h>
376527Sache#include <sysexits.h>
386527Sache#include "collate.h"
3987012Sache#include "common.h"
406527Sache
416527Sacheextern FILE *yyin;
4280280Skrisvoid yyerror(char *fmt, ...) __printflike(1, 2);
4341568Sarchieint yyparse(void);
4441568Sarchieint yylex(void);
4526959Scharnierstatic void usage __P((void));
466527Sache
4718950Sachechar map_name[FILENAME_MAX] = ".";
4818950Sache
4918950Sachechar __collate_version[STR_LEN];
5087012Sacheu_char charmap_table[UCHAR_MAX + 1][CHARMAP_SYMBOL_LEN];
516527Sacheu_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN];
526527Sachestruct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1];
536527Sachestruct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE];
5418950Sacheint chain_index;
556527Sacheint prim_pri = 1, sec_pri = 1;
566527Sache#ifdef COLLATE_DEBUG
576527Sacheint debug;
586527Sache#endif
596527Sache
606527Sachechar *out_file = "LC_COLLATE";
616527Sache%}
626527Sache%union {
636527Sache	u_char ch;
6487052Sache	u_char str[BUFSIZE];
656527Sache}
666527Sache%token SUBSTITUTE WITH ORDER RANGE
676527Sache%token <str> STRING
686527Sache%token <str> CHAIN
6918950Sache%token <str> DEFN
706527Sache%token <ch> CHAR
716527Sache%%
726527Sachecollate : statment_list
736527Sache;
746527Sachestatment_list : statment
756527Sache	| statment_list '\n' statment
766527Sache;
776527Sachestatment :
786527Sache	| charmap
796527Sache	| substitute
806527Sache	| order
816527Sache;
8218950Sachecharmap : DEFN CHAR {
8387015Sache	if (strlen($1) + 1 > CHARMAP_SYMBOL_LEN)
8487015Sache		yyerror("Charmap symbol name '%s' is too long", $1);
8518950Sache	strcpy(charmap_table[$2], $1);
866527Sache}
876527Sache;
8843967Sachesubstitute : SUBSTITUTE CHAR WITH STRING {
8943967Sache	if ($2 == '\0')
9043943Sache		yyerror("NUL character can't be substituted");
9143967Sache	if (strchr($4, $2) != NULL)
9243967Sache		yyerror("Char 0x%02x substitution is recursive", $2);
9387052Sache	if (strlen($4) + 1 > STR_LEN)
9487052Sache		yyerror("Char 0x%02x substitution is too long", $2);
9543967Sache	strcpy(__collate_substitute_table[$2], $4);
966527Sache}
976527Sache;
986527Sacheorder : ORDER order_list {
9919128Sache	FILE *fp;
10043943Sache	int ch, substed, ordered;
1016527Sache
10243943Sache	for (ch = 0; ch < UCHAR_MAX + 1; ch++) {
10343943Sache		substed = (__collate_substitute_table[ch][0] != ch);
10443943Sache		ordered = !!__collate_char_pri_table[ch].prim;
10543943Sache		if (!ordered && !substed)
10643940Sache			yyerror("Char 0x%02x not found", ch);
10743943Sache		if (substed && ordered)
10843943Sache			yyerror("Char 0x%02x can't be ordered since substituted", ch);
10943943Sache	}
11019128Sache
11119128Sache	fp = fopen(out_file, "w");
1126527Sache	if(!fp)
11318950Sache		err(EX_UNAVAILABLE, "can't open destination file %s",
1146527Sache		    out_file);
1156527Sache
11618950Sache	strcpy(__collate_version, COLLATE_VERSION);
11718950Sache	fwrite(__collate_version, sizeof(__collate_version), 1, fp);
1186527Sache	fwrite(__collate_substitute_table, sizeof(__collate_substitute_table), 1, fp);
1196527Sache	fwrite(__collate_char_pri_table, sizeof(__collate_char_pri_table), 1, fp);
1206527Sache	fwrite(__collate_chain_pri_table, sizeof(__collate_chain_pri_table), 1, fp);
12118950Sache	if (fflush(fp))
12218950Sache		err(EX_UNAVAILABLE, "IO error writting to destination file %s",
12318950Sache		    out_file);
12418950Sache	fclose(fp);
1256527Sache#ifdef COLLATE_DEBUG
1266527Sache	if (debug)
12719128Sache		collate_print_tables();
1286527Sache#endif
1296527Sache	exit(EX_OK);
1306527Sache}
1316527Sache;
1326527Sacheorder_list : item
1336527Sache	| order_list ';' item
1346527Sache;
13519128Sacheitem :  CHAR {
13619128Sache	if (__collate_char_pri_table[$1].prim)
13719163Sache		yyerror("Char 0x%02x duplicated", $1);
13819128Sache	__collate_char_pri_table[$1].prim = prim_pri++;
13919128Sache}
1406527Sache	| CHAIN {
1416527Sache	if (chain_index >= TABLE_SIZE - 1)
1426527Sache		yyerror("__collate_chain_pri_table overflow");
14387052Sache	if (strlen($1) + 1 > STR_LEN)
14487052Sache		yyerror("Chain %d is too long", chain_index);
1456527Sache	strcpy(__collate_chain_pri_table[chain_index].str, $1);
1466527Sache	__collate_chain_pri_table[chain_index++].prim = prim_pri++;
1476527Sache}
1486527Sache	| CHAR RANGE CHAR {
1496527Sache	u_int i;
1506527Sache
1516527Sache	if ($3 <= $1)
15218950Sache		yyerror("Illegal range 0x%02x -- 0x%02x", $1, $3);
1536527Sache
15419128Sache	for (i = $1; i <= $3; i++) {
15519128Sache		if (__collate_char_pri_table[(u_char)i].prim)
15619163Sache			yyerror("Char 0x%02x duplicated", (u_char)i);
1576527Sache		__collate_char_pri_table[(u_char)i].prim = prim_pri++;
15819128Sache	}
1596527Sache}
1606527Sache	| '{' prim_order_list '}' {
1616527Sache	prim_pri++;
1626527Sache}
1636527Sache	| '(' sec_order_list ')' {
1646527Sache	prim_pri++;
1656527Sache	sec_pri = 1;
1666527Sache}
1676527Sache;
1686527Sacheprim_order_list : prim_sub_item
1696527Sache	| prim_order_list ',' prim_sub_item
1706527Sache;
1716527Sachesec_order_list : sec_sub_item
1726527Sache	| sec_order_list ',' sec_sub_item
1736527Sache;
1746527Sacheprim_sub_item : CHAR {
17519128Sache	if (__collate_char_pri_table[$1].prim)
17619163Sache		yyerror("Char 0x%02x duplicated", $1);
1776527Sache	__collate_char_pri_table[$1].prim = prim_pri;
1786527Sache}
1796527Sache	| CHAR RANGE CHAR {
1806527Sache	u_int i;
1816527Sache
1826527Sache	if ($3 <= $1)
18318950Sache		yyerror("Illegal range 0x%02x -- 0x%02x",
18418950Sache			$1, $3);
1856527Sache
18619128Sache	for (i = $1; i <= $3; i++) {
18719128Sache		if (__collate_char_pri_table[(u_char)i].prim)
18819163Sache			yyerror("Char 0x%02x duplicated", (u_char)i);
1896527Sache		__collate_char_pri_table[(u_char)i].prim = prim_pri;
19019128Sache	}
1916527Sache}
1926527Sache	| CHAIN {
1936527Sache	if (chain_index >= TABLE_SIZE - 1)
1946527Sache		yyerror("__collate_chain_pri_table overflow");
19587052Sache	if (strlen($1) + 1 > STR_LEN)
19687052Sache		yyerror("Chain %d is too long", chain_index);
1976527Sache	strcpy(__collate_chain_pri_table[chain_index].str, $1);
1986527Sache	__collate_chain_pri_table[chain_index++].prim = prim_pri;
1996527Sache}
2006527Sache;
2016527Sachesec_sub_item : CHAR {
20219128Sache	if (__collate_char_pri_table[$1].prim)
20319163Sache		yyerror("Char 0x%02x duplicated", $1);
2046527Sache	__collate_char_pri_table[$1].prim = prim_pri;
2056527Sache	__collate_char_pri_table[$1].sec = sec_pri++;
2066527Sache}
2076527Sache	| CHAR RANGE CHAR {
2086527Sache	u_int i;
2096527Sache
2106527Sache	if ($3 <= $1)
21118950Sache		yyerror("Illegal range 0x%02x -- 0x%02x",
21218950Sache			$1, $3);
2136527Sache
2146527Sache	for (i = $1; i <= $3; i++) {
21519128Sache		if (__collate_char_pri_table[(u_char)i].prim)
21619163Sache			yyerror("Char 0x%02x duplicated", (u_char)i);
2176527Sache		__collate_char_pri_table[(u_char)i].prim = prim_pri;
2186527Sache		__collate_char_pri_table[(u_char)i].sec = sec_pri++;
2196527Sache	}
2206527Sache}
2216527Sache	| CHAIN {
2226527Sache	if (chain_index >= TABLE_SIZE - 1)
2236527Sache		yyerror("__collate_chain_pri_table overflow");
22487052Sache	if (strlen($1) + 1 > STR_LEN)
22587052Sache		yyerror("Chain %d is too long", chain_index);
2266527Sache	strcpy(__collate_chain_pri_table[chain_index].str, $1);
2276527Sache	__collate_chain_pri_table[chain_index].prim = prim_pri;
2286527Sache	__collate_chain_pri_table[chain_index++].sec = sec_pri++;
2296527Sache}
2306527Sache;
2316527Sache%%
23241568Sarchieint
2336527Sachemain(ac, av)
2346527Sache	char **av;
2356527Sache{
2366527Sache	int ch;
2376527Sache
2386527Sache#ifdef COLLATE_DEBUG
23918950Sache	while((ch = getopt(ac, av, ":do:I:")) != EOF) {
2406527Sache#else
24118950Sache	while((ch = getopt(ac, av, ":o:I:")) != EOF) {
2426527Sache#endif
2436527Sache		switch (ch)
2446527Sache		{
2456527Sache#ifdef COLLATE_DEBUG
2466527Sache		  case 'd':
2476527Sache			debug++;
2486527Sache			break;
2496527Sache#endif
2506527Sache		  case 'o':
2516527Sache			out_file = optarg;
2526527Sache			break;
2536527Sache
25418950Sache		  case 'I':
25585026Ssobomax			strlcpy(map_name, optarg, sizeof(map_name));
25618950Sache			break;
25718950Sache
2586527Sache		  default:
25926959Scharnier			usage();
2606527Sache		}
2616527Sache	}
2626527Sache	ac -= optind;
2636527Sache	av += optind;
2646527Sache	if(ac > 0) {
2656527Sache		if((yyin = fopen(*av, "r")) == 0)
2666527Sache			err(EX_UNAVAILABLE, "can't open source file %s", *av);
2676527Sache	}
2686527Sache	for(ch = 0; ch <= UCHAR_MAX; ch++)
2696527Sache		__collate_substitute_table[ch][0] = ch;
2706527Sache	yyparse();
2716527Sache	return 0;
2726527Sache}
2736527Sache
27426959Scharnierstatic void
27526959Scharnierusage()
27626959Scharnier{
27726959Scharnier	fprintf(stderr, "usage: colldef [-o out_file] [-I map_dir] [filename]\n");
27827109Scharnier	exit(EX_USAGE);
27926959Scharnier}
28026959Scharnier
28118950Sachevoid yyerror(char *fmt, ...)
2826527Sache{
28318950Sache	va_list ap;
28418950Sache	char msg[128];
28518950Sache
28618950Sache	va_start(ap, fmt);
28769194Skris	vsnprintf(msg, sizeof(msg), fmt, ap);
28818950Sache	va_end(ap);
2896527Sache	errx(EX_UNAVAILABLE, "%s near line %d", msg, line_no);
2906527Sache}
29119128Sache
29219128Sache#ifdef COLLATE_DEBUG
29341568Sarchievoid
29419128Sachecollate_print_tables()
29519128Sache{
29619128Sache	int i;
29719128Sache	struct __collate_st_chain_pri *p2;
29819128Sache
29919128Sache	printf("Substitute table:\n");
30019128Sache	for (i = 0; i < UCHAR_MAX + 1; i++)
30119128Sache	    if (i != *__collate_substitute_table[i])
30219128Sache		printf("\t'%c' --> \"%s\"\n", i,
30319128Sache		       __collate_substitute_table[i]);
30419128Sache	printf("Chain priority table:\n");
30519128Sache	for (p2 = __collate_chain_pri_table; p2->str[0]; p2++)
30619128Sache		printf("\t\"%s\" : %d %d\n\n", p2->str, p2->prim, p2->sec);
30719128Sache	printf("Char priority table:\n");
30819128Sache	for (i = 0; i < UCHAR_MAX + 1; i++)
30919128Sache		printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim,
31019128Sache		       __collate_char_pri_table[i].sec);
31119128Sache}
31219128Sache#endif
313