Move VarCreate() and VarDestroy() close to top of file, and add white
[dragonfly.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.4 2004/10/29 06:03:21 asmodai 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 <runetype.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  <str>   STRING
98
99 %type   <list>  list
100 %type   <list>  map
101
102
103 %%
104
105 locale  :       /* empty */
106         |       table
107                 { dump_tables(); }
108         ;
109
110 table   :       entry
111         |       table entry
112         ;
113
114 entry   :       ENCODING STRING
115                 { if (strcmp($2, "NONE") &&
116                       strcmp($2, "UTF2") &&
117                       strcmp($2, "UTF-8") &&
118                       strcmp($2, "EUC") &&
119                       strcmp($2, "GBK") &&
120                       strcmp($2, "GB18030") &&
121                       strcmp($2, "GB2312") &&
122                       strcmp($2, "BIG5") &&
123                       strcmp($2, "MSKanji"))
124                         warnx("ENCODING %s is not supported by libc", $2);
125                 strncpy(new_locale.encoding, $2, sizeof(new_locale.encoding)); }
126         |       VARIABLE
127                 { new_locale.variable_len = strlen($1) + 1;
128                   new_locale.variable = malloc(new_locale.variable_len);
129                   strcpy((char *)new_locale.variable, $1);
130                 }
131         |       LIST list
132                 { set_map(&types, $2, $1); }
133         |       MAPLOWER map
134                 { set_map(&maplower, $2, 0); }
135         |       MAPUPPER map
136                 { set_map(&mapupper, $2, 0); }
137         |       DIGITMAP map
138                 { set_digitmap(&types, $2); }
139         ;
140
141 list    :       RUNE
142                 {
143                     $$ = (rune_list *)malloc(sizeof(rune_list));
144                     $$->min = $1;
145                     $$->max = $1;
146                     $$->next = 0;
147                 }
148         |       RUNE THRU RUNE
149                 {
150                     $$ = (rune_list *)malloc(sizeof(rune_list));
151                     $$->min = $1;
152                     $$->max = $3;
153                     $$->next = 0;
154                 }
155         |       list RUNE
156                 {
157                     $$ = (rune_list *)malloc(sizeof(rune_list));
158                     $$->min = $2;
159                     $$->max = $2;
160                     $$->next = $1;
161                 }
162         |       list RUNE THRU RUNE
163                 {
164                     $$ = (rune_list *)malloc(sizeof(rune_list));
165                     $$->min = $2;
166                     $$->max = $4;
167                     $$->next = $1;
168                 }
169         ;
170
171 map     :       LBRK RUNE RUNE RBRK
172                 {
173                     $$ = (rune_list *)malloc(sizeof(rune_list));
174                     $$->min = $2;
175                     $$->max = $2;
176                     $$->map = $3;
177                     $$->next = 0;
178                 }
179         |       map LBRK RUNE RUNE RBRK
180                 {
181                     $$ = (rune_list *)malloc(sizeof(rune_list));
182                     $$->min = $3;
183                     $$->max = $3;
184                     $$->map = $4;
185                     $$->next = $1;
186                 }
187         |       LBRK RUNE THRU RUNE ':' RUNE RBRK
188                 {
189                     $$ = (rune_list *)malloc(sizeof(rune_list));
190                     $$->min = $2;
191                     $$->max = $4;
192                     $$->map = $6;
193                     $$->next = 0;
194                 }
195         |       map LBRK RUNE THRU RUNE ':' RUNE RBRK
196                 {
197                     $$ = (rune_list *)malloc(sizeof(rune_list));
198                     $$->min = $3;
199                     $$->max = $5;
200                     $$->map = $7;
201                     $$->next = $1;
202                 }
203         ;
204 %%
205
206 int debug;
207 FILE *fp;
208
209 static void
210 cleanout(void)
211 {
212     if (fp != NULL)
213         unlink(locale_file);
214 }
215
216 int
217 main(int ac, char *av[])
218 {
219     int x;
220
221     extern char *optarg;
222     extern int optind;
223     fp = stdout;
224
225     while ((x = getopt(ac, av, "do:")) != EOF) {
226         switch(x) {
227         case 'd':
228             debug = 1;
229             break;
230         case 'o':
231             locale_file = optarg;
232             if ((fp = fopen(locale_file, "w")) == 0) {
233                 perror(locale_file);
234                 exit(1);
235             }
236             atexit(cleanout);
237             break;
238         default:
239         usage:
240             fprintf(stderr, "usage: mklocale [-d] [-o output] [source]\n");
241             exit(1);
242         }
243     }
244
245     switch (ac - optind) {
246     case 0:
247         break;
248     case 1:
249         if (freopen(av[optind], "r", stdin) == 0) {
250             perror(av[optind]);
251             exit(1);
252         }
253         break;
254     default:
255         goto 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, _RUNE_MAGIC_1, sizeof(new_locale.magic));
262
263     yyparse();
264
265     return(0);
266 }
267
268 void
269 yyerror(s)
270         const char *s;
271 {
272     fprintf(stderr, "%s\n", s);
273 }
274
275 static void *
276 xmalloc(sz)
277         unsigned int sz;
278 {
279     void *r = malloc(sz);
280     if (!r) {
281         perror("xmalloc");
282         exit(1);
283     }
284     return(r);
285 }
286
287 static unsigned long *
288 xlalloc(sz)
289         unsigned int sz;
290 {
291     unsigned long *r = (unsigned long *)malloc(sz * sizeof(unsigned long));
292     if (!r) {
293         perror("xlalloc");
294         exit(1);
295     }
296     return(r);
297 }
298
299 static unsigned long *
300 xrelalloc(old, sz)
301         unsigned long *old;
302         unsigned int sz;
303 {
304     unsigned long *r = (unsigned long *)realloc((char *)old,
305                                                 sz * sizeof(unsigned long));
306     if (!r) {
307         perror("xrelalloc");
308         exit(1);
309     }
310     return(r);
311 }
312
313 void
314 set_map(map, list, flag)
315         rune_map *map;
316         rune_list *list;
317         unsigned long flag;
318 {
319     while (list) {
320         rune_list *nlist = list->next;
321         add_map(map, list, flag);
322         list = nlist;
323     }
324 }
325
326 void
327 set_digitmap(map, list)
328         rune_map *map;
329         rune_list *list;
330 {
331     rune_t i;
332
333     while (list) {
334         rune_list *nlist = list->next;
335         for (i = list->min; i <= list->max; ++i) {
336             if (list->map + (i - list->min)) {
337                 rune_list *tmp = (rune_list *)xmalloc(sizeof(rune_list));
338                 tmp->min = i;
339                 tmp->max = i;
340                 add_map(map, tmp, list->map + (i - list->min));
341             }
342         }
343         free(list);
344         list = nlist;
345     }
346 }
347
348 void
349 add_map(map, list, flag)
350         rune_map *map;
351         rune_list *list;
352         unsigned long flag;
353 {
354     rune_t i;
355     rune_list *lr = 0;
356     rune_list *r;
357     rune_t run;
358
359     while (list->min < _CACHED_RUNES && list->min <= list->max) {
360         if (flag)
361             map->map[list->min++] |= flag;
362         else
363             map->map[list->min++] = list->map++;
364     }
365
366     if (list->min > list->max) {
367         free(list);
368         return;
369     }
370
371     run = list->max - list->min + 1;
372
373     if (!(r = map->root) || (list->max < r->min - 1)
374                          || (!flag && list->max == r->min - 1)) {
375         if (flag) {
376             list->types = xlalloc(run);
377             for (i = 0; i < run; ++i)
378                 list->types[i] = flag;
379         }
380         list->next = map->root;
381         map->root = list;
382         return;
383     }
384
385     for (r = map->root; r && r->max + 1 < list->min; r = r->next)
386         lr = r;
387
388     if (!r) {
389         /*
390          * We are off the end.
391          */
392         if (flag) {
393             list->types = xlalloc(run);
394             for (i = 0; i < run; ++i)
395                 list->types[i] = flag;
396         }
397         list->next = 0;
398         lr->next = list;
399         return;
400     }
401
402     if (list->max < r->min - 1) {
403         /*
404          * We come before this range and we do not intersect it.
405          * We are not before the root node, it was checked before the loop
406          */
407         if (flag) {
408             list->types = xlalloc(run);
409             for (i = 0; i < run; ++i)
410                 list->types[i] = flag;
411         }
412         list->next = lr->next;
413         lr->next = list;
414         return;
415     }
416
417     /*
418      * At this point we have found that we at least intersect with
419      * the range pointed to by `r', we might intersect with one or
420      * more ranges beyond `r' as well.
421      */
422
423     if (!flag && list->map - list->min != r->map - r->min) {
424         /*
425          * There are only two cases when we are doing case maps and
426          * our maps needn't have the same offset.  When we are adjoining
427          * but not intersecting.
428          */
429         if (list->max + 1 == r->min) {
430             lr->next = list;
431             list->next = r;
432             return;
433         }
434         if (list->min - 1 == r->max) {
435             list->next = r->next;
436             r->next = list;
437             return;
438         }
439         fprintf(stderr, "Error: conflicting map entries\n");
440         exit(1);
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 ((rune_t)list->types[x] != list->map) {
570                 list->map = 0;
571                 break;
572             }
573         }
574     }
575
576     first_d = -1;
577     for (x = 0; x < _CACHED_RUNES; ++x) {
578         unsigned long 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                         fprintf(stderr, "Error: DIGIT range is not contiguous\n");
585                         exit(1);
586                 } else if (x - first_d > 9) {
587                         fprintf(stderr, "Error: DIGIT range is too big\n");
588                         exit(1);
589                 } else
590                         curr_d++;
591                 if (!(r & _CTYPE_X)) {
592                         fprintf(stderr, "Error: DIGIT range is not a subset of XDIGIT range\n");
593                         exit(1);
594                 }
595         }
596     }
597     if (first_d < 0) {
598         fprintf(stderr, "Error: no DIGIT range defined in the single byte area\n");
599         exit(1);
600     } else if (curr_d - first_d < 9) {
601         fprintf(stderr, "Error: DIGIT range is too small in the single byte area\n");
602         exit(1);
603     }
604
605     /*
606      * Fill in our tables.  Do this in network order so that
607      * diverse machines have a chance of sharing data.
608      * (Machines like Crays cannot share with little machines due to
609      *  word size.  Sigh.  We tried.)
610      */
611     for (x = 0; x < _CACHED_RUNES; ++x) {
612         new_locale.runetype[x] = htonl(types.map[x]);
613         new_locale.maplower[x] = htonl(maplower.map[x]);
614         new_locale.mapupper[x] = htonl(mapupper.map[x]);
615     }
616
617     /*
618      * Count up how many ranges we will need for each of the extents.
619      */
620     list = types.root;
621
622     while (list) {
623         new_locale.runetype_ext.nranges++;
624         list = list->next;
625     }
626     new_locale.runetype_ext.nranges = htonl(new_locale.runetype_ext.nranges);
627
628     list = maplower.root;
629
630     while (list) {
631         new_locale.maplower_ext.nranges++;
632         list = list->next;
633     }
634     new_locale.maplower_ext.nranges = htonl(new_locale.maplower_ext.nranges);
635
636     list = mapupper.root;
637
638     while (list) {
639         new_locale.mapupper_ext.nranges++;
640         list = list->next;
641     }
642     new_locale.mapupper_ext.nranges = htonl(new_locale.mapupper_ext.nranges);
643
644     new_locale.variable_len = htonl(new_locale.variable_len);
645
646     /*
647      * Okay, we are now ready to write the new locale file.
648      */
649
650     /*
651      * PART 1: The _RuneLocale structure
652      */
653     if (fwrite((char *)&new_locale, sizeof(new_locale), 1, fp) != 1) {
654         perror(locale_file);
655         exit(1);
656     }
657     /*
658      * PART 2: The runetype_ext structures (not the actual tables)
659      */
660     list = types.root;
661
662     while (list) {
663         _RuneEntry re;
664
665         re.min = htonl(list->min);
666         re.max = htonl(list->max);
667         re.map = htonl(list->map);
668
669         if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) {
670             perror(locale_file);
671             exit(1);
672         }
673
674         list = list->next;
675     }
676     /*
677      * PART 3: The maplower_ext structures
678      */
679     list = maplower.root;
680
681     while (list) {
682         _RuneEntry re;
683
684         re.min = htonl(list->min);
685         re.max = htonl(list->max);
686         re.map = htonl(list->map);
687
688         if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) {
689             perror(locale_file);
690             exit(1);
691         }
692
693         list = list->next;
694     }
695     /*
696      * PART 4: The mapupper_ext structures
697      */
698     list = mapupper.root;
699
700     while (list) {
701         _RuneEntry re;
702
703         re.min = htonl(list->min);
704         re.max = htonl(list->max);
705         re.map = htonl(list->map);
706
707         if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) {
708             perror(locale_file);
709             exit(1);
710         }
711
712         list = list->next;
713     }
714     /*
715      * PART 5: The runetype_ext tables
716      */
717     list = types.root;
718
719     while (list) {
720         for (x = 0; x < list->max - list->min + 1; ++x)
721             list->types[x] = htonl(list->types[x]);
722
723         if (!list->map) {
724             if (fwrite((char *)list->types,
725                        (list->max - list->min + 1) * sizeof(unsigned long),
726                        1, fp) != 1) {
727                 perror(locale_file);
728                 exit(1);
729             }
730         }
731         list = list->next;
732     }
733     /*
734      * PART 5: And finally the variable data
735      */
736     if (fwrite((char *)new_locale.variable,
737                ntohl(new_locale.variable_len), 1, fp) != 1) {
738         perror(locale_file);
739         exit(1);
740     }
741     if (fclose(fp) != 0) {
742         perror(locale_file);
743         exit(1);
744     }
745     fp = NULL;
746
747     if (!debug)
748         return;
749
750     if (new_locale.encoding[0])
751         fprintf(stderr, "ENCODING       %s\n", new_locale.encoding);
752     if (new_locale.variable)
753         fprintf(stderr, "VARIABLE       %s\n", (char *)new_locale.variable);
754
755     fprintf(stderr, "\nMAPLOWER:\n\n");
756
757     for (x = 0; x < _CACHED_RUNES; ++x) {
758         if (isprint(maplower.map[x]))
759             fprintf(stderr, " '%c'", (int)maplower.map[x]);
760         else if (maplower.map[x])
761             fprintf(stderr, "%04lx", maplower.map[x]);
762         else
763             fprintf(stderr, "%4x", 0);
764         if ((x & 0xf) == 0xf)
765             fprintf(stderr, "\n");
766         else
767             fprintf(stderr, " ");
768     }
769     fprintf(stderr, "\n");
770
771     for (list = maplower.root; list; list = list->next)
772         fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map);
773
774     fprintf(stderr, "\nMAPUPPER:\n\n");
775
776     for (x = 0; x < _CACHED_RUNES; ++x) {
777         if (isprint(mapupper.map[x]))
778             fprintf(stderr, " '%c'", (int)mapupper.map[x]);
779         else if (mapupper.map[x])
780             fprintf(stderr, "%04lx", mapupper.map[x]);
781         else
782             fprintf(stderr, "%4x", 0);
783         if ((x & 0xf) == 0xf)
784             fprintf(stderr, "\n");
785         else
786             fprintf(stderr, " ");
787     }
788     fprintf(stderr, "\n");
789
790     for (list = mapupper.root; list; list = list->next)
791         fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map);
792
793
794     fprintf(stderr, "\nTYPES:\n\n");
795
796     for (x = 0; x < _CACHED_RUNES; ++x) {
797         unsigned long r = types.map[x];
798
799         if (r) {
800             if (isprint(x))
801                 fprintf(stderr, " '%c': %2d", x, (int)(r & 0xff));
802             else
803                 fprintf(stderr, "%04x: %2d", x, (int)(r & 0xff));
804
805             fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : "");
806             fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : "");
807             fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : "");
808             fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : "");
809             fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : "");
810             fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : "");
811             fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : "");
812             fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : "");
813             fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : "");
814             fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : "");
815             fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : "");
816             fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : "");
817             fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : "");
818             fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : "");
819             fprintf(stderr, "\n");
820         }
821     }
822
823     for (list = types.root; list; list = list->next) {
824         if (list->map && list->min + 3 < list->max) {
825             unsigned long r = list->map;
826
827             fprintf(stderr, "%04lx: %2d",
828                 (unsigned long)list->min, (int)(r & 0xff));
829
830             fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : "");
831             fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : "");
832             fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : "");
833             fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : "");
834             fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : "");
835             fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : "");
836             fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : "");
837             fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : "");
838             fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : "");
839             fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : "");
840             fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : "");
841             fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : "");
842             fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : "");
843             fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : "");
844             fprintf(stderr, "\n...\n");
845
846             fprintf(stderr, "%04lx: %2d",
847                 (unsigned long)list->max, (int)(r & 0xff));
848
849             fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : "");
850             fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : "");
851             fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : "");
852             fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : "");
853             fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : "");
854             fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : "");
855             fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : "");
856             fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : "");
857             fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : "");
858             fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : "");
859             fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : "");
860             fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : "");
861             fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : "");
862             fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : "");
863             fprintf(stderr, "\n");
864         } else 
865         for (x = list->min; x <= list->max; ++x) {
866             unsigned long r = ntohl(list->types[x - list->min]);
867
868             if (r) {
869                 fprintf(stderr, "%04x: %2d", x, (int)(r & 0xff));
870
871                 fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : "");
872                 fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : "");
873                 fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : "");
874                 fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : "");
875                 fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : "");
876                 fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : "");
877                 fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : "");
878                 fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : "");
879                 fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : "");
880                 fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : "");
881                 fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : "");
882                 fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : "");
883                 fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : "");
884                 fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : "");
885                 fprintf(stderr, "\n");
886             }
887         }
888     }
889 }