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