parse.y revision 94276
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: head/usr.bin/colldef/parse.y 94276 2002-04-09 11:39:05Z ru $"); 31 32#include <err.h> 33#include <stdarg.h> 34#include <stdio.h> 35#include <string.h> 36#include <stdlib.h> 37#include <unistd.h> 38#include <sysexits.h> 39#include "collate.h" 40#include "common.h" 41 42extern FILE *yyin; 43void yyerror(const char *fmt, ...) __printflike(1, 2); 44int yyparse(void); 45int yylex(void); 46static void usage(void); 47static void collate_print_tables(void); 48 49char map_name[FILENAME_MAX] = "."; 50 51char __collate_version[STR_LEN]; 52u_char charmap_table[UCHAR_MAX + 1][CHARMAP_SYMBOL_LEN]; 53u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; 54struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; 55struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE]; 56int chain_index; 57int prim_pri = 1, sec_pri = 1; 58#ifdef COLLATE_DEBUG 59int debug; 60#endif 61 62const char *out_file = "LC_COLLATE"; 63%} 64%union { 65 u_char ch; 66 u_char str[BUFSIZE]; 67} 68%token SUBSTITUTE WITH ORDER RANGE 69%token <str> STRING 70%token <str> CHAIN 71%token <str> DEFN 72%token <ch> CHAR 73%% 74collate : statment_list 75; 76statment_list : statment 77 | statment_list '\n' statment 78; 79statment : 80 | charmap 81 | substitute 82 | order 83; 84charmap : DEFN CHAR { 85 if (strlen($1) + 1 > CHARMAP_SYMBOL_LEN) 86 yyerror("Charmap symbol name '%s' is too long", $1); 87 strcpy(charmap_table[$2], $1); 88} 89; 90substitute : SUBSTITUTE CHAR WITH STRING { 91 if ($2 == '\0') 92 yyerror("NUL character can't be substituted"); 93 if (strchr($4, $2) != NULL) 94 yyerror("Char 0x%02x substitution is recursive", $2); 95 if (strlen($4) + 1 > STR_LEN) 96 yyerror("Char 0x%02x substitution is too long", $2); 97 strcpy(__collate_substitute_table[$2], $4); 98} 99; 100order : ORDER order_list { 101 FILE *fp; 102 int ch, substed, ordered; 103 104 for (ch = 0; ch < UCHAR_MAX + 1; ch++) { 105 substed = (__collate_substitute_table[ch][0] != ch); 106 ordered = !!__collate_char_pri_table[ch].prim; 107 if (!ordered && !substed) 108 yyerror("Char 0x%02x not found", ch); 109 if (substed && ordered) 110 yyerror("Char 0x%02x can't be ordered since substituted", ch); 111 } 112 113 fp = fopen(out_file, "w"); 114 if(!fp) 115 err(EX_UNAVAILABLE, "can't open destination file %s", 116 out_file); 117 118 strcpy(__collate_version, COLLATE_VERSION); 119 fwrite(__collate_version, sizeof(__collate_version), 1, fp); 120 fwrite(__collate_substitute_table, sizeof(__collate_substitute_table), 1, fp); 121 fwrite(__collate_char_pri_table, sizeof(__collate_char_pri_table), 1, fp); 122 fwrite(__collate_chain_pri_table, sizeof(__collate_chain_pri_table), 1, fp); 123 if (fflush(fp)) 124 err(EX_UNAVAILABLE, "IO error writting to destination file %s", 125 out_file); 126 fclose(fp); 127#ifdef COLLATE_DEBUG 128 if (debug) 129 collate_print_tables(); 130#endif 131 exit(EX_OK); 132} 133; 134order_list : item 135 | order_list ';' item 136; 137item : CHAR { 138 if (__collate_char_pri_table[$1].prim) 139 yyerror("Char 0x%02x duplicated", $1); 140 __collate_char_pri_table[$1].prim = prim_pri++; 141} 142 | CHAIN { 143 if (chain_index >= TABLE_SIZE - 1) 144 yyerror("__collate_chain_pri_table overflow"); 145 if (strlen($1) + 1 > STR_LEN) 146 yyerror("Chain %d is too long", chain_index); 147 strcpy(__collate_chain_pri_table[chain_index].str, $1); 148 __collate_chain_pri_table[chain_index++].prim = prim_pri++; 149} 150 | CHAR RANGE CHAR { 151 u_int i; 152 153 if ($3 <= $1) 154 yyerror("Illegal range 0x%02x -- 0x%02x", $1, $3); 155 156 for (i = $1; i <= $3; i++) { 157 if (__collate_char_pri_table[(u_char)i].prim) 158 yyerror("Char 0x%02x duplicated", (u_char)i); 159 __collate_char_pri_table[(u_char)i].prim = prim_pri++; 160 } 161} 162 | '{' prim_order_list '}' { 163 prim_pri++; 164} 165 | '(' sec_order_list ')' { 166 prim_pri++; 167 sec_pri = 1; 168} 169; 170prim_order_list : prim_sub_item 171 | prim_order_list ',' prim_sub_item 172; 173sec_order_list : sec_sub_item 174 | sec_order_list ',' sec_sub_item 175; 176prim_sub_item : CHAR { 177 if (__collate_char_pri_table[$1].prim) 178 yyerror("Char 0x%02x duplicated", $1); 179 __collate_char_pri_table[$1].prim = prim_pri; 180} 181 | CHAR RANGE CHAR { 182 u_int i; 183 184 if ($3 <= $1) 185 yyerror("Illegal range 0x%02x -- 0x%02x", 186 $1, $3); 187 188 for (i = $1; i <= $3; i++) { 189 if (__collate_char_pri_table[(u_char)i].prim) 190 yyerror("Char 0x%02x duplicated", (u_char)i); 191 __collate_char_pri_table[(u_char)i].prim = prim_pri; 192 } 193} 194 | CHAIN { 195 if (chain_index >= TABLE_SIZE - 1) 196 yyerror("__collate_chain_pri_table overflow"); 197 if (strlen($1) + 1 > STR_LEN) 198 yyerror("Chain %d is too long", chain_index); 199 strcpy(__collate_chain_pri_table[chain_index].str, $1); 200 __collate_chain_pri_table[chain_index++].prim = prim_pri; 201} 202; 203sec_sub_item : CHAR { 204 if (__collate_char_pri_table[$1].prim) 205 yyerror("Char 0x%02x duplicated", $1); 206 __collate_char_pri_table[$1].prim = prim_pri; 207 __collate_char_pri_table[$1].sec = sec_pri++; 208} 209 | CHAR RANGE CHAR { 210 u_int i; 211 212 if ($3 <= $1) 213 yyerror("Illegal range 0x%02x -- 0x%02x", 214 $1, $3); 215 216 for (i = $1; i <= $3; i++) { 217 if (__collate_char_pri_table[(u_char)i].prim) 218 yyerror("Char 0x%02x duplicated", (u_char)i); 219 __collate_char_pri_table[(u_char)i].prim = prim_pri; 220 __collate_char_pri_table[(u_char)i].sec = sec_pri++; 221 } 222} 223 | CHAIN { 224 if (chain_index >= TABLE_SIZE - 1) 225 yyerror("__collate_chain_pri_table overflow"); 226 if (strlen($1) + 1 > STR_LEN) 227 yyerror("Chain %d is too long", chain_index); 228 strcpy(__collate_chain_pri_table[chain_index].str, $1); 229 __collate_chain_pri_table[chain_index].prim = prim_pri; 230 __collate_chain_pri_table[chain_index++].sec = sec_pri++; 231} 232; 233%% 234int 235main(ac, av) 236 int ac; 237 char **av; 238{ 239 int ch; 240 241#ifdef COLLATE_DEBUG 242 while((ch = getopt(ac, av, ":do:I:")) != EOF) { 243#else 244 while((ch = getopt(ac, av, ":o:I:")) != EOF) { 245#endif 246 switch (ch) 247 { 248#ifdef COLLATE_DEBUG 249 case 'd': 250 debug++; 251 break; 252#endif 253 case 'o': 254 out_file = optarg; 255 break; 256 257 case 'I': 258 strlcpy(map_name, optarg, sizeof(map_name)); 259 break; 260 261 default: 262 usage(); 263 } 264 } 265 ac -= optind; 266 av += optind; 267 if(ac > 0) { 268 if((yyin = fopen(*av, "r")) == 0) 269 err(EX_UNAVAILABLE, "can't open source file %s", *av); 270 } 271 for(ch = 0; ch <= UCHAR_MAX; ch++) 272 __collate_substitute_table[ch][0] = ch; 273 yyparse(); 274 return 0; 275} 276 277static void 278usage() 279{ 280 fprintf(stderr, "usage: colldef [-o out_file] [-I map_dir] [filename]\n"); 281 exit(EX_USAGE); 282} 283 284void 285yyerror(const char *fmt, ...) 286{ 287 va_list ap; 288 char msg[128]; 289 290 va_start(ap, fmt); 291 vsnprintf(msg, sizeof(msg), fmt, ap); 292 va_end(ap); 293 errx(EX_UNAVAILABLE, "%s near line %d", msg, line_no); 294} 295 296#ifdef COLLATE_DEBUG 297static void 298collate_print_tables(void) 299{ 300 int i; 301 struct __collate_st_chain_pri *p2; 302 303 printf("Substitute table:\n"); 304 for (i = 0; i < UCHAR_MAX + 1; i++) 305 if (i != *__collate_substitute_table[i]) 306 printf("\t'%c' --> \"%s\"\n", i, 307 __collate_substitute_table[i]); 308 printf("Chain priority table:\n"); 309 for (p2 = __collate_chain_pri_table; p2->str[0]; p2++) 310 printf("\t\"%s\" : %d %d\n\n", p2->str, p2->prim, p2->sec); 311 printf("Char priority table:\n"); 312 for (i = 0; i < UCHAR_MAX + 1; i++) 313 printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim, 314 __collate_char_pri_table[i].sec); 315} 316#endif 317