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: releng/11.0/usr.bin/colldef/parse.y 291127 2015-11-21 10:52:32Z bapt $"); 3187243Smarkm 32175038Simp#include <sys/types.h> 33102659Sache#include <arpa/inet.h> 346527Sache#include <err.h> 35291127Sbapt#include <limits.h> 3618950Sache#include <stdarg.h> 376527Sache#include <stdio.h> 38291127Sbapt#include <stdlib.h> 396527Sache#include <string.h> 4023706Speter#include <unistd.h> 416527Sache#include <sysexits.h> 4287012Sache#include "common.h" 436527Sache 446527Sacheextern FILE *yyin; 4587243Smarkmvoid yyerror(const char *fmt, ...) __printflike(1, 2); 4641568Sarchieint yyparse(void); 4741568Sarchieint yylex(void); 4887243Smarkmstatic void usage(void); 4987243Smarkmstatic void collate_print_tables(void); 506527Sache 51291115Sbapt#undef STR_LEN 52291115Sbapt#define STR_LEN 10 53291115Sbapt#undef TABLE_SIZE 54291115Sbapt#define TABLE_SIZE 100 55291115Sbapt#undef COLLATE_VERSION 56291115Sbapt#define COLLATE_VERSION "1.0\n" 57291115Sbapt#undef COLLATE_VERSION_2 58291115Sbapt#define COLLATE_VERSION1_2 "1.2\n" 59291115Sbapt 60291115Sbaptstruct __collate_st_char_pri { 61291115Sbapt int prim, sec; 62291115Sbapt}; 63291115Sbapt 64291115Sbaptstruct __collate_st_chain_pri { 65291115Sbapt u_char str[STR_LEN]; 66291115Sbapt int prim, sec; 67291115Sbapt}; 68291115Sbapt 6918950Sachechar map_name[FILENAME_MAX] = "."; 70102299Sachechar curr_chain[STR_LEN]; 7118950Sache 7218950Sachechar __collate_version[STR_LEN]; 7387012Sacheu_char charmap_table[UCHAR_MAX + 1][CHARMAP_SYMBOL_LEN]; 74101866Sache 75101866Sache#undef __collate_substitute_table 766527Sacheu_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; 77101866Sache#undef __collate_char_pri_table 786527Sachestruct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; 79102640Sachestruct __collate_st_chain_pri *__collate_chain_pri_table; 80101866Sache 81142686Sruint chain_index = 0; 826527Sacheint prim_pri = 1, sec_pri = 1; 836527Sache#ifdef COLLATE_DEBUG 846527Sacheint debug; 856527Sache#endif 866527Sache 8787243Smarkmconst char *out_file = "LC_COLLATE"; 886527Sache%} 896527Sache%union { 906527Sache u_char ch; 9187052Sache u_char str[BUFSIZE]; 926527Sache} 936527Sache%token SUBSTITUTE WITH ORDER RANGE 946527Sache%token <str> STRING 9518950Sache%token <str> DEFN 966527Sache%token <ch> CHAR 976527Sache%% 986527Sachecollate : statment_list 996527Sache; 1006527Sachestatment_list : statment 1016527Sache | statment_list '\n' statment 1026527Sache; 1036527Sachestatment : 1046527Sache | charmap 1056527Sache | substitute 1066527Sache | order 1076527Sache; 10818950Sachecharmap : DEFN CHAR { 10987015Sache if (strlen($1) + 1 > CHARMAP_SYMBOL_LEN) 11087015Sache yyerror("Charmap symbol name '%s' is too long", $1); 11118950Sache strcpy(charmap_table[$2], $1); 1126527Sache} 1136527Sache; 11443967Sachesubstitute : SUBSTITUTE CHAR WITH STRING { 11543967Sache if ($2 == '\0') 11643943Sache yyerror("NUL character can't be substituted"); 11743967Sache if (strchr($4, $2) != NULL) 11843967Sache yyerror("Char 0x%02x substitution is recursive", $2); 11987052Sache if (strlen($4) + 1 > STR_LEN) 12087052Sache yyerror("Char 0x%02x substitution is too long", $2); 12143967Sache strcpy(__collate_substitute_table[$2], $4); 1226527Sache} 1236527Sache; 1246527Sacheorder : ORDER order_list { 12519128Sache FILE *fp; 12643943Sache int ch, substed, ordered; 127102659Sache uint32_t u32; 1286527Sache 12943943Sache for (ch = 0; ch < UCHAR_MAX + 1; ch++) { 13043943Sache substed = (__collate_substitute_table[ch][0] != ch); 13143943Sache ordered = !!__collate_char_pri_table[ch].prim; 13243943Sache if (!ordered && !substed) 13343940Sache yyerror("Char 0x%02x not found", ch); 13443943Sache if (substed && ordered) 13543943Sache yyerror("Char 0x%02x can't be ordered since substituted", ch); 13643943Sache } 13719128Sache 138102659Sache if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, 139102659Sache sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) 140102659Sache yyerror("can't grow chain table"); 141142649Sru (void)memset(&__collate_chain_pri_table[chain_index], 0, 142142649Sru sizeof(__collate_chain_pri_table[0])); 143102659Sache chain_index++; 144102659Sache 145142686Sru#ifdef COLLATE_DEBUG 146142686Sru if (debug) 147142686Sru collate_print_tables(); 148142686Sru#endif 149102640Sache if ((fp = fopen(out_file, "w")) == NULL) 15018950Sache err(EX_UNAVAILABLE, "can't open destination file %s", 1516527Sache out_file); 1526527Sache 153142686Sru strcpy(__collate_version, COLLATE_VERSION1_2); 154102640Sache if (fwrite(__collate_version, sizeof(__collate_version), 1, fp) != 1) 155102640Sache err(EX_IOERR, 156289677Seadler "I/O error writing collate version to destination file %s", 15718950Sache out_file); 158102659Sache u32 = htonl(chain_index); 159102659Sache if (fwrite(&u32, sizeof(u32), 1, fp) != 1) 160102659Sache err(EX_IOERR, 161289677Seadler "I/O error writing chains number to destination file %s", 162102659Sache out_file); 163102640Sache if (fwrite(__collate_substitute_table, 164102640Sache sizeof(__collate_substitute_table), 1, fp) != 1) 165102640Sache err(EX_IOERR, 166289677Seadler "I/O error writing substitution table to destination file %s", 167102640Sache out_file); 168142686Sru for (ch = 0; ch < UCHAR_MAX + 1; ch++) { 169142686Sru __collate_char_pri_table[ch].prim = 170142686Sru htonl(__collate_char_pri_table[ch].prim); 171142686Sru __collate_char_pri_table[ch].sec = 172142686Sru htonl(__collate_char_pri_table[ch].sec); 173142686Sru } 174102640Sache if (fwrite(__collate_char_pri_table, 175102640Sache sizeof(__collate_char_pri_table), 1, fp) != 1) 176102640Sache err(EX_IOERR, 177289677Seadler "I/O error writing char table to destination file %s", 178102640Sache out_file); 179142686Sru for (ch = 0; ch < chain_index; ch++) { 180142686Sru __collate_chain_pri_table[ch].prim = 181142686Sru htonl(__collate_chain_pri_table[ch].prim); 182142686Sru __collate_chain_pri_table[ch].sec = 183142686Sru htonl(__collate_chain_pri_table[ch].sec); 184142686Sru } 185102640Sache if (fwrite(__collate_chain_pri_table, 186102659Sache sizeof(*__collate_chain_pri_table), chain_index, fp) != 187102942Sdwmalone (size_t)chain_index) 188102640Sache err(EX_IOERR, 189289677Seadler "I/O error writing chain table to destination file %s", 190102640Sache out_file); 191102640Sache if (fclose(fp) != 0) 192289677Seadler err(EX_IOERR, "I/O error closing destination file %s", 193102640Sache out_file); 1946527Sache exit(EX_OK); 1956527Sache} 1966527Sache; 1976527Sacheorder_list : item 1986527Sache | order_list ';' item 1996527Sache; 200102299Sachechain : CHAR CHAR { 201102299Sache curr_chain[0] = $1; 202102299Sache curr_chain[1] = $2; 203102299Sache if (curr_chain[0] == '\0' || curr_chain[1] == '\0') 204102299Sache yyerror("\\0 can't be chained"); 205102299Sache curr_chain[2] = '\0'; 206102299Sache} 207102299Sache | chain CHAR { 208102299Sache static char tb[2]; 209102299Sache 210102299Sache tb[0] = $2; 211102299Sache if (tb[0] == '\0') 212102299Sache yyerror("\\0 can't be chained"); 213102299Sache if (strlen(curr_chain) + 2 > STR_LEN) 214102299Sache yyerror("Chain '%s' grows too long", curr_chain); 215102299Sache (void)strcat(curr_chain, tb); 216102299Sache} 217102299Sache; 21819128Sacheitem : CHAR { 21919128Sache if (__collate_char_pri_table[$1].prim) 22019163Sache yyerror("Char 0x%02x duplicated", $1); 22119128Sache __collate_char_pri_table[$1].prim = prim_pri++; 22219128Sache} 223102299Sache | chain { 224102659Sache if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, 225102659Sache sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) 226102659Sache yyerror("can't grow chain table"); 227142649Sru (void)memset(&__collate_chain_pri_table[chain_index], 0, 228142649Sru sizeof(__collate_chain_pri_table[0])); 229102299Sache (void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain); 230102659Sache __collate_chain_pri_table[chain_index].prim = prim_pri++; 231102659Sache chain_index++; 2326527Sache} 2336527Sache | CHAR RANGE CHAR { 2346527Sache u_int i; 2356527Sache 2366527Sache if ($3 <= $1) 23718950Sache yyerror("Illegal range 0x%02x -- 0x%02x", $1, $3); 2386527Sache 23919128Sache for (i = $1; i <= $3; i++) { 24019128Sache if (__collate_char_pri_table[(u_char)i].prim) 24119163Sache yyerror("Char 0x%02x duplicated", (u_char)i); 2426527Sache __collate_char_pri_table[(u_char)i].prim = prim_pri++; 24319128Sache } 2446527Sache} 2456527Sache | '{' prim_order_list '}' { 2466527Sache prim_pri++; 2476527Sache} 2486527Sache | '(' sec_order_list ')' { 2496527Sache prim_pri++; 2506527Sache sec_pri = 1; 2516527Sache} 2526527Sache; 2536527Sacheprim_order_list : prim_sub_item 2546527Sache | prim_order_list ',' prim_sub_item 2556527Sache; 2566527Sachesec_order_list : sec_sub_item 2576527Sache | sec_order_list ',' sec_sub_item 2586527Sache; 2596527Sacheprim_sub_item : CHAR { 26019128Sache if (__collate_char_pri_table[$1].prim) 26119163Sache yyerror("Char 0x%02x duplicated", $1); 2626527Sache __collate_char_pri_table[$1].prim = prim_pri; 2636527Sache} 2646527Sache | CHAR RANGE CHAR { 2656527Sache u_int i; 2666527Sache 2676527Sache if ($3 <= $1) 26818950Sache yyerror("Illegal range 0x%02x -- 0x%02x", 26918950Sache $1, $3); 2706527Sache 27119128Sache for (i = $1; i <= $3; i++) { 27219128Sache if (__collate_char_pri_table[(u_char)i].prim) 27319163Sache yyerror("Char 0x%02x duplicated", (u_char)i); 2746527Sache __collate_char_pri_table[(u_char)i].prim = prim_pri; 27519128Sache } 2766527Sache} 277102299Sache | chain { 278102659Sache if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, 279102659Sache sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) 280102659Sache yyerror("can't grow chain table"); 281142649Sru (void)memset(&__collate_chain_pri_table[chain_index], 0, 282142649Sru sizeof(__collate_chain_pri_table[0])); 283102299Sache (void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain); 284102659Sache __collate_chain_pri_table[chain_index].prim = prim_pri; 285102659Sache chain_index++; 2866527Sache} 2876527Sache; 2886527Sachesec_sub_item : CHAR { 28919128Sache if (__collate_char_pri_table[$1].prim) 29019163Sache yyerror("Char 0x%02x duplicated", $1); 2916527Sache __collate_char_pri_table[$1].prim = prim_pri; 2926527Sache __collate_char_pri_table[$1].sec = sec_pri++; 2936527Sache} 2946527Sache | CHAR RANGE CHAR { 2956527Sache u_int i; 2966527Sache 2976527Sache if ($3 <= $1) 29818950Sache yyerror("Illegal range 0x%02x -- 0x%02x", 29918950Sache $1, $3); 3006527Sache 3016527Sache for (i = $1; i <= $3; i++) { 30219128Sache if (__collate_char_pri_table[(u_char)i].prim) 30319163Sache yyerror("Char 0x%02x duplicated", (u_char)i); 3046527Sache __collate_char_pri_table[(u_char)i].prim = prim_pri; 3056527Sache __collate_char_pri_table[(u_char)i].sec = sec_pri++; 3066527Sache } 3076527Sache} 308102299Sache | chain { 309102659Sache if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, 310102659Sache sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) 311102659Sache yyerror("can't grow chain table"); 312142649Sru (void)memset(&__collate_chain_pri_table[chain_index], 0, 313142649Sru sizeof(__collate_chain_pri_table[0])); 314102299Sache (void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain); 3156527Sache __collate_chain_pri_table[chain_index].prim = prim_pri; 316102659Sache __collate_chain_pri_table[chain_index].sec = sec_pri++; 317102659Sache chain_index++; 3186527Sache} 3196527Sache; 3206527Sache%% 32141568Sarchieint 322100816Sdwmalonemain(int ac, char **av) 3236527Sache{ 3246527Sache int ch; 3256527Sache 3266527Sache#ifdef COLLATE_DEBUG 327105237Scharnier while((ch = getopt(ac, av, ":do:I:")) != -1) { 3286527Sache#else 329105237Scharnier while((ch = getopt(ac, av, ":o:I:")) != -1) { 3306527Sache#endif 3316527Sache switch (ch) 3326527Sache { 3336527Sache#ifdef COLLATE_DEBUG 3346527Sache case 'd': 3356527Sache debug++; 3366527Sache break; 3376527Sache#endif 3386527Sache case 'o': 3396527Sache out_file = optarg; 3406527Sache break; 3416527Sache 34218950Sache case 'I': 34385026Ssobomax strlcpy(map_name, optarg, sizeof(map_name)); 34418950Sache break; 34518950Sache 3466527Sache default: 34726959Scharnier usage(); 3486527Sache } 3496527Sache } 3506527Sache ac -= optind; 3516527Sache av += optind; 352102640Sache if (ac > 0) { 353102640Sache if ((yyin = fopen(*av, "r")) == NULL) 3546527Sache err(EX_UNAVAILABLE, "can't open source file %s", *av); 3556527Sache } 356102640Sache for (ch = 0; ch <= UCHAR_MAX; ch++) 3576527Sache __collate_substitute_table[ch][0] = ch; 3586527Sache yyparse(); 3596527Sache return 0; 3606527Sache} 3616527Sache 36226959Scharnierstatic void 363100816Sdwmaloneusage(void) 36426959Scharnier{ 365146466Sru fprintf(stderr, "usage: colldef [-I map_dir] [-o out_file] [filename]\n"); 36627109Scharnier exit(EX_USAGE); 36726959Scharnier} 36826959Scharnier 36987243Smarkmvoid 37087243Smarkmyyerror(const char *fmt, ...) 3716527Sache{ 37218950Sache va_list ap; 37318950Sache char msg[128]; 37418950Sache 37518950Sache va_start(ap, fmt); 37669194Skris vsnprintf(msg, sizeof(msg), fmt, ap); 37718950Sache va_end(ap); 3786527Sache errx(EX_UNAVAILABLE, "%s near line %d", msg, line_no); 3796527Sache} 38019128Sache 38119128Sache#ifdef COLLATE_DEBUG 38287243Smarkmstatic void 38387243Smarkmcollate_print_tables(void) 38419128Sache{ 38519128Sache int i; 38619128Sache 38719128Sache printf("Substitute table:\n"); 38819128Sache for (i = 0; i < UCHAR_MAX + 1; i++) 38919128Sache if (i != *__collate_substitute_table[i]) 39019128Sache printf("\t'%c' --> \"%s\"\n", i, 39119128Sache __collate_substitute_table[i]); 39219128Sache printf("Chain priority table:\n"); 393142686Sru for (i = 0; i < chain_index - 1; i++) 394142686Sru printf("\t\"%s\" : %d %d\n", 395142686Sru __collate_chain_pri_table[i].str, 396142686Sru __collate_chain_pri_table[i].prim, 397142686Sru __collate_chain_pri_table[i].sec); 39819128Sache printf("Char priority table:\n"); 39919128Sache for (i = 0; i < UCHAR_MAX + 1; i++) 40019128Sache printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim, 40119128Sache __collate_char_pri_table[i].sec); 40219128Sache} 40319128Sache#endif 404