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