parse.y revision 293290
1%{ 2/*- 3 * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua> 4 * at Electronni Visti IA, Kiev, Ukraine. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: stable/10/usr.bin/colldef/parse.y 293290 2016-01-07 00:40:51Z bdrewery $"); 31 32#include <sys/types.h> 33#include <arpa/inet.h> 34#include <err.h> 35#include <stdarg.h> 36#include <stdio.h> 37#include <string.h> 38#include <unistd.h> 39#include <sysexits.h> 40#include "collate.h" 41#include "common.h" 42 43extern FILE *yyin; 44void yyerror(const char *fmt, ...) __printflike(1, 2); 45int yyparse(void); 46int yylex(void); 47static void usage(void); 48static void collate_print_tables(void); 49 50char map_name[FILENAME_MAX] = "."; 51char curr_chain[STR_LEN]; 52 53char __collate_version[STR_LEN]; 54u_char charmap_table[UCHAR_MAX + 1][CHARMAP_SYMBOL_LEN]; 55 56#undef __collate_substitute_table 57u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; 58#undef __collate_char_pri_table 59struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; 60struct __collate_st_chain_pri *__collate_chain_pri_table; 61 62int chain_index = 0; 63int prim_pri = 1, sec_pri = 1; 64#ifdef COLLATE_DEBUG 65int debug; 66#endif 67 68const char *out_file = "LC_COLLATE"; 69%} 70%union { 71 u_char ch; 72 u_char str[BUFSIZE]; 73} 74%token SUBSTITUTE WITH ORDER RANGE 75%token <str> STRING 76%token <str> DEFN 77%token <ch> CHAR 78%% 79collate : statment_list 80; 81statment_list : statment 82 | statment_list '\n' statment 83; 84statment : 85 | charmap 86 | substitute 87 | order 88; 89charmap : DEFN CHAR { 90 if (strlen($1) + 1 > CHARMAP_SYMBOL_LEN) 91 yyerror("Charmap symbol name '%s' is too long", $1); 92 strcpy(charmap_table[$2], $1); 93} 94; 95substitute : SUBSTITUTE CHAR WITH STRING { 96 if ($2 == '\0') 97 yyerror("NUL character can't be substituted"); 98 if (strchr($4, $2) != NULL) 99 yyerror("Char 0x%02x substitution is recursive", $2); 100 if (strlen($4) + 1 > STR_LEN) 101 yyerror("Char 0x%02x substitution is too long", $2); 102 strcpy(__collate_substitute_table[$2], $4); 103} 104; 105order : ORDER order_list { 106 FILE *fp; 107 int ch, substed, ordered; 108 uint32_t u32; 109 110 for (ch = 0; ch < UCHAR_MAX + 1; ch++) { 111 substed = (__collate_substitute_table[ch][0] != ch); 112 ordered = !!__collate_char_pri_table[ch].prim; 113 if (!ordered && !substed) 114 yyerror("Char 0x%02x not found", ch); 115 if (substed && ordered) 116 yyerror("Char 0x%02x can't be ordered since substituted", ch); 117 } 118 119 if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, 120 sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) 121 yyerror("can't grow chain table"); 122 (void)memset(&__collate_chain_pri_table[chain_index], 0, 123 sizeof(__collate_chain_pri_table[0])); 124 chain_index++; 125 126#ifdef COLLATE_DEBUG 127 if (debug) 128 collate_print_tables(); 129#endif 130 if ((fp = fopen(out_file, "w")) == NULL) 131 err(EX_UNAVAILABLE, "can't open destination file %s", 132 out_file); 133 134 strcpy(__collate_version, COLLATE_VERSION1_2); 135 if (fwrite(__collate_version, sizeof(__collate_version), 1, fp) != 1) 136 err(EX_IOERR, 137 "I/O error writing collate version to destination file %s", 138 out_file); 139 u32 = htonl(chain_index); 140 if (fwrite(&u32, sizeof(u32), 1, fp) != 1) 141 err(EX_IOERR, 142 "I/O error writing chains number to destination file %s", 143 out_file); 144 if (fwrite(__collate_substitute_table, 145 sizeof(__collate_substitute_table), 1, fp) != 1) 146 err(EX_IOERR, 147 "I/O error writing substitution table to destination file %s", 148 out_file); 149 for (ch = 0; ch < UCHAR_MAX + 1; ch++) { 150 __collate_char_pri_table[ch].prim = 151 htonl(__collate_char_pri_table[ch].prim); 152 __collate_char_pri_table[ch].sec = 153 htonl(__collate_char_pri_table[ch].sec); 154 } 155 if (fwrite(__collate_char_pri_table, 156 sizeof(__collate_char_pri_table), 1, fp) != 1) 157 err(EX_IOERR, 158 "I/O error writing char table to destination file %s", 159 out_file); 160 for (ch = 0; ch < chain_index; ch++) { 161 __collate_chain_pri_table[ch].prim = 162 htonl(__collate_chain_pri_table[ch].prim); 163 __collate_chain_pri_table[ch].sec = 164 htonl(__collate_chain_pri_table[ch].sec); 165 } 166 if (fwrite(__collate_chain_pri_table, 167 sizeof(*__collate_chain_pri_table), chain_index, fp) != 168 (size_t)chain_index) 169 err(EX_IOERR, 170 "I/O error writing chain table to destination file %s", 171 out_file); 172 if (fclose(fp) != 0) 173 err(EX_IOERR, "I/O error closing destination file %s", 174 out_file); 175 exit(EX_OK); 176} 177; 178order_list : item 179 | order_list ';' item 180; 181chain : CHAR CHAR { 182 curr_chain[0] = $1; 183 curr_chain[1] = $2; 184 if (curr_chain[0] == '\0' || curr_chain[1] == '\0') 185 yyerror("\\0 can't be chained"); 186 curr_chain[2] = '\0'; 187} 188 | chain CHAR { 189 static char tb[2]; 190 191 tb[0] = $2; 192 if (tb[0] == '\0') 193 yyerror("\\0 can't be chained"); 194 if (strlen(curr_chain) + 2 > STR_LEN) 195 yyerror("Chain '%s' grows too long", curr_chain); 196 (void)strcat(curr_chain, tb); 197} 198; 199item : CHAR { 200 if (__collate_char_pri_table[$1].prim) 201 yyerror("Char 0x%02x duplicated", $1); 202 __collate_char_pri_table[$1].prim = prim_pri++; 203} 204 | chain { 205 if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, 206 sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) 207 yyerror("can't grow chain table"); 208 (void)memset(&__collate_chain_pri_table[chain_index], 0, 209 sizeof(__collate_chain_pri_table[0])); 210 (void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain); 211 __collate_chain_pri_table[chain_index].prim = prim_pri++; 212 chain_index++; 213} 214 | CHAR RANGE CHAR { 215 u_int i; 216 217 if ($3 <= $1) 218 yyerror("Illegal range 0x%02x -- 0x%02x", $1, $3); 219 220 for (i = $1; i <= $3; i++) { 221 if (__collate_char_pri_table[(u_char)i].prim) 222 yyerror("Char 0x%02x duplicated", (u_char)i); 223 __collate_char_pri_table[(u_char)i].prim = prim_pri++; 224 } 225} 226 | '{' prim_order_list '}' { 227 prim_pri++; 228} 229 | '(' sec_order_list ')' { 230 prim_pri++; 231 sec_pri = 1; 232} 233; 234prim_order_list : prim_sub_item 235 | prim_order_list ',' prim_sub_item 236; 237sec_order_list : sec_sub_item 238 | sec_order_list ',' sec_sub_item 239; 240prim_sub_item : CHAR { 241 if (__collate_char_pri_table[$1].prim) 242 yyerror("Char 0x%02x duplicated", $1); 243 __collate_char_pri_table[$1].prim = prim_pri; 244} 245 | CHAR RANGE CHAR { 246 u_int i; 247 248 if ($3 <= $1) 249 yyerror("Illegal range 0x%02x -- 0x%02x", 250 $1, $3); 251 252 for (i = $1; i <= $3; i++) { 253 if (__collate_char_pri_table[(u_char)i].prim) 254 yyerror("Char 0x%02x duplicated", (u_char)i); 255 __collate_char_pri_table[(u_char)i].prim = prim_pri; 256 } 257} 258 | chain { 259 if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, 260 sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) 261 yyerror("can't grow chain table"); 262 (void)memset(&__collate_chain_pri_table[chain_index], 0, 263 sizeof(__collate_chain_pri_table[0])); 264 (void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain); 265 __collate_chain_pri_table[chain_index].prim = prim_pri; 266 chain_index++; 267} 268; 269sec_sub_item : CHAR { 270 if (__collate_char_pri_table[$1].prim) 271 yyerror("Char 0x%02x duplicated", $1); 272 __collate_char_pri_table[$1].prim = prim_pri; 273 __collate_char_pri_table[$1].sec = sec_pri++; 274} 275 | CHAR RANGE CHAR { 276 u_int i; 277 278 if ($3 <= $1) 279 yyerror("Illegal range 0x%02x -- 0x%02x", 280 $1, $3); 281 282 for (i = $1; i <= $3; i++) { 283 if (__collate_char_pri_table[(u_char)i].prim) 284 yyerror("Char 0x%02x duplicated", (u_char)i); 285 __collate_char_pri_table[(u_char)i].prim = prim_pri; 286 __collate_char_pri_table[(u_char)i].sec = sec_pri++; 287 } 288} 289 | chain { 290 if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table, 291 sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL) 292 yyerror("can't grow chain table"); 293 (void)memset(&__collate_chain_pri_table[chain_index], 0, 294 sizeof(__collate_chain_pri_table[0])); 295 (void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain); 296 __collate_chain_pri_table[chain_index].prim = prim_pri; 297 __collate_chain_pri_table[chain_index].sec = sec_pri++; 298 chain_index++; 299} 300; 301%% 302int 303main(int ac, char **av) 304{ 305 int ch; 306 307#ifdef COLLATE_DEBUG 308 while((ch = getopt(ac, av, ":do:I:")) != -1) { 309#else 310 while((ch = getopt(ac, av, ":o:I:")) != -1) { 311#endif 312 switch (ch) 313 { 314#ifdef COLLATE_DEBUG 315 case 'd': 316 debug++; 317 break; 318#endif 319 case 'o': 320 out_file = optarg; 321 break; 322 323 case 'I': 324 strlcpy(map_name, optarg, sizeof(map_name)); 325 break; 326 327 default: 328 usage(); 329 } 330 } 331 ac -= optind; 332 av += optind; 333 if (ac > 0) { 334 if ((yyin = fopen(*av, "r")) == NULL) 335 err(EX_UNAVAILABLE, "can't open source file %s", *av); 336 } 337 for (ch = 0; ch <= UCHAR_MAX; ch++) 338 __collate_substitute_table[ch][0] = ch; 339 yyparse(); 340 return 0; 341} 342 343static void 344usage(void) 345{ 346 fprintf(stderr, "usage: colldef [-I map_dir] [-o out_file] [filename]\n"); 347 exit(EX_USAGE); 348} 349 350void 351yyerror(const char *fmt, ...) 352{ 353 va_list ap; 354 char msg[128]; 355 356 va_start(ap, fmt); 357 vsnprintf(msg, sizeof(msg), fmt, ap); 358 va_end(ap); 359 errx(EX_UNAVAILABLE, "%s near line %d", msg, line_no); 360} 361 362#ifdef COLLATE_DEBUG 363static void 364collate_print_tables(void) 365{ 366 int i; 367 368 printf("Substitute table:\n"); 369 for (i = 0; i < UCHAR_MAX + 1; i++) 370 if (i != *__collate_substitute_table[i]) 371 printf("\t'%c' --> \"%s\"\n", i, 372 __collate_substitute_table[i]); 373 printf("Chain priority table:\n"); 374 for (i = 0; i < chain_index - 1; i++) 375 printf("\t\"%s\" : %d %d\n", 376 __collate_chain_pri_table[i].str, 377 __collate_chain_pri_table[i].prim, 378 __collate_chain_pri_table[i].sec); 379 printf("Char priority table:\n"); 380 for (i = 0; i < UCHAR_MAX + 1; i++) 381 printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim, 382 __collate_char_pri_table[i].sec); 383} 384#endif 385