parse.y revision 146466
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 */ 286527Sache 2987243Smarkm#include <sys/cdefs.h> 3087243Smarkm__FBSDID("$FreeBSD: head/usr.bin/colldef/parse.y 146466 2005-05-21 09:55:10Z ru $"); 3187243Smarkm 32102659Sache#include <arpa/inet.h> 336527Sache#include <err.h> 3418950Sache#include <stdarg.h> 356527Sache#include <stdio.h> 366527Sache#include <string.h> 3723706Speter#include <unistd.h> 386527Sache#include <sysexits.h> 396527Sache#include "collate.h" 4087012Sache#include "common.h" 416527Sache 426527Sacheextern FILE *yyin; 4387243Smarkmvoid yyerror(const char *fmt, ...) __printflike(1, 2); 4441568Sarchieint yyparse(void); 4541568Sarchieint yylex(void); 4687243Smarkmstatic void usage(void); 4787243Smarkmstatic void collate_print_tables(void); 486527Sache 4918950Sachechar map_name[FILENAME_MAX] = "."; 50102299Sachechar curr_chain[STR_LEN]; 5118950Sache 5218950Sachechar __collate_version[STR_LEN]; 5387012Sacheu_char charmap_table[UCHAR_MAX + 1][CHARMAP_SYMBOL_LEN]; 54101866Sache 55101866Sache#undef __collate_substitute_table 566527Sacheu_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; 57101866Sache#undef __collate_char_pri_table 586527Sachestruct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; 59102640Sachestruct __collate_st_chain_pri *__collate_chain_pri_table; 60101866Sache 61142686Sruint chain_index = 0; 626527Sacheint prim_pri = 1, sec_pri = 1; 636527Sache#ifdef COLLATE_DEBUG 646527Sacheint debug; 656527Sache#endif 666527Sache 6787243Smarkmconst char *out_file = "LC_COLLATE"; 686527Sache%} 696527Sache%union { 706527Sache u_char ch; 7187052Sache u_char str[BUFSIZE]; 726527Sache} 736527Sache%token SUBSTITUTE WITH ORDER RANGE 746527Sache%token <str> STRING 7518950Sache%token <str> DEFN 766527Sache%token <ch> CHAR 776527Sache%% 786527Sachecollate : statment_list 796527Sache; 806527Sachestatment_list : statment 816527Sache | statment_list '\n' statment 826527Sache; 836527Sachestatment : 846527Sache | charmap 856527Sache | substitute 866527Sache | order 876527Sache; 8818950Sachecharmap : DEFN CHAR { 8987015Sache if (strlen($1) + 1 > CHARMAP_SYMBOL_LEN) 9087015Sache yyerror("Charmap symbol name '%s' is too long", $1); 9118950Sache strcpy(charmap_table[$2], $1); 926527Sache} 936527Sache; 9443967Sachesubstitute : SUBSTITUTE CHAR WITH STRING { 9543967Sache if ($2 == '\0') 9643943Sache yyerror("NUL character can't be substituted"); 9743967Sache if (strchr($4, $2) != NULL) 9843967Sache yyerror("Char 0x%02x substitution is recursive", $2); 9987052Sache if (strlen($4) + 1 > STR_LEN) 10087052Sache yyerror("Char 0x%02x substitution is too long", $2); 10143967Sache strcpy(__collate_substitute_table[$2], $4); 1026527Sache} 1036527Sache; 1046527Sacheorder : ORDER order_list { 10519128Sache FILE *fp; 10643943Sache int ch, substed, ordered; 107102659Sache uint32_t u32; 1086527Sache 10943943Sache for (ch = 0; ch < UCHAR_MAX + 1; ch++) { 11043943Sache substed = (__collate_substitute_table[ch][0] != ch); 11143943Sache ordered = !!__collate_char_pri_table[ch].prim; 11243943Sache if (!ordered && !substed) 11343940Sache yyerror("Char 0x%02x not found", ch); 11443943Sache if (substed && ordered) 11543943Sache yyerror("Char 0x%02x can't be ordered since substituted", ch); 11643943Sache } 11719128Sache 118102659Sache if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, 119102659Sache sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) 120102659Sache yyerror("can't grow chain table"); 121142649Sru (void)memset(&__collate_chain_pri_table[chain_index], 0, 122142649Sru sizeof(__collate_chain_pri_table[0])); 123102659Sache chain_index++; 124102659Sache 125142686Sru#ifdef COLLATE_DEBUG 126142686Sru if (debug) 127142686Sru collate_print_tables(); 128142686Sru#endif 129102640Sache if ((fp = fopen(out_file, "w")) == NULL) 13018950Sache err(EX_UNAVAILABLE, "can't open destination file %s", 1316527Sache out_file); 1326527Sache 133142686Sru strcpy(__collate_version, COLLATE_VERSION1_2); 134102640Sache if (fwrite(__collate_version, sizeof(__collate_version), 1, fp) != 1) 135102640Sache err(EX_IOERR, 136102640Sache "IO error writting collate version to destination file %s", 13718950Sache out_file); 138102659Sache u32 = htonl(chain_index); 139102659Sache if (fwrite(&u32, sizeof(u32), 1, fp) != 1) 140102659Sache err(EX_IOERR, 141102659Sache "IO error writting chains number to destination file %s", 142102659Sache out_file); 143102640Sache if (fwrite(__collate_substitute_table, 144102640Sache sizeof(__collate_substitute_table), 1, fp) != 1) 145102640Sache err(EX_IOERR, 146102640Sache "IO error writting substitute table to destination file %s", 147102640Sache out_file); 148142686Sru for (ch = 0; ch < UCHAR_MAX + 1; ch++) { 149142686Sru __collate_char_pri_table[ch].prim = 150142686Sru htonl(__collate_char_pri_table[ch].prim); 151142686Sru __collate_char_pri_table[ch].sec = 152142686Sru htonl(__collate_char_pri_table[ch].sec); 153142686Sru } 154102640Sache if (fwrite(__collate_char_pri_table, 155102640Sache sizeof(__collate_char_pri_table), 1, fp) != 1) 156102640Sache err(EX_IOERR, 157102640Sache "IO error writting char table to destination file %s", 158102640Sache out_file); 159142686Sru for (ch = 0; ch < chain_index; ch++) { 160142686Sru __collate_chain_pri_table[ch].prim = 161142686Sru htonl(__collate_chain_pri_table[ch].prim); 162142686Sru __collate_chain_pri_table[ch].sec = 163142686Sru htonl(__collate_chain_pri_table[ch].sec); 164142686Sru } 165102640Sache if (fwrite(__collate_chain_pri_table, 166102659Sache sizeof(*__collate_chain_pri_table), chain_index, fp) != 167102942Sdwmalone (size_t)chain_index) 168102640Sache err(EX_IOERR, 169102640Sache "IO error writting chain table to destination file %s", 170102640Sache out_file); 171102640Sache if (fclose(fp) != 0) 172102640Sache err(EX_IOERR, "IO error closing destination file %s", 173102640Sache out_file); 1746527Sache exit(EX_OK); 1756527Sache} 1766527Sache; 1776527Sacheorder_list : item 1786527Sache | order_list ';' item 1796527Sache; 180102299Sachechain : CHAR CHAR { 181102299Sache curr_chain[0] = $1; 182102299Sache curr_chain[1] = $2; 183102299Sache if (curr_chain[0] == '\0' || curr_chain[1] == '\0') 184102299Sache yyerror("\\0 can't be chained"); 185102299Sache curr_chain[2] = '\0'; 186102299Sache} 187102299Sache | chain CHAR { 188102299Sache static char tb[2]; 189102299Sache 190102299Sache tb[0] = $2; 191102299Sache if (tb[0] == '\0') 192102299Sache yyerror("\\0 can't be chained"); 193102299Sache if (strlen(curr_chain) + 2 > STR_LEN) 194102299Sache yyerror("Chain '%s' grows too long", curr_chain); 195102299Sache (void)strcat(curr_chain, tb); 196102299Sache} 197102299Sache; 19819128Sacheitem : CHAR { 19919128Sache if (__collate_char_pri_table[$1].prim) 20019163Sache yyerror("Char 0x%02x duplicated", $1); 20119128Sache __collate_char_pri_table[$1].prim = prim_pri++; 20219128Sache} 203102299Sache | chain { 204102659Sache if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, 205102659Sache sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) 206102659Sache yyerror("can't grow chain table"); 207142649Sru (void)memset(&__collate_chain_pri_table[chain_index], 0, 208142649Sru sizeof(__collate_chain_pri_table[0])); 209102299Sache (void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain); 210102659Sache __collate_chain_pri_table[chain_index].prim = prim_pri++; 211102659Sache chain_index++; 2126527Sache} 2136527Sache | CHAR RANGE CHAR { 2146527Sache u_int i; 2156527Sache 2166527Sache if ($3 <= $1) 21718950Sache yyerror("Illegal range 0x%02x -- 0x%02x", $1, $3); 2186527Sache 21919128Sache for (i = $1; i <= $3; i++) { 22019128Sache if (__collate_char_pri_table[(u_char)i].prim) 22119163Sache yyerror("Char 0x%02x duplicated", (u_char)i); 2226527Sache __collate_char_pri_table[(u_char)i].prim = prim_pri++; 22319128Sache } 2246527Sache} 2256527Sache | '{' prim_order_list '}' { 2266527Sache prim_pri++; 2276527Sache} 2286527Sache | '(' sec_order_list ')' { 2296527Sache prim_pri++; 2306527Sache sec_pri = 1; 2316527Sache} 2326527Sache; 2336527Sacheprim_order_list : prim_sub_item 2346527Sache | prim_order_list ',' prim_sub_item 2356527Sache; 2366527Sachesec_order_list : sec_sub_item 2376527Sache | sec_order_list ',' sec_sub_item 2386527Sache; 2396527Sacheprim_sub_item : CHAR { 24019128Sache if (__collate_char_pri_table[$1].prim) 24119163Sache yyerror("Char 0x%02x duplicated", $1); 2426527Sache __collate_char_pri_table[$1].prim = prim_pri; 2436527Sache} 2446527Sache | CHAR RANGE CHAR { 2456527Sache u_int i; 2466527Sache 2476527Sache if ($3 <= $1) 24818950Sache yyerror("Illegal range 0x%02x -- 0x%02x", 24918950Sache $1, $3); 2506527Sache 25119128Sache for (i = $1; i <= $3; i++) { 25219128Sache if (__collate_char_pri_table[(u_char)i].prim) 25319163Sache yyerror("Char 0x%02x duplicated", (u_char)i); 2546527Sache __collate_char_pri_table[(u_char)i].prim = prim_pri; 25519128Sache } 2566527Sache} 257102299Sache | chain { 258102659Sache if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, 259102659Sache sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) 260102659Sache yyerror("can't grow chain table"); 261142649Sru (void)memset(&__collate_chain_pri_table[chain_index], 0, 262142649Sru sizeof(__collate_chain_pri_table[0])); 263102299Sache (void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain); 264102659Sache __collate_chain_pri_table[chain_index].prim = prim_pri; 265102659Sache chain_index++; 2666527Sache} 2676527Sache; 2686527Sachesec_sub_item : CHAR { 26919128Sache if (__collate_char_pri_table[$1].prim) 27019163Sache yyerror("Char 0x%02x duplicated", $1); 2716527Sache __collate_char_pri_table[$1].prim = prim_pri; 2726527Sache __collate_char_pri_table[$1].sec = sec_pri++; 2736527Sache} 2746527Sache | CHAR RANGE CHAR { 2756527Sache u_int i; 2766527Sache 2776527Sache if ($3 <= $1) 27818950Sache yyerror("Illegal range 0x%02x -- 0x%02x", 27918950Sache $1, $3); 2806527Sache 2816527Sache for (i = $1; i <= $3; i++) { 28219128Sache if (__collate_char_pri_table[(u_char)i].prim) 28319163Sache yyerror("Char 0x%02x duplicated", (u_char)i); 2846527Sache __collate_char_pri_table[(u_char)i].prim = prim_pri; 2856527Sache __collate_char_pri_table[(u_char)i].sec = sec_pri++; 2866527Sache } 2876527Sache} 288102299Sache | chain { 289102659Sache if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, 290102659Sache sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) 291102659Sache yyerror("can't grow chain table"); 292142649Sru (void)memset(&__collate_chain_pri_table[chain_index], 0, 293142649Sru sizeof(__collate_chain_pri_table[0])); 294102299Sache (void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain); 2956527Sache __collate_chain_pri_table[chain_index].prim = prim_pri; 296102659Sache __collate_chain_pri_table[chain_index].sec = sec_pri++; 297102659Sache chain_index++; 2986527Sache} 2996527Sache; 3006527Sache%% 30141568Sarchieint 302100816Sdwmalonemain(int ac, char **av) 3036527Sache{ 3046527Sache int ch; 3056527Sache 3066527Sache#ifdef COLLATE_DEBUG 307105237Scharnier while((ch = getopt(ac, av, ":do:I:")) != -1) { 3086527Sache#else 309105237Scharnier while((ch = getopt(ac, av, ":o:I:")) != -1) { 3106527Sache#endif 3116527Sache switch (ch) 3126527Sache { 3136527Sache#ifdef COLLATE_DEBUG 3146527Sache case 'd': 3156527Sache debug++; 3166527Sache break; 3176527Sache#endif 3186527Sache case 'o': 3196527Sache out_file = optarg; 3206527Sache break; 3216527Sache 32218950Sache case 'I': 32385026Ssobomax strlcpy(map_name, optarg, sizeof(map_name)); 32418950Sache break; 32518950Sache 3266527Sache default: 32726959Scharnier usage(); 3286527Sache } 3296527Sache } 3306527Sache ac -= optind; 3316527Sache av += optind; 332102640Sache if (ac > 0) { 333102640Sache if ((yyin = fopen(*av, "r")) == NULL) 3346527Sache err(EX_UNAVAILABLE, "can't open source file %s", *av); 3356527Sache } 336102640Sache for (ch = 0; ch <= UCHAR_MAX; ch++) 3376527Sache __collate_substitute_table[ch][0] = ch; 3386527Sache yyparse(); 3396527Sache return 0; 3406527Sache} 3416527Sache 34226959Scharnierstatic void 343100816Sdwmaloneusage(void) 34426959Scharnier{ 345146466Sru fprintf(stderr, "usage: colldef [-I map_dir] [-o out_file] [filename]\n"); 34627109Scharnier exit(EX_USAGE); 34726959Scharnier} 34826959Scharnier 34987243Smarkmvoid 35087243Smarkmyyerror(const char *fmt, ...) 3516527Sache{ 35218950Sache va_list ap; 35318950Sache char msg[128]; 35418950Sache 35518950Sache va_start(ap, fmt); 35669194Skris vsnprintf(msg, sizeof(msg), fmt, ap); 35718950Sache va_end(ap); 3586527Sache errx(EX_UNAVAILABLE, "%s near line %d", msg, line_no); 3596527Sache} 36019128Sache 36119128Sache#ifdef COLLATE_DEBUG 36287243Smarkmstatic void 36387243Smarkmcollate_print_tables(void) 36419128Sache{ 36519128Sache int i; 36619128Sache 36719128Sache printf("Substitute table:\n"); 36819128Sache for (i = 0; i < UCHAR_MAX + 1; i++) 36919128Sache if (i != *__collate_substitute_table[i]) 37019128Sache printf("\t'%c' --> \"%s\"\n", i, 37119128Sache __collate_substitute_table[i]); 37219128Sache printf("Chain priority table:\n"); 373142686Sru for (i = 0; i < chain_index - 1; i++) 374142686Sru printf("\t\"%s\" : %d %d\n", 375142686Sru __collate_chain_pri_table[i].str, 376142686Sru __collate_chain_pri_table[i].prim, 377142686Sru __collate_chain_pri_table[i].sec); 37819128Sache printf("Char priority table:\n"); 37919128Sache for (i = 0; i < UCHAR_MAX + 1; i++) 38019128Sache printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim, 38119128Sache __collate_char_pri_table[i].sec); 38219128Sache} 38319128Sache#endif 384