1 %{ 2 /*- 3 * Copyright (c) 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Paul Borman at Krystal Technologies. 8 * 9 * %sccs.include.redist.c% 10 */ 11 12 #ifndef lint 13 static char sccsid[] = "@(#)yacc.y 8.1 (Berkeley) 06/06/93"; 14 #endif /* not lint */ 15 16 #include <ctype.h> 17 #include <rune.h> 18 #include <stddef.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 22 #include "ldef.h" 23 24 char *locale_file = "<stdout>"; 25 26 rune_map maplower = { 0, }; 27 rune_map mapupper = { 0, }; 28 rune_map types = { 0, }; 29 30 _RuneLocale new_locale = { 0, }; 31 32 void set_map __P((rune_map *, rune_list *, u_long)); 33 void set_digitmap __P((rune_map *, rune_list *)); 34 void add_map __P((rune_map *, rune_list *, u_long)); 35 %} 36 37 %union { 38 rune_t rune; 39 int i; 40 char *str; 41 42 rune_list *list; 43 } 44 45 %token <rune> RUNE 46 %token LBRK 47 %token RBRK 48 %token THRU 49 %token MAPLOWER 50 %token MAPUPPER 51 %token DIGITMAP 52 %token <i> LIST 53 %token <str> VARIABLE 54 %token ENCODING 55 %token INVALID 56 %token <str> STRING 57 58 %type <list> list 59 %type <list> map 60 61 62 %% 63 64 locale : /* empty */ 65 | table 66 { dump_tables(); } 67 ; 68 69 table : entry 70 | table entry 71 ; 72 73 entry : ENCODING STRING 74 { strncpy(new_locale.encoding, $2, sizeof(new_locale.encoding)); } 75 | VARIABLE 76 { new_locale.variable_len = strlen($1) + 1; 77 new_locale.variable = malloc(new_locale.variable_len); 78 strcpy((char *)new_locale.variable, $1); 79 } 80 | INVALID RUNE 81 { new_locale.invalid_rune = $2; } 82 | LIST list 83 { set_map(&types, $2, $1); } 84 | MAPLOWER map 85 { set_map(&maplower, $2, 0); } 86 | MAPUPPER map 87 { set_map(&mapupper, $2, 0); } 88 | DIGITMAP map 89 { set_digitmap(&types, $2); } 90 ; 91 92 list : RUNE 93 { 94 $$ = (rune_list *)malloc(sizeof(rune_list)); 95 $$->min = $1; 96 $$->max = $1; 97 $$->next = 0; 98 } 99 | RUNE THRU RUNE 100 { 101 $$ = (rune_list *)malloc(sizeof(rune_list)); 102 $$->min = $1; 103 $$->max = $3; 104 $$->next = 0; 105 } 106 | list RUNE 107 { 108 $$ = (rune_list *)malloc(sizeof(rune_list)); 109 $$->min = $2; 110 $$->max = $2; 111 $$->next = $1; 112 } 113 | list RUNE THRU RUNE 114 { 115 $$ = (rune_list *)malloc(sizeof(rune_list)); 116 $$->min = $2; 117 $$->max = $4; 118 $$->next = $1; 119 } 120 ; 121 122 map : LBRK RUNE RUNE RBRK 123 { 124 $$ = (rune_list *)malloc(sizeof(rune_list)); 125 $$->min = $2; 126 $$->max = $2; 127 $$->map = $3; 128 $$->next = 0; 129 } 130 | map LBRK RUNE RUNE RBRK 131 { 132 $$ = (rune_list *)malloc(sizeof(rune_list)); 133 $$->min = $3; 134 $$->max = $3; 135 $$->map = $4; 136 $$->next = $1; 137 } 138 | LBRK RUNE THRU RUNE ':' RUNE RBRK 139 { 140 $$ = (rune_list *)malloc(sizeof(rune_list)); 141 $$->min = $2; 142 $$->max = $4; 143 $$->map = $6; 144 $$->next = 0; 145 } 146 | map LBRK RUNE THRU RUNE ':' RUNE RBRK 147 { 148 $$ = (rune_list *)malloc(sizeof(rune_list)); 149 $$->min = $3; 150 $$->max = $5; 151 $$->map = $7; 152 $$->next = $1; 153 } 154 ; 155 %% 156 157 int debug = 0; 158 FILE *fp = stdout; 159 160 main(ac, av) 161 int ac; 162 char *av[]; 163 { 164 int x; 165 166 extern char *optarg; 167 extern int optind; 168 169 while ((x = getopt(ac, av, "do:")) != EOF) { 170 switch(x) { 171 case 'd': 172 debug = 1; 173 break; 174 case 'o': 175 locale_file = optarg; 176 if ((fp = fopen(locale_file, "w")) == 0) { 177 perror(locale_file); 178 exit(1); 179 } 180 break; 181 default: 182 usage: 183 fprintf(stderr, "Usage: mklocale [-d] [-o output] [source]\n"); 184 exit(1); 185 } 186 } 187 188 switch (ac - optind) { 189 case 0: 190 break; 191 case 1: 192 if (freopen(av[optind], "r", stdin) == 0) { 193 perror(av[optind]); 194 exit(1); 195 } 196 break; 197 default: 198 goto usage; 199 } 200 for (x = 0; x < _CACHED_RUNES; ++x) { 201 mapupper.map[x] = x; 202 maplower.map[x] = x; 203 } 204 new_locale.invalid_rune = _INVALID_RUNE; 205 memcpy(new_locale.magic, _RUNE_MAGIC_1, sizeof(new_locale.magic)); 206 207 yyparse(); 208 } 209 210 yyerror(s) 211 char *s; 212 { 213 fprintf(stderr, "%s\n", s); 214 } 215 216 void * 217 xmalloc(sz) 218 unsigned int sz; 219 { 220 void *r = malloc(sz); 221 if (!r) { 222 perror("xmalloc"); 223 abort(); 224 } 225 return(r); 226 } 227 228 u_long * 229 xlalloc(sz) 230 unsigned int sz; 231 { 232 u_long *r = (u_long *)malloc(sz * sizeof(u_long)); 233 if (!r) { 234 perror("xlalloc"); 235 abort(); 236 } 237 return(r); 238 } 239 240 u_long * 241 xrelalloc(old, sz) 242 u_long *old; 243 unsigned int sz; 244 { 245 u_long *r = (u_long *)realloc((char *)old, sz * sizeof(u_long)); 246 if (!r) { 247 perror("xrelalloc"); 248 abort(); 249 } 250 return(r); 251 } 252 253 void 254 set_map(map, list, flag) 255 rune_map *map; 256 rune_list *list; 257 u_long flag; 258 { 259 while (list) { 260 rune_list *nlist = list->next; 261 add_map(map, list, flag); 262 list = nlist; 263 } 264 } 265 266 void 267 set_digitmap(map, list) 268 rune_map *map; 269 rune_list *list; 270 { 271 rune_t i; 272 273 while (list) { 274 rune_list *nlist = list->next; 275 for (i = list->min; i <= list->max; ++i) { 276 if (list->map + (i - list->min)) { 277 rune_list *tmp = (rune_list *)xmalloc(sizeof(rune_list)); 278 tmp->min = i; 279 tmp->max = i; 280 add_map(map, tmp, list->map + (i - list->min)); 281 } 282 } 283 free(list); 284 list = nlist; 285 } 286 } 287 288 void 289 add_map(map, list, flag) 290 rune_map *map; 291 rune_list *list; 292 u_long flag; 293 { 294 rune_t i; 295 rune_list *lr = 0; 296 rune_list *r; 297 rune_t run; 298 299 while (list->min < _CACHED_RUNES && list->min <= list->max) { 300 if (flag) 301 map->map[list->min++] |= flag; 302 else 303 map->map[list->min++] = list->map++; 304 } 305 306 if (list->min > list->max) { 307 free(list); 308 return; 309 } 310 311 run = list->max - list->min + 1; 312 313 if (!(r = map->root) || (list->max < r->min - 1) 314 || (!flag && list->max == r->min - 1)) { 315 if (flag) { 316 list->types = xlalloc(run); 317 for (i = 0; i < run; ++i) 318 list->types[i] = flag; 319 } 320 list->next = map->root; 321 map->root = list; 322 return; 323 } 324 325 for (r = map->root; r && r->max + 1 < list->min; r = r->next) 326 lr = r; 327 328 if (!r) { 329 /* 330 * We are off the end. 331 */ 332 if (flag) { 333 list->types = xlalloc(run); 334 for (i = 0; i < run; ++i) 335 list->types[i] = flag; 336 } 337 list->next = 0; 338 lr->next = list; 339 return; 340 } 341 342 if (list->max < r->min - 1) { 343 /* 344 * We come before this range and we do not intersect it. 345 * We are not before the root node, it was checked before the loop 346 */ 347 if (flag) { 348 list->types = xlalloc(run); 349 for (i = 0; i < run; ++i) 350 list->types[i] = flag; 351 } 352 list->next = lr->next; 353 lr->next = list; 354 return; 355 } 356 357 /* 358 * At this point we have found that we at least intersect with 359 * the range pointed to by `r', we might intersect with one or 360 * more ranges beyond `r' as well. 361 */ 362 363 if (!flag && list->map - list->min != r->map - r->min) { 364 /* 365 * There are only two cases when we are doing case maps and 366 * our maps needn't have the same offset. When we are adjoining 367 * but not intersecting. 368 */ 369 if (list->max + 1 == r->min) { 370 lr->next = list; 371 list->next = r; 372 return; 373 } 374 if (list->min - 1 == r->max) { 375 list->next = r->next; 376 r->next = list; 377 return; 378 } 379 fprintf(stderr, "Error: conflicting map entries\n"); 380 exit(1); 381 } 382 383 if (list->min >= r->min && list->max <= r->max) { 384 /* 385 * Subset case. 386 */ 387 388 if (flag) { 389 for (i = list->min; i <= list->max; ++i) 390 r->types[i - r->min] |= flag; 391 } 392 free(list); 393 return; 394 } 395 if (list->min <= r->min && list->max >= r->max) { 396 /* 397 * Superset case. Make him big enough to hold us. 398 * We might need to merge with the guy after him. 399 */ 400 if (flag) { 401 list->types = xlalloc(list->max - list->min + 1); 402 403 for (i = list->min; i <= list->max; ++i) 404 list->types[i - list->min] = flag; 405 406 for (i = r->min; i <= r->max; ++i) 407 list->types[i - list->min] |= r->types[i - r->min]; 408 409 free(r->types); 410 r->types = list->types; 411 } else { 412 r->map = list->map; 413 } 414 r->min = list->min; 415 r->max = list->max; 416 free(list); 417 } else if (list->min < r->min) { 418 /* 419 * Our tail intersects his head. 420 */ 421 if (flag) { 422 list->types = xlalloc(r->max - list->min + 1); 423 424 for (i = r->min; i <= r->max; ++i) 425 list->types[i - list->min] = r->types[i - r->min]; 426 427 for (i = list->min; i < r->min; ++i) 428 list->types[i - list->min] = flag; 429 430 for (i = r->min; i <= list->max; ++i) 431 list->types[i - list->min] |= flag; 432 433 free(r->types); 434 r->types = list->types; 435 } else { 436 r->map = list->map; 437 } 438 r->min = list->min; 439 free(list); 440 return; 441 } else { 442 /* 443 * Our head intersects his tail. 444 * We might need to merge with the guy after him. 445 */ 446 if (flag) { 447 r->types = xrelalloc(r->types, list->max - r->min + 1); 448 449 for (i = list->min; i <= r->max; ++i) 450 r->types[i - r->min] |= flag; 451 452 for (i = r->max+1; i <= list->max; ++i) 453 r->types[i - r->min] = flag; 454 } 455 r->max = r->max; 456 free(list); 457 } 458 459 /* 460 * Okay, check to see if we grew into the next guy(s) 461 */ 462 while ((lr = r->next) && r->max >= lr->min) { 463 if (flag) { 464 if (r->max >= lr->max) { 465 /* 466 * Good, we consumed all of him. 467 */ 468 for (i = lr->min; i <= lr->max; ++i) 469 r->types[i - r->min] |= lr->types[i - lr->min]; 470 } else { 471 /* 472 * "append" him on to the end of us. 473 */ 474 r->types = xrelalloc(r->types, lr->max - r->min + 1); 475 476 for (i = lr->min; i <= r->max; ++i) 477 r->types[i - r->min] |= lr->types[i - lr->min]; 478 479 for (i = r->max+1; i <= lr->max; ++i) 480 r->types[i - r->min] = lr->types[i - lr->min]; 481 482 r->max = lr->max; 483 } 484 } else { 485 if (lr->max > r->max) 486 r->max = lr->max; 487 } 488 489 r->next = lr->next; 490 491 if (flag) 492 free(lr->types); 493 free(lr); 494 } 495 } 496 497 void 498 dump_tables() 499 { 500 int x; 501 rune_list *list; 502 503 /* 504 * See if we can compress some of the istype arrays 505 */ 506 for(list = types.root; list; list = list->next) { 507 list->map = list->types[0]; 508 for (x = 1; x < list->max - list->min + 1; ++x) { 509 if (list->types[x] != list->map) { 510 list->map = 0; 511 break; 512 } 513 } 514 } 515 516 new_locale.invalid_rune = htonl(new_locale.invalid_rune); 517 518 /* 519 * Fill in our tables. Do this in network order so that 520 * diverse machines have a chance of sharing data. 521 * (Machines like Crays cannot share with little machines due to 522 * word size. Sigh. We tried.) 523 */ 524 for (x = 0; x < _CACHED_RUNES; ++x) { 525 new_locale.runetype[x] = htonl(types.map[x]); 526 new_locale.maplower[x] = htonl(maplower.map[x]); 527 new_locale.mapupper[x] = htonl(mapupper.map[x]); 528 } 529 530 /* 531 * Count up how many ranges we will need for each of the extents. 532 */ 533 list = types.root; 534 535 while (list) { 536 new_locale.runetype_ext.nranges++; 537 list = list->next; 538 } 539 new_locale.runetype_ext.nranges = htonl(new_locale.runetype_ext.nranges); 540 541 list = maplower.root; 542 543 while (list) { 544 new_locale.maplower_ext.nranges++; 545 list = list->next; 546 } 547 new_locale.maplower_ext.nranges = htonl(new_locale.maplower_ext.nranges); 548 549 list = mapupper.root; 550 551 while (list) { 552 new_locale.mapupper_ext.nranges++; 553 list = list->next; 554 } 555 new_locale.mapupper_ext.nranges = htonl(new_locale.mapupper_ext.nranges); 556 557 new_locale.variable_len = htonl(new_locale.variable_len); 558 559 /* 560 * Okay, we are now ready to write the new locale file. 561 */ 562 563 /* 564 * PART 1: The _RuneLocale structure 565 */ 566 if (fwrite((char *)&new_locale, sizeof(new_locale), 1, fp) != 1) { 567 perror(locale_file); 568 exit(1); 569 } 570 /* 571 * PART 2: The runetype_ext structures (not the actual tables) 572 */ 573 list = types.root; 574 575 while (list) { 576 _RuneEntry re; 577 578 re.min = htonl(list->min); 579 re.max = htonl(list->max); 580 re.map = htonl(list->map); 581 582 if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { 583 perror(locale_file); 584 exit(1); 585 } 586 587 list = list->next; 588 } 589 /* 590 * PART 3: The maplower_ext structures 591 */ 592 list = maplower.root; 593 594 while (list) { 595 _RuneEntry re; 596 597 re.min = htonl(list->min); 598 re.max = htonl(list->max); 599 re.map = htonl(list->map); 600 601 if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { 602 perror(locale_file); 603 exit(1); 604 } 605 606 list = list->next; 607 } 608 /* 609 * PART 4: The mapupper_ext structures 610 */ 611 list = mapupper.root; 612 613 while (list) { 614 _RuneEntry re; 615 616 re.min = htonl(list->min); 617 re.max = htonl(list->max); 618 re.map = htonl(list->map); 619 620 if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { 621 perror(locale_file); 622 exit(1); 623 } 624 625 list = list->next; 626 } 627 /* 628 * PART 5: The runetype_ext tables 629 */ 630 list = types.root; 631 632 while (list) { 633 for (x = 0; x < list->max - list->min + 1; ++x) 634 list->types[x] = htonl(list->types[x]); 635 636 if (!list->map) { 637 if (fwrite((char *)&list->types, 638 (list->max - list->min + 1)*sizeof(u_long), 1, fp) != 1) { 639 perror(locale_file); 640 exit(1); 641 } 642 } 643 list = list->next; 644 } 645 /* 646 * PART 5: And finally the variable data 647 */ 648 if (fwrite((char *)new_locale.variable, 649 ntohl(new_locale.variable_len), 1, fp) != 1) { 650 perror(locale_file); 651 exit(1); 652 } 653 fclose(fp); 654 655 if (!debug) 656 return; 657 658 if (new_locale.encoding[0]) 659 fprintf(stderr, "ENCODING %s\n", new_locale.encoding); 660 if (new_locale.variable) 661 fprintf(stderr, "VARIABLE %s\n", new_locale.variable); 662 663 fprintf(stderr, "\nMAPLOWER:\n\n"); 664 665 for (x = 0; x < _CACHED_RUNES; ++x) { 666 if (isprint(maplower.map[x])) 667 fprintf(stderr, " '%c'", maplower.map[x]); 668 else if (maplower.map[x]) 669 fprintf(stderr, "%04x", maplower.map[x]); 670 else 671 fprintf(stderr, "%4x", 0); 672 if ((x & 0xf) == 0xf) 673 fprintf(stderr, "\n"); 674 else 675 fprintf(stderr, " "); 676 } 677 fprintf(stderr, "\n"); 678 679 for (list = maplower.root; list; list = list->next) 680 fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map); 681 682 fprintf(stderr, "\nMAPUPPER:\n\n"); 683 684 for (x = 0; x < _CACHED_RUNES; ++x) { 685 if (isprint(mapupper.map[x])) 686 fprintf(stderr, " '%c'", mapupper.map[x]); 687 else if (mapupper.map[x]) 688 fprintf(stderr, "%04x", mapupper.map[x]); 689 else 690 fprintf(stderr, "%4x", 0); 691 if ((x & 0xf) == 0xf) 692 fprintf(stderr, "\n"); 693 else 694 fprintf(stderr, " "); 695 } 696 fprintf(stderr, "\n"); 697 698 for (list = mapupper.root; list; list = list->next) 699 fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map); 700 701 702 fprintf(stderr, "\nTYPES:\n\n"); 703 704 for (x = 0; x < _CACHED_RUNES; ++x) { 705 u_long r = types.map[x]; 706 707 if (r) { 708 if (isprint(x)) 709 fprintf(stderr, " '%c': %2d", x, r & 0xff); 710 else 711 fprintf(stderr, "%04x: %2d", x, r & 0xff); 712 713 fprintf(stderr, " %4s", (r & _A) ? "alph" : ""); 714 fprintf(stderr, " %4s", (r & _C) ? "ctrl" : ""); 715 fprintf(stderr, " %4s", (r & _D) ? "dig" : ""); 716 fprintf(stderr, " %4s", (r & _G) ? "graf" : ""); 717 fprintf(stderr, " %4s", (r & _L) ? "low" : ""); 718 fprintf(stderr, " %4s", (r & _P) ? "punc" : ""); 719 fprintf(stderr, " %4s", (r & _S) ? "spac" : ""); 720 fprintf(stderr, " %4s", (r & _U) ? "upp" : ""); 721 fprintf(stderr, " %4s", (r & _X) ? "xdig" : ""); 722 fprintf(stderr, " %4s", (r & _B) ? "blnk" : ""); 723 fprintf(stderr, " %4s", (r & _R) ? "prnt" : ""); 724 fprintf(stderr, " %4s", (r & _I) ? "ideo" : ""); 725 fprintf(stderr, " %4s", (r & _T) ? "spec" : ""); 726 fprintf(stderr, " %4s", (r & _Q) ? "phon" : ""); 727 fprintf(stderr, "\n"); 728 } 729 } 730 731 for (list = types.root; list; list = list->next) { 732 if (list->map && list->min + 3 < list->max) { 733 u_long r = list->map; 734 735 fprintf(stderr, "%04x: %2d", list->min, r & 0xff); 736 737 fprintf(stderr, " %4s", (r & _A) ? "alph" : ""); 738 fprintf(stderr, " %4s", (r & _C) ? "ctrl" : ""); 739 fprintf(stderr, " %4s", (r & _D) ? "dig" : ""); 740 fprintf(stderr, " %4s", (r & _G) ? "graf" : ""); 741 fprintf(stderr, " %4s", (r & _L) ? "low" : ""); 742 fprintf(stderr, " %4s", (r & _P) ? "punc" : ""); 743 fprintf(stderr, " %4s", (r & _S) ? "spac" : ""); 744 fprintf(stderr, " %4s", (r & _U) ? "upp" : ""); 745 fprintf(stderr, " %4s", (r & _X) ? "xdig" : ""); 746 fprintf(stderr, " %4s", (r & _B) ? "blnk" : ""); 747 fprintf(stderr, " %4s", (r & _R) ? "prnt" : ""); 748 fprintf(stderr, " %4s", (r & _I) ? "ideo" : ""); 749 fprintf(stderr, " %4s", (r & _T) ? "spec" : ""); 750 fprintf(stderr, " %4s", (r & _Q) ? "phon" : ""); 751 fprintf(stderr, "\n...\n"); 752 753 fprintf(stderr, "%04x: %2d", list->max, r & 0xff); 754 755 fprintf(stderr, " %4s", (r & _A) ? "alph" : ""); 756 fprintf(stderr, " %4s", (r & _C) ? "ctrl" : ""); 757 fprintf(stderr, " %4s", (r & _D) ? "dig" : ""); 758 fprintf(stderr, " %4s", (r & _G) ? "graf" : ""); 759 fprintf(stderr, " %4s", (r & _L) ? "low" : ""); 760 fprintf(stderr, " %4s", (r & _P) ? "punc" : ""); 761 fprintf(stderr, " %4s", (r & _S) ? "spac" : ""); 762 fprintf(stderr, " %4s", (r & _U) ? "upp" : ""); 763 fprintf(stderr, " %4s", (r & _X) ? "xdig" : ""); 764 fprintf(stderr, " %4s", (r & _B) ? "blnk" : ""); 765 fprintf(stderr, " %4s", (r & _R) ? "prnt" : ""); 766 fprintf(stderr, " %4s", (r & _I) ? "ideo" : ""); 767 fprintf(stderr, " %4s", (r & _T) ? "spec" : ""); 768 fprintf(stderr, " %4s", (r & _Q) ? "phon" : ""); 769 fprintf(stderr, "\n"); 770 } else 771 for (x = list->min; x <= list->max; ++x) { 772 u_long r = ntohl(list->types[x - list->min]); 773 774 if (r) { 775 fprintf(stderr, "%04x: %2d", x, r & 0xff); 776 777 fprintf(stderr, " %4s", (r & _A) ? "alph" : ""); 778 fprintf(stderr, " %4s", (r & _C) ? "ctrl" : ""); 779 fprintf(stderr, " %4s", (r & _D) ? "dig" : ""); 780 fprintf(stderr, " %4s", (r & _G) ? "graf" : ""); 781 fprintf(stderr, " %4s", (r & _L) ? "low" : ""); 782 fprintf(stderr, " %4s", (r & _P) ? "punc" : ""); 783 fprintf(stderr, " %4s", (r & _S) ? "spac" : ""); 784 fprintf(stderr, " %4s", (r & _U) ? "upp" : ""); 785 fprintf(stderr, " %4s", (r & _X) ? "xdig" : ""); 786 fprintf(stderr, " %4s", (r & _B) ? "blnk" : ""); 787 fprintf(stderr, " %4s", (r & _R) ? "prnt" : ""); 788 fprintf(stderr, " %4s", (r & _I) ? "ideo" : ""); 789 fprintf(stderr, " %4s", (r & _T) ? "spec" : ""); 790 fprintf(stderr, " %4s", (r & _Q) ? "phon" : ""); 791 fprintf(stderr, "\n"); 792 } 793 } 794 } 795 } 796