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