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