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