60 61static void *xmalloc(unsigned int sz); 62static uint32_t *xlalloc(unsigned int sz); 63void yyerror(const char *s); 64static uint32_t *xrelalloc(uint32_t *old, unsigned int sz); 65static void dump_tables(void); 66static void cleanout(void); 67 68const char *locale_file = "<stdout>"; 69 70rune_map maplower = { { 0 }, NULL }; 71rune_map mapupper = { { 0 }, NULL }; 72rune_map types = { { 0 }, NULL }; 73 74_FileRuneLocale new_locale = { "", "", {}, {}, {}, 0, 0, 0, 0 }; 75char *variable = NULL; 76 77void set_map(rune_map *, rune_list *, uint32_t); 78void set_digitmap(rune_map *, rune_list *); 79void add_map(rune_map *, rune_list *, uint32_t); 80static void usage(void); 81%} 82 83%union { 84 int32_t rune; 85 int i; 86 char *str; 87 88 rune_list *list; 89} 90 91%token <rune> RUNE 92%token LBRK 93%token RBRK 94%token THRU 95%token MAPLOWER 96%token MAPUPPER 97%token DIGITMAP 98%token <i> LIST 99%token <str> VARIABLE 100%token ENCODING 101%token INVALID 102%token <str> STRING 103 104%type <list> list 105%type <list> map 106 107 108%% 109 110locale : /* empty */ 111 | table 112 { dump_tables(); } 113 ; 114 115table : entry 116 | table entry 117 ; 118 119entry : ENCODING STRING 120 { if (strcmp($2, "NONE") && 121 strcmp($2, "UTF-8") && 122 strcmp($2, "EUC") && 123 strcmp($2, "GBK") && 124 strcmp($2, "GB18030") && 125 strcmp($2, "GB2312") && 126 strcmp($2, "BIG5") && 127 strcmp($2, "MSKanji")) 128 warnx("ENCODING %s is not supported by libc", $2); 129 strncpy(new_locale.encoding, $2, 130 sizeof(new_locale.encoding)); } 131 | VARIABLE 132 { new_locale.variable_len = strlen($1) + 1; 133 variable = xmalloc(new_locale.variable_len); 134 strcpy(variable, $1); 135 } 136 | INVALID RUNE 137 { warnx("the INVALID keyword is deprecated"); } 138 | LIST list 139 { set_map(&types, $2, $1); } 140 | MAPLOWER map 141 { set_map(&maplower, $2, 0); } 142 | MAPUPPER map 143 { set_map(&mapupper, $2, 0); } 144 | DIGITMAP map 145 { set_digitmap(&types, $2); } 146 ; 147 148list : RUNE 149 { 150 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 151 $$->min = $1; 152 $$->max = $1; 153 $$->next = 0; 154 } 155 | RUNE THRU RUNE 156 { 157 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 158 $$->min = $1; 159 $$->max = $3; 160 $$->next = 0; 161 } 162 | list RUNE 163 { 164 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 165 $$->min = $2; 166 $$->max = $2; 167 $$->next = $1; 168 } 169 | list RUNE THRU RUNE 170 { 171 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 172 $$->min = $2; 173 $$->max = $4; 174 $$->next = $1; 175 } 176 ; 177 178map : LBRK RUNE RUNE RBRK 179 { 180 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 181 $$->min = $2; 182 $$->max = $2; 183 $$->map = $3; 184 $$->next = 0; 185 } 186 | map LBRK RUNE RUNE RBRK 187 { 188 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 189 $$->min = $3; 190 $$->max = $3; 191 $$->map = $4; 192 $$->next = $1; 193 } 194 | LBRK RUNE THRU RUNE ':' RUNE RBRK 195 { 196 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 197 $$->min = $2; 198 $$->max = $4; 199 $$->map = $6; 200 $$->next = 0; 201 } 202 | map LBRK RUNE THRU RUNE ':' RUNE RBRK 203 { 204 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 205 $$->min = $3; 206 $$->max = $5; 207 $$->map = $7; 208 $$->next = $1; 209 } 210 ; 211%% 212 213int debug; 214FILE *fp; 215 216static void 217cleanout(void) 218{ 219 if (fp != NULL) 220 unlink(locale_file); 221} 222 223int 224main(int ac, char *av[]) 225{ 226 int x; 227 228 fp = stdout; 229 230 while ((x = getopt(ac, av, "do:")) != EOF) { 231 switch(x) { 232 case 'd': 233 debug = 1; 234 break; 235 case 'o': 236 locale_file = optarg; 237 if ((fp = fopen(locale_file, "w")) == 0) 238 err(1, "%s", locale_file); 239 atexit(cleanout); 240 break; 241 default: 242 usage(); 243 } 244 } 245 246 switch (ac - optind) { 247 case 0: 248 break; 249 case 1: 250 if (freopen(av[optind], "r", stdin) == 0) 251 err(1, "%s", av[optind]); 252 break; 253 default: 254 usage(); 255 } 256 for (x = 0; x < _CACHED_RUNES; ++x) { 257 mapupper.map[x] = x; 258 maplower.map[x] = x; 259 } 260 memcpy(new_locale.magic, _FILE_RUNE_MAGIC_1, sizeof(new_locale.magic)); 261 262 yyparse(); 263 264 return(0); 265} 266 267static void 268usage() 269{ 270 fprintf(stderr, "usage: mklocale [-d] [-o output] [source]\n"); 271 exit(1); 272} 273 274void 275yyerror(s) 276 const char *s; 277{ 278 fprintf(stderr, "%s\n", s); 279} 280 281static void * 282xmalloc(sz) 283 unsigned int sz; 284{ 285 void *r = malloc(sz); 286 if (!r) 287 errx(1, "xmalloc"); 288 return(r); 289} 290 291static uint32_t * 292xlalloc(sz) 293 unsigned int sz; 294{ 295 uint32_t *r = (uint32_t *)malloc(sz * sizeof(uint32_t)); 296 if (!r) 297 errx(1, "xlalloc"); 298 return(r); 299} 300 301static uint32_t * 302xrelalloc(old, sz) 303 uint32_t *old; 304 unsigned int sz; 305{ 306 uint32_t *r = (uint32_t *)realloc((char *)old, 307 sz * sizeof(uint32_t)); 308 if (!r) 309 errx(1, "xrelalloc"); 310 return(r); 311} 312 313void 314set_map(map, list, flag) 315 rune_map *map; 316 rune_list *list; 317 uint32_t flag; 318{ 319 while (list) { 320 rune_list *nlist = list->next; 321 add_map(map, list, flag); 322 list = nlist; 323 } 324} 325 326void 327set_digitmap(map, list) 328 rune_map *map; 329 rune_list *list; 330{ 331 int32_t i; 332 333 while (list) { 334 rune_list *nlist = list->next; 335 for (i = list->min; i <= list->max; ++i) { 336 if (list->map + (i - list->min)) { 337 rune_list *tmp = (rune_list *)xmalloc(sizeof(rune_list)); 338 tmp->min = i; 339 tmp->max = i; 340 add_map(map, tmp, list->map + (i - list->min)); 341 } 342 } 343 free(list); 344 list = nlist; 345 } 346} 347 348void 349add_map(map, list, flag) 350 rune_map *map; 351 rune_list *list; 352 uint32_t flag; 353{ 354 int32_t i; 355 rune_list *lr = 0; 356 rune_list *r; 357 int32_t run; 358 359 while (list->min < _CACHED_RUNES && list->min <= list->max) { 360 if (flag) 361 map->map[list->min++] |= flag; 362 else 363 map->map[list->min++] = list->map++; 364 } 365 366 if (list->min > list->max) { 367 free(list); 368 return; 369 } 370 371 run = list->max - list->min + 1; 372 373 if (!(r = map->root) || (list->max < r->min - 1) 374 || (!flag && list->max == r->min - 1)) { 375 if (flag) { 376 list->types = xlalloc(run); 377 for (i = 0; i < run; ++i) 378 list->types[i] = flag; 379 } 380 list->next = map->root; 381 map->root = list; 382 return; 383 } 384 385 for (r = map->root; r && r->max + 1 < list->min; r = r->next) 386 lr = r; 387 388 if (!r) { 389 /* 390 * We are off the end. 391 */ 392 if (flag) { 393 list->types = xlalloc(run); 394 for (i = 0; i < run; ++i) 395 list->types[i] = flag; 396 } 397 list->next = 0; 398 lr->next = list; 399 return; 400 } 401 402 if (list->max < r->min - 1) { 403 /* 404 * We come before this range and we do not intersect it. 405 * We are not before the root node, it was checked before the loop 406 */ 407 if (flag) { 408 list->types = xlalloc(run); 409 for (i = 0; i < run; ++i) 410 list->types[i] = flag; 411 } 412 list->next = lr->next; 413 lr->next = list; 414 return; 415 } 416 417 /* 418 * At this point we have found that we at least intersect with 419 * the range pointed to by `r', we might intersect with one or 420 * more ranges beyond `r' as well. 421 */ 422 423 if (!flag && list->map - list->min != r->map - r->min) { 424 /* 425 * There are only two cases when we are doing case maps and 426 * our maps needn't have the same offset. When we are adjoining 427 * but not intersecting. 428 */ 429 if (list->max + 1 == r->min) { 430 lr->next = list; 431 list->next = r; 432 return; 433 } 434 if (list->min - 1 == r->max) { 435 list->next = r->next; 436 r->next = list; 437 return; 438 } 439 errx(1, "error: conflicting map entries"); 440 } 441 442 if (list->min >= r->min && list->max <= r->max) { 443 /* 444 * Subset case. 445 */ 446 447 if (flag) { 448 for (i = list->min; i <= list->max; ++i) 449 r->types[i - r->min] |= flag; 450 } 451 free(list); 452 return; 453 } 454 if (list->min <= r->min && list->max >= r->max) { 455 /* 456 * Superset case. Make him big enough to hold us. 457 * We might need to merge with the guy after him. 458 */ 459 if (flag) { 460 list->types = xlalloc(list->max - list->min + 1); 461 462 for (i = list->min; i <= list->max; ++i) 463 list->types[i - list->min] = flag; 464 465 for (i = r->min; i <= r->max; ++i) 466 list->types[i - list->min] |= r->types[i - r->min]; 467 468 free(r->types); 469 r->types = list->types; 470 } else { 471 r->map = list->map; 472 } 473 r->min = list->min; 474 r->max = list->max; 475 free(list); 476 } else if (list->min < r->min) { 477 /* 478 * Our tail intersects his head. 479 */ 480 if (flag) { 481 list->types = xlalloc(r->max - list->min + 1); 482 483 for (i = r->min; i <= r->max; ++i) 484 list->types[i - list->min] = r->types[i - r->min]; 485 486 for (i = list->min; i < r->min; ++i) 487 list->types[i - list->min] = flag; 488 489 for (i = r->min; i <= list->max; ++i) 490 list->types[i - list->min] |= flag; 491 492 free(r->types); 493 r->types = list->types; 494 } else { 495 r->map = list->map; 496 } 497 r->min = list->min; 498 free(list); 499 return; 500 } else { 501 /* 502 * Our head intersects his tail. 503 * We might need to merge with the guy after him. 504 */ 505 if (flag) { 506 r->types = xrelalloc(r->types, list->max - r->min + 1); 507 508 for (i = list->min; i <= r->max; ++i) 509 r->types[i - r->min] |= flag; 510 511 for (i = r->max+1; i <= list->max; ++i) 512 r->types[i - r->min] = flag; 513 } 514 r->max = list->max; 515 free(list); 516 } 517 518 /* 519 * Okay, check to see if we grew into the next guy(s) 520 */ 521 while ((lr = r->next) && r->max >= lr->min) { 522 if (flag) { 523 if (r->max >= lr->max) { 524 /* 525 * Good, we consumed all of him. 526 */ 527 for (i = lr->min; i <= lr->max; ++i) 528 r->types[i - r->min] |= lr->types[i - lr->min]; 529 } else { 530 /* 531 * "append" him on to the end of us. 532 */ 533 r->types = xrelalloc(r->types, lr->max - r->min + 1); 534 535 for (i = lr->min; i <= r->max; ++i) 536 r->types[i - r->min] |= lr->types[i - lr->min]; 537 538 for (i = r->max+1; i <= lr->max; ++i) 539 r->types[i - r->min] = lr->types[i - lr->min]; 540 541 r->max = lr->max; 542 } 543 } else { 544 if (lr->max > r->max) 545 r->max = lr->max; 546 } 547 548 r->next = lr->next; 549 550 if (flag) 551 free(lr->types); 552 free(lr); 553 } 554} 555 556static void 557dump_tables() 558{ 559 int x, first_d, curr_d; 560 rune_list *list; 561 562 /* 563 * See if we can compress some of the istype arrays 564 */ 565 for(list = types.root; list; list = list->next) { 566 list->map = list->types[0]; 567 for (x = 1; x < list->max - list->min + 1; ++x) { 568 if ((int32_t)list->types[x] != list->map) { 569 list->map = 0; 570 break; 571 } 572 } 573 } 574 575 first_d = curr_d = -1; 576 for (x = 0; x < _CACHED_RUNES; ++x) { 577 uint32_t r = types.map[x]; 578 579 if (r & _CTYPE_D) { 580 if (first_d < 0) 581 first_d = curr_d = x; 582 else if (x != curr_d + 1) 583 errx(1, "error: DIGIT range is not contiguous"); 584 else if (x - first_d > 9) 585 errx(1, "error: DIGIT range is too big"); 586 else 587 curr_d++; 588 if (!(r & _CTYPE_X)) 589 errx(1, 590 "error: DIGIT range is not a subset of XDIGIT range"); 591 } 592 } 593 if (first_d < 0) 594 errx(1, "error: no DIGIT range defined in the single byte area"); 595 else if (curr_d - first_d < 9) 596 errx(1, "error: DIGIT range is too small in the single byte area"); 597 598 /* 599 * Fill in our tables. Do this in network order so that 600 * diverse machines have a chance of sharing data. 601 * (Machines like Crays cannot share with little machines due to 602 * word size. Sigh. We tried.) 603 */ 604 for (x = 0; x < _CACHED_RUNES; ++x) { 605 new_locale.runetype[x] = htonl(types.map[x]); 606 new_locale.maplower[x] = htonl(maplower.map[x]); 607 new_locale.mapupper[x] = htonl(mapupper.map[x]); 608 } 609 610 /* 611 * Count up how many ranges we will need for each of the extents. 612 */ 613 list = types.root; 614 615 while (list) { 616 new_locale.runetype_ext_nranges++; 617 list = list->next; 618 } 619 new_locale.runetype_ext_nranges = 620 htonl(new_locale.runetype_ext_nranges); 621 622 list = maplower.root; 623 624 while (list) { 625 new_locale.maplower_ext_nranges++; 626 list = list->next; 627 } 628 new_locale.maplower_ext_nranges = 629 htonl(new_locale.maplower_ext_nranges); 630 631 list = mapupper.root; 632 633 while (list) { 634 new_locale.mapupper_ext_nranges++; 635 list = list->next; 636 } 637 new_locale.mapupper_ext_nranges = 638 htonl(new_locale.mapupper_ext_nranges); 639 640 new_locale.variable_len = htonl(new_locale.variable_len); 641 642 /* 643 * Okay, we are now ready to write the new locale file. 644 */ 645 646 /* 647 * PART 1: The _FileRuneLocale structure 648 */ 649 if (fwrite((char *)&new_locale, sizeof(new_locale), 1, fp) != 1) { 650 perror(locale_file); 651 exit(1); 652 } 653 /* 654 * PART 2: The runetype_ext structures (not the actual tables) 655 */ 656 list = types.root; 657 658 while (list) { 659 _FileRuneEntry re; 660 661 re.min = htonl(list->min); 662 re.max = htonl(list->max); 663 re.map = htonl(list->map); 664 665 if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { 666 perror(locale_file); 667 exit(1); 668 } 669 670 list = list->next; 671 } 672 /* 673 * PART 3: The maplower_ext structures 674 */ 675 list = maplower.root; 676 677 while (list) { 678 _FileRuneEntry re; 679 680 re.min = htonl(list->min); 681 re.max = htonl(list->max); 682 re.map = htonl(list->map); 683 684 if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { 685 perror(locale_file); 686 exit(1); 687 } 688 689 list = list->next; 690 } 691 /* 692 * PART 4: The mapupper_ext structures 693 */ 694 list = mapupper.root; 695 696 while (list) { 697 _FileRuneEntry re; 698 699 re.min = htonl(list->min); 700 re.max = htonl(list->max); 701 re.map = htonl(list->map); 702 703 if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { 704 perror(locale_file); 705 exit(1); 706 } 707 708 list = list->next; 709 } 710 /* 711 * PART 5: The runetype_ext tables 712 */ 713 list = types.root; 714 715 while (list) { 716 for (x = 0; x < list->max - list->min + 1; ++x) 717 list->types[x] = htonl(list->types[x]); 718 719 if (!list->map) { 720 if (fwrite((char *)list->types, 721 (list->max - list->min + 1) * sizeof(uint32_t), 722 1, fp) != 1) { 723 perror(locale_file); 724 exit(1); 725 } 726 } 727 list = list->next; 728 } 729 /* 730 * PART 6: And finally the variable data 731 */ 732 if (fwrite(variable, 733 ntohl(new_locale.variable_len), 1, fp) != 1) { 734 perror(locale_file); 735 exit(1); 736 } 737 if (fclose(fp) != 0) { 738 perror(locale_file); 739 exit(1); 740 } 741 fp = NULL; 742 743 if (!debug) 744 return; 745 746 if (new_locale.encoding[0]) 747 fprintf(stderr, "ENCODING %s\n", new_locale.encoding); 748 if (variable) 749 fprintf(stderr, "VARIABLE %s\n", variable); 750 751 fprintf(stderr, "\nMAPLOWER:\n\n"); 752 753 for (x = 0; x < _CACHED_RUNES; ++x) { 754 if (isprint(maplower.map[x])) 755 fprintf(stderr, " '%c'", (int)maplower.map[x]); 756 else if (maplower.map[x]) 757 fprintf(stderr, "%04x", maplower.map[x]); 758 else 759 fprintf(stderr, "%4x", 0); 760 if ((x & 0xf) == 0xf) 761 fprintf(stderr, "\n"); 762 else 763 fprintf(stderr, " "); 764 } 765 fprintf(stderr, "\n"); 766 767 for (list = maplower.root; list; list = list->next) 768 fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map); 769 770 fprintf(stderr, "\nMAPUPPER:\n\n"); 771 772 for (x = 0; x < _CACHED_RUNES; ++x) { 773 if (isprint(mapupper.map[x])) 774 fprintf(stderr, " '%c'", (int)mapupper.map[x]); 775 else if (mapupper.map[x]) 776 fprintf(stderr, "%04x", mapupper.map[x]); 777 else 778 fprintf(stderr, "%4x", 0); 779 if ((x & 0xf) == 0xf) 780 fprintf(stderr, "\n"); 781 else 782 fprintf(stderr, " "); 783 } 784 fprintf(stderr, "\n"); 785 786 for (list = mapupper.root; list; list = list->next) 787 fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map); 788 789 790 fprintf(stderr, "\nTYPES:\n\n"); 791 792 for (x = 0; x < _CACHED_RUNES; ++x) { 793 uint32_t r = types.map[x]; 794 795 if (r) { 796 if (isprint(x)) 797 fprintf(stderr, " '%c': %2d", x, (int)(r & 0xff)); 798 else 799 fprintf(stderr, "%04x: %2d", x, (int)(r & 0xff)); 800 801 fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); 802 fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); 803 fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); 804 fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); 805 fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); 806 fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); 807 fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); 808 fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); 809 fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); 810 fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); 811 fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); 812 fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); 813 fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); 814 fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); 815 fprintf(stderr, "\n"); 816 } 817 } 818 819 for (list = types.root; list; list = list->next) { 820 if (list->map && list->min + 3 < list->max) { 821 uint32_t r = list->map; 822 823 fprintf(stderr, "%04x: %2d", 824 (uint32_t)list->min, (int)(r & 0xff)); 825 826 fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); 827 fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); 828 fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); 829 fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); 830 fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); 831 fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); 832 fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); 833 fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); 834 fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); 835 fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); 836 fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); 837 fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); 838 fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); 839 fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); 840 fprintf(stderr, "\n...\n"); 841 842 fprintf(stderr, "%04x: %2d", 843 (uint32_t)list->max, (int)(r & 0xff)); 844 845 fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); 846 fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); 847 fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); 848 fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); 849 fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); 850 fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); 851 fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); 852 fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); 853 fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); 854 fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); 855 fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); 856 fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); 857 fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); 858 fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); 859 fprintf(stderr, "\n"); 860 } else 861 for (x = list->min; x <= list->max; ++x) { 862 uint32_t r = ntohl(list->types[x - list->min]); 863 864 if (r) { 865 fprintf(stderr, "%04x: %2d", x, (int)(r & 0xff)); 866 867 fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); 868 fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); 869 fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); 870 fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); 871 fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); 872 fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); 873 fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); 874 fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); 875 fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); 876 fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); 877 fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); 878 fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); 879 fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); 880 fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); 881 fprintf(stderr, "\n"); 882 } 883 } 884 } 885}
| 60 61static void *xmalloc(unsigned int sz); 62static uint32_t *xlalloc(unsigned int sz); 63void yyerror(const char *s); 64static uint32_t *xrelalloc(uint32_t *old, unsigned int sz); 65static void dump_tables(void); 66static void cleanout(void); 67 68const char *locale_file = "<stdout>"; 69 70rune_map maplower = { { 0 }, NULL }; 71rune_map mapupper = { { 0 }, NULL }; 72rune_map types = { { 0 }, NULL }; 73 74_FileRuneLocale new_locale = { "", "", {}, {}, {}, 0, 0, 0, 0 }; 75char *variable = NULL; 76 77void set_map(rune_map *, rune_list *, uint32_t); 78void set_digitmap(rune_map *, rune_list *); 79void add_map(rune_map *, rune_list *, uint32_t); 80static void usage(void); 81%} 82 83%union { 84 int32_t rune; 85 int i; 86 char *str; 87 88 rune_list *list; 89} 90 91%token <rune> RUNE 92%token LBRK 93%token RBRK 94%token THRU 95%token MAPLOWER 96%token MAPUPPER 97%token DIGITMAP 98%token <i> LIST 99%token <str> VARIABLE 100%token ENCODING 101%token INVALID 102%token <str> STRING 103 104%type <list> list 105%type <list> map 106 107 108%% 109 110locale : /* empty */ 111 | table 112 { dump_tables(); } 113 ; 114 115table : entry 116 | table entry 117 ; 118 119entry : ENCODING STRING 120 { if (strcmp($2, "NONE") && 121 strcmp($2, "UTF-8") && 122 strcmp($2, "EUC") && 123 strcmp($2, "GBK") && 124 strcmp($2, "GB18030") && 125 strcmp($2, "GB2312") && 126 strcmp($2, "BIG5") && 127 strcmp($2, "MSKanji")) 128 warnx("ENCODING %s is not supported by libc", $2); 129 strncpy(new_locale.encoding, $2, 130 sizeof(new_locale.encoding)); } 131 | VARIABLE 132 { new_locale.variable_len = strlen($1) + 1; 133 variable = xmalloc(new_locale.variable_len); 134 strcpy(variable, $1); 135 } 136 | INVALID RUNE 137 { warnx("the INVALID keyword is deprecated"); } 138 | LIST list 139 { set_map(&types, $2, $1); } 140 | MAPLOWER map 141 { set_map(&maplower, $2, 0); } 142 | MAPUPPER map 143 { set_map(&mapupper, $2, 0); } 144 | DIGITMAP map 145 { set_digitmap(&types, $2); } 146 ; 147 148list : RUNE 149 { 150 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 151 $$->min = $1; 152 $$->max = $1; 153 $$->next = 0; 154 } 155 | RUNE THRU RUNE 156 { 157 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 158 $$->min = $1; 159 $$->max = $3; 160 $$->next = 0; 161 } 162 | list RUNE 163 { 164 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 165 $$->min = $2; 166 $$->max = $2; 167 $$->next = $1; 168 } 169 | list RUNE THRU RUNE 170 { 171 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 172 $$->min = $2; 173 $$->max = $4; 174 $$->next = $1; 175 } 176 ; 177 178map : LBRK RUNE RUNE RBRK 179 { 180 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 181 $$->min = $2; 182 $$->max = $2; 183 $$->map = $3; 184 $$->next = 0; 185 } 186 | map LBRK RUNE RUNE RBRK 187 { 188 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 189 $$->min = $3; 190 $$->max = $3; 191 $$->map = $4; 192 $$->next = $1; 193 } 194 | LBRK RUNE THRU RUNE ':' RUNE RBRK 195 { 196 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 197 $$->min = $2; 198 $$->max = $4; 199 $$->map = $6; 200 $$->next = 0; 201 } 202 | map LBRK RUNE THRU RUNE ':' RUNE RBRK 203 { 204 $$ = (rune_list *)xmalloc(sizeof(rune_list)); 205 $$->min = $3; 206 $$->max = $5; 207 $$->map = $7; 208 $$->next = $1; 209 } 210 ; 211%% 212 213int debug; 214FILE *fp; 215 216static void 217cleanout(void) 218{ 219 if (fp != NULL) 220 unlink(locale_file); 221} 222 223int 224main(int ac, char *av[]) 225{ 226 int x; 227 228 fp = stdout; 229 230 while ((x = getopt(ac, av, "do:")) != EOF) { 231 switch(x) { 232 case 'd': 233 debug = 1; 234 break; 235 case 'o': 236 locale_file = optarg; 237 if ((fp = fopen(locale_file, "w")) == 0) 238 err(1, "%s", locale_file); 239 atexit(cleanout); 240 break; 241 default: 242 usage(); 243 } 244 } 245 246 switch (ac - optind) { 247 case 0: 248 break; 249 case 1: 250 if (freopen(av[optind], "r", stdin) == 0) 251 err(1, "%s", av[optind]); 252 break; 253 default: 254 usage(); 255 } 256 for (x = 0; x < _CACHED_RUNES; ++x) { 257 mapupper.map[x] = x; 258 maplower.map[x] = x; 259 } 260 memcpy(new_locale.magic, _FILE_RUNE_MAGIC_1, sizeof(new_locale.magic)); 261 262 yyparse(); 263 264 return(0); 265} 266 267static void 268usage() 269{ 270 fprintf(stderr, "usage: mklocale [-d] [-o output] [source]\n"); 271 exit(1); 272} 273 274void 275yyerror(s) 276 const char *s; 277{ 278 fprintf(stderr, "%s\n", s); 279} 280 281static void * 282xmalloc(sz) 283 unsigned int sz; 284{ 285 void *r = malloc(sz); 286 if (!r) 287 errx(1, "xmalloc"); 288 return(r); 289} 290 291static uint32_t * 292xlalloc(sz) 293 unsigned int sz; 294{ 295 uint32_t *r = (uint32_t *)malloc(sz * sizeof(uint32_t)); 296 if (!r) 297 errx(1, "xlalloc"); 298 return(r); 299} 300 301static uint32_t * 302xrelalloc(old, sz) 303 uint32_t *old; 304 unsigned int sz; 305{ 306 uint32_t *r = (uint32_t *)realloc((char *)old, 307 sz * sizeof(uint32_t)); 308 if (!r) 309 errx(1, "xrelalloc"); 310 return(r); 311} 312 313void 314set_map(map, list, flag) 315 rune_map *map; 316 rune_list *list; 317 uint32_t flag; 318{ 319 while (list) { 320 rune_list *nlist = list->next; 321 add_map(map, list, flag); 322 list = nlist; 323 } 324} 325 326void 327set_digitmap(map, list) 328 rune_map *map; 329 rune_list *list; 330{ 331 int32_t i; 332 333 while (list) { 334 rune_list *nlist = list->next; 335 for (i = list->min; i <= list->max; ++i) { 336 if (list->map + (i - list->min)) { 337 rune_list *tmp = (rune_list *)xmalloc(sizeof(rune_list)); 338 tmp->min = i; 339 tmp->max = i; 340 add_map(map, tmp, list->map + (i - list->min)); 341 } 342 } 343 free(list); 344 list = nlist; 345 } 346} 347 348void 349add_map(map, list, flag) 350 rune_map *map; 351 rune_list *list; 352 uint32_t flag; 353{ 354 int32_t i; 355 rune_list *lr = 0; 356 rune_list *r; 357 int32_t run; 358 359 while (list->min < _CACHED_RUNES && list->min <= list->max) { 360 if (flag) 361 map->map[list->min++] |= flag; 362 else 363 map->map[list->min++] = list->map++; 364 } 365 366 if (list->min > list->max) { 367 free(list); 368 return; 369 } 370 371 run = list->max - list->min + 1; 372 373 if (!(r = map->root) || (list->max < r->min - 1) 374 || (!flag && list->max == r->min - 1)) { 375 if (flag) { 376 list->types = xlalloc(run); 377 for (i = 0; i < run; ++i) 378 list->types[i] = flag; 379 } 380 list->next = map->root; 381 map->root = list; 382 return; 383 } 384 385 for (r = map->root; r && r->max + 1 < list->min; r = r->next) 386 lr = r; 387 388 if (!r) { 389 /* 390 * We are off the end. 391 */ 392 if (flag) { 393 list->types = xlalloc(run); 394 for (i = 0; i < run; ++i) 395 list->types[i] = flag; 396 } 397 list->next = 0; 398 lr->next = list; 399 return; 400 } 401 402 if (list->max < r->min - 1) { 403 /* 404 * We come before this range and we do not intersect it. 405 * We are not before the root node, it was checked before the loop 406 */ 407 if (flag) { 408 list->types = xlalloc(run); 409 for (i = 0; i < run; ++i) 410 list->types[i] = flag; 411 } 412 list->next = lr->next; 413 lr->next = list; 414 return; 415 } 416 417 /* 418 * At this point we have found that we at least intersect with 419 * the range pointed to by `r', we might intersect with one or 420 * more ranges beyond `r' as well. 421 */ 422 423 if (!flag && list->map - list->min != r->map - r->min) { 424 /* 425 * There are only two cases when we are doing case maps and 426 * our maps needn't have the same offset. When we are adjoining 427 * but not intersecting. 428 */ 429 if (list->max + 1 == r->min) { 430 lr->next = list; 431 list->next = r; 432 return; 433 } 434 if (list->min - 1 == r->max) { 435 list->next = r->next; 436 r->next = list; 437 return; 438 } 439 errx(1, "error: conflicting map entries"); 440 } 441 442 if (list->min >= r->min && list->max <= r->max) { 443 /* 444 * Subset case. 445 */ 446 447 if (flag) { 448 for (i = list->min; i <= list->max; ++i) 449 r->types[i - r->min] |= flag; 450 } 451 free(list); 452 return; 453 } 454 if (list->min <= r->min && list->max >= r->max) { 455 /* 456 * Superset case. Make him big enough to hold us. 457 * We might need to merge with the guy after him. 458 */ 459 if (flag) { 460 list->types = xlalloc(list->max - list->min + 1); 461 462 for (i = list->min; i <= list->max; ++i) 463 list->types[i - list->min] = flag; 464 465 for (i = r->min; i <= r->max; ++i) 466 list->types[i - list->min] |= r->types[i - r->min]; 467 468 free(r->types); 469 r->types = list->types; 470 } else { 471 r->map = list->map; 472 } 473 r->min = list->min; 474 r->max = list->max; 475 free(list); 476 } else if (list->min < r->min) { 477 /* 478 * Our tail intersects his head. 479 */ 480 if (flag) { 481 list->types = xlalloc(r->max - list->min + 1); 482 483 for (i = r->min; i <= r->max; ++i) 484 list->types[i - list->min] = r->types[i - r->min]; 485 486 for (i = list->min; i < r->min; ++i) 487 list->types[i - list->min] = flag; 488 489 for (i = r->min; i <= list->max; ++i) 490 list->types[i - list->min] |= flag; 491 492 free(r->types); 493 r->types = list->types; 494 } else { 495 r->map = list->map; 496 } 497 r->min = list->min; 498 free(list); 499 return; 500 } else { 501 /* 502 * Our head intersects his tail. 503 * We might need to merge with the guy after him. 504 */ 505 if (flag) { 506 r->types = xrelalloc(r->types, list->max - r->min + 1); 507 508 for (i = list->min; i <= r->max; ++i) 509 r->types[i - r->min] |= flag; 510 511 for (i = r->max+1; i <= list->max; ++i) 512 r->types[i - r->min] = flag; 513 } 514 r->max = list->max; 515 free(list); 516 } 517 518 /* 519 * Okay, check to see if we grew into the next guy(s) 520 */ 521 while ((lr = r->next) && r->max >= lr->min) { 522 if (flag) { 523 if (r->max >= lr->max) { 524 /* 525 * Good, we consumed all of him. 526 */ 527 for (i = lr->min; i <= lr->max; ++i) 528 r->types[i - r->min] |= lr->types[i - lr->min]; 529 } else { 530 /* 531 * "append" him on to the end of us. 532 */ 533 r->types = xrelalloc(r->types, lr->max - r->min + 1); 534 535 for (i = lr->min; i <= r->max; ++i) 536 r->types[i - r->min] |= lr->types[i - lr->min]; 537 538 for (i = r->max+1; i <= lr->max; ++i) 539 r->types[i - r->min] = lr->types[i - lr->min]; 540 541 r->max = lr->max; 542 } 543 } else { 544 if (lr->max > r->max) 545 r->max = lr->max; 546 } 547 548 r->next = lr->next; 549 550 if (flag) 551 free(lr->types); 552 free(lr); 553 } 554} 555 556static void 557dump_tables() 558{ 559 int x, first_d, curr_d; 560 rune_list *list; 561 562 /* 563 * See if we can compress some of the istype arrays 564 */ 565 for(list = types.root; list; list = list->next) { 566 list->map = list->types[0]; 567 for (x = 1; x < list->max - list->min + 1; ++x) { 568 if ((int32_t)list->types[x] != list->map) { 569 list->map = 0; 570 break; 571 } 572 } 573 } 574 575 first_d = curr_d = -1; 576 for (x = 0; x < _CACHED_RUNES; ++x) { 577 uint32_t r = types.map[x]; 578 579 if (r & _CTYPE_D) { 580 if (first_d < 0) 581 first_d = curr_d = x; 582 else if (x != curr_d + 1) 583 errx(1, "error: DIGIT range is not contiguous"); 584 else if (x - first_d > 9) 585 errx(1, "error: DIGIT range is too big"); 586 else 587 curr_d++; 588 if (!(r & _CTYPE_X)) 589 errx(1, 590 "error: DIGIT range is not a subset of XDIGIT range"); 591 } 592 } 593 if (first_d < 0) 594 errx(1, "error: no DIGIT range defined in the single byte area"); 595 else if (curr_d - first_d < 9) 596 errx(1, "error: DIGIT range is too small in the single byte area"); 597 598 /* 599 * Fill in our tables. Do this in network order so that 600 * diverse machines have a chance of sharing data. 601 * (Machines like Crays cannot share with little machines due to 602 * word size. Sigh. We tried.) 603 */ 604 for (x = 0; x < _CACHED_RUNES; ++x) { 605 new_locale.runetype[x] = htonl(types.map[x]); 606 new_locale.maplower[x] = htonl(maplower.map[x]); 607 new_locale.mapupper[x] = htonl(mapupper.map[x]); 608 } 609 610 /* 611 * Count up how many ranges we will need for each of the extents. 612 */ 613 list = types.root; 614 615 while (list) { 616 new_locale.runetype_ext_nranges++; 617 list = list->next; 618 } 619 new_locale.runetype_ext_nranges = 620 htonl(new_locale.runetype_ext_nranges); 621 622 list = maplower.root; 623 624 while (list) { 625 new_locale.maplower_ext_nranges++; 626 list = list->next; 627 } 628 new_locale.maplower_ext_nranges = 629 htonl(new_locale.maplower_ext_nranges); 630 631 list = mapupper.root; 632 633 while (list) { 634 new_locale.mapupper_ext_nranges++; 635 list = list->next; 636 } 637 new_locale.mapupper_ext_nranges = 638 htonl(new_locale.mapupper_ext_nranges); 639 640 new_locale.variable_len = htonl(new_locale.variable_len); 641 642 /* 643 * Okay, we are now ready to write the new locale file. 644 */ 645 646 /* 647 * PART 1: The _FileRuneLocale structure 648 */ 649 if (fwrite((char *)&new_locale, sizeof(new_locale), 1, fp) != 1) { 650 perror(locale_file); 651 exit(1); 652 } 653 /* 654 * PART 2: The runetype_ext structures (not the actual tables) 655 */ 656 list = types.root; 657 658 while (list) { 659 _FileRuneEntry re; 660 661 re.min = htonl(list->min); 662 re.max = htonl(list->max); 663 re.map = htonl(list->map); 664 665 if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { 666 perror(locale_file); 667 exit(1); 668 } 669 670 list = list->next; 671 } 672 /* 673 * PART 3: The maplower_ext structures 674 */ 675 list = maplower.root; 676 677 while (list) { 678 _FileRuneEntry re; 679 680 re.min = htonl(list->min); 681 re.max = htonl(list->max); 682 re.map = htonl(list->map); 683 684 if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { 685 perror(locale_file); 686 exit(1); 687 } 688 689 list = list->next; 690 } 691 /* 692 * PART 4: The mapupper_ext structures 693 */ 694 list = mapupper.root; 695 696 while (list) { 697 _FileRuneEntry re; 698 699 re.min = htonl(list->min); 700 re.max = htonl(list->max); 701 re.map = htonl(list->map); 702 703 if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { 704 perror(locale_file); 705 exit(1); 706 } 707 708 list = list->next; 709 } 710 /* 711 * PART 5: The runetype_ext tables 712 */ 713 list = types.root; 714 715 while (list) { 716 for (x = 0; x < list->max - list->min + 1; ++x) 717 list->types[x] = htonl(list->types[x]); 718 719 if (!list->map) { 720 if (fwrite((char *)list->types, 721 (list->max - list->min + 1) * sizeof(uint32_t), 722 1, fp) != 1) { 723 perror(locale_file); 724 exit(1); 725 } 726 } 727 list = list->next; 728 } 729 /* 730 * PART 6: And finally the variable data 731 */ 732 if (fwrite(variable, 733 ntohl(new_locale.variable_len), 1, fp) != 1) { 734 perror(locale_file); 735 exit(1); 736 } 737 if (fclose(fp) != 0) { 738 perror(locale_file); 739 exit(1); 740 } 741 fp = NULL; 742 743 if (!debug) 744 return; 745 746 if (new_locale.encoding[0]) 747 fprintf(stderr, "ENCODING %s\n", new_locale.encoding); 748 if (variable) 749 fprintf(stderr, "VARIABLE %s\n", variable); 750 751 fprintf(stderr, "\nMAPLOWER:\n\n"); 752 753 for (x = 0; x < _CACHED_RUNES; ++x) { 754 if (isprint(maplower.map[x])) 755 fprintf(stderr, " '%c'", (int)maplower.map[x]); 756 else if (maplower.map[x]) 757 fprintf(stderr, "%04x", maplower.map[x]); 758 else 759 fprintf(stderr, "%4x", 0); 760 if ((x & 0xf) == 0xf) 761 fprintf(stderr, "\n"); 762 else 763 fprintf(stderr, " "); 764 } 765 fprintf(stderr, "\n"); 766 767 for (list = maplower.root; list; list = list->next) 768 fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map); 769 770 fprintf(stderr, "\nMAPUPPER:\n\n"); 771 772 for (x = 0; x < _CACHED_RUNES; ++x) { 773 if (isprint(mapupper.map[x])) 774 fprintf(stderr, " '%c'", (int)mapupper.map[x]); 775 else if (mapupper.map[x]) 776 fprintf(stderr, "%04x", mapupper.map[x]); 777 else 778 fprintf(stderr, "%4x", 0); 779 if ((x & 0xf) == 0xf) 780 fprintf(stderr, "\n"); 781 else 782 fprintf(stderr, " "); 783 } 784 fprintf(stderr, "\n"); 785 786 for (list = mapupper.root; list; list = list->next) 787 fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map); 788 789 790 fprintf(stderr, "\nTYPES:\n\n"); 791 792 for (x = 0; x < _CACHED_RUNES; ++x) { 793 uint32_t r = types.map[x]; 794 795 if (r) { 796 if (isprint(x)) 797 fprintf(stderr, " '%c': %2d", x, (int)(r & 0xff)); 798 else 799 fprintf(stderr, "%04x: %2d", x, (int)(r & 0xff)); 800 801 fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); 802 fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); 803 fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); 804 fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); 805 fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); 806 fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); 807 fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); 808 fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); 809 fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); 810 fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); 811 fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); 812 fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); 813 fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); 814 fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); 815 fprintf(stderr, "\n"); 816 } 817 } 818 819 for (list = types.root; list; list = list->next) { 820 if (list->map && list->min + 3 < list->max) { 821 uint32_t r = list->map; 822 823 fprintf(stderr, "%04x: %2d", 824 (uint32_t)list->min, (int)(r & 0xff)); 825 826 fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); 827 fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); 828 fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); 829 fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); 830 fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); 831 fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); 832 fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); 833 fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); 834 fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); 835 fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); 836 fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); 837 fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); 838 fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); 839 fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); 840 fprintf(stderr, "\n...\n"); 841 842 fprintf(stderr, "%04x: %2d", 843 (uint32_t)list->max, (int)(r & 0xff)); 844 845 fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); 846 fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); 847 fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); 848 fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); 849 fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); 850 fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); 851 fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); 852 fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); 853 fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); 854 fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); 855 fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); 856 fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); 857 fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); 858 fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); 859 fprintf(stderr, "\n"); 860 } else 861 for (x = list->min; x <= list->max; ++x) { 862 uint32_t r = ntohl(list->types[x - list->min]); 863 864 if (r) { 865 fprintf(stderr, "%04x: %2d", x, (int)(r & 0xff)); 866 867 fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); 868 fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); 869 fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); 870 fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); 871 fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); 872 fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); 873 fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); 874 fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); 875 fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); 876 fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); 877 fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); 878 fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); 879 fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); 880 fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); 881 fprintf(stderr, "\n"); 882 } 883 } 884 } 885}
|