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