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