Fix warnings from byacc import.
[dragonfly.git] / usr.bin / mklocale / yacc.y
1 /*      $NetBSD: src/usr.bin/mklocale/yacc.y,v 1.24 2004/01/05 23:23:36 jmmv Exp $      */
2 /*      $DragonFly: src/usr.bin/mklocale/yacc.y,v 1.8 2008/07/10 18:29:52 swildner 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 for htonl on POSIX systems. */
39
40 #include <ctype.h>
41 #include <err.h>
42 #include <stddef.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47
48 #include "locale/runetype.h"
49
50 #include "ldef.h"
51
52 const char      *locale_file = "<stdout>";
53
54 rune_map        maplower = { { 0, }, NULL };
55 rune_map        mapupper = { { 0, }, NULL };
56 rune_map        types = { { 0, }, NULL };
57
58 _NBRuneLocale   new_locale;
59
60 __nbrune_t      charsetbits = (__nbrune_t)0x00000000;
61 #if 0
62 __nbrune_t      charsetmask = (__nbrune_t)0x0000007f;
63 #endif
64 __nbrune_t      charsetmask = (__nbrune_t)0xffffffff;
65
66 void    set_map(rune_map *, rune_list *, uint32_t);
67 void    set_digitmap(rune_map *, rune_list *);
68 void    add_map(rune_map *, rune_list *, uint32_t);
69
70 int             main(int, char *[]);
71 int             yyerror(const char *s);
72 void            *xmalloc(unsigned int sz);
73 uint32_t        *xlalloc(unsigned int sz);
74 uint32_t        *xrelalloc(uint32_t *old, unsigned int sz);
75 void            dump_tables(void);
76 extern int      yylex(void);
77 %}
78
79 %union  {
80     __nbrune_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 map
167                 { set_digitmap(&types, $2); }
168         ;
169
170 list    :       RUNE
171                 {
172                     $$ = (rune_list *)malloc(sizeof(rune_list));
173                     $$->min = ($1 & charsetmask) | charsetbits;
174                     $$->max = ($1 & charsetmask) | charsetbits;
175                     $$->next = 0;
176                 }
177         |       RUNE THRU RUNE
178                 {
179                     $$ = (rune_list *)malloc(sizeof(rune_list));
180                     $$->min = ($1 & charsetmask) | charsetbits;
181                     $$->max = ($3 & charsetmask) | charsetbits;
182                     $$->next = 0;
183                 }
184         |       list RUNE
185                 {
186                     $$ = (rune_list *)malloc(sizeof(rune_list));
187                     $$->min = ($2 & charsetmask) | charsetbits;
188                     $$->max = ($2 & charsetmask) | charsetbits;
189                     $$->next = $1;
190                 }
191         |       list RUNE THRU RUNE
192                 {
193                     $$ = (rune_list *)malloc(sizeof(rune_list));
194                     $$->min = ($2 & charsetmask) | charsetbits;
195                     $$->max = ($4 & charsetmask) | charsetbits;
196                     $$->next = $1;
197                 }
198         ;
199
200 map     :       LBRK RUNE RUNE RBRK
201                 {
202                     $$ = (rune_list *)malloc(sizeof(rune_list));
203                     $$->min = ($2 & charsetmask) | charsetbits;
204                     $$->max = ($2 & charsetmask) | charsetbits;
205                     $$->map = $3;
206                     $$->next = 0;
207                 }
208         |       map LBRK RUNE RUNE RBRK
209                 {
210                     $$ = (rune_list *)malloc(sizeof(rune_list));
211                     $$->min = ($3 & charsetmask) | charsetbits;
212                     $$->max = ($3 & charsetmask) | charsetbits;
213                     $$->map = $4;
214                     $$->next = $1;
215                 }
216         |       LBRK RUNE THRU RUNE ':' RUNE RBRK
217                 {
218                     $$ = (rune_list *)malloc(sizeof(rune_list));
219                     $$->min = ($2 & charsetmask) | charsetbits;
220                     $$->max = ($4 & charsetmask) | charsetbits;
221                     $$->map = $6;
222                     $$->next = 0;
223                 }
224         |       map LBRK RUNE THRU RUNE ':' RUNE RBRK
225                 {
226                     $$ = (rune_list *)malloc(sizeof(rune_list));
227                     $$->min = ($3 & charsetmask) | charsetbits;
228                     $$->max = ($5 & charsetmask) | charsetbits;
229                     $$->map = $7;
230                     $$->next = $1;
231                 }
232         ;
233 %%
234
235 int debug = 0;
236 FILE *ofile;
237
238 int
239 main(int ac, char *av[])
240 {
241     int x;
242
243     while ((x = getopt(ac, av, "do:")) != -1) {
244         switch(x) {
245         case 'd':
246             debug = 1;
247             break;
248         case 'o':
249             locale_file = optarg;
250             if ((ofile = fopen(locale_file, "w")) == 0)
251                 err(1, "unable to open output file %s", locale_file);
252             break;
253         default:
254         usage:
255             fprintf(stderr, "usage: mklocale [-d] [-o output] [source]\n");
256             exit(1);
257         }
258     }
259
260     switch (ac - optind) {
261     case 0:
262         break;
263     case 1:
264         if (freopen(av[optind], "r", stdin) == 0)
265             err(1, "unable to open input file %s", av[optind]);
266         break;
267     default:
268         goto usage;
269     }
270     for (x = 0; x < _NB_CACHED_RUNES; ++x) {
271         mapupper.map[x] = x;
272         maplower.map[x] = x;
273     }
274     new_locale.rl_invalid_rune = _NB_DEFAULT_INVALID_RUNE;
275     memcpy(new_locale.rl_magic, _NB_RUNE_MAGIC_1, sizeof(new_locale.rl_magic));
276
277     yyparse();
278
279     return 0;
280 }
281
282 int
283 yyerror(const char *s)
284 {
285     fprintf(stderr, "%s\n", s);
286
287     return 0;
288 }
289
290 void *
291 xmalloc(unsigned int sz)
292 {
293     void *r = malloc(sz);
294     if (!r) {
295         perror("xmalloc");
296         abort();
297     }
298     return(r);
299 }
300
301 uint32_t *
302 xlalloc(unsigned int sz)
303 {
304     uint32_t *r = (uint32_t *)malloc(sz * sizeof(uint32_t));
305     if (!r) {
306         perror("xlalloc");
307         abort();
308     }
309     return(r);
310 }
311
312 uint32_t *
313 xrelalloc(uint32_t *old, unsigned int sz)
314 {
315     uint32_t *r = (uint32_t *)realloc((char *)old, sz * sizeof(uint32_t));
316     if (!r) {
317         perror("xrelalloc");
318         abort();
319     }
320     return(r);
321 }
322
323 void
324 set_map(rune_map *map, rune_list *list, uint32_t flag)
325 {
326     list->map &= charsetmask;
327     list->map |= charsetbits;
328     while (list) {
329         rune_list *nlist = list->next;
330         add_map(map, list, flag);
331         list = nlist;
332     }
333 }
334
335 void
336 set_digitmap(rune_map *map, rune_list *list)
337 {
338     __nbrune_t i;
339
340     while (list) {
341         rune_list *nlist = list->next;
342         for (i = list->min; i <= list->max; ++i) {
343             if (list->map + (i - list->min)) {
344                 rune_list *tmp = (rune_list *)xmalloc(sizeof(rune_list));
345                 tmp->min = i;
346                 tmp->max = i;
347                 add_map(map, tmp, list->map + (i - list->min));
348             }
349         }
350         free(list);
351         list = nlist;
352     }
353 }
354
355 void
356 add_map(rune_map *map, rune_list *list, uint32_t flag)
357 {
358     __nbrune_t i;
359     rune_list *lr = 0;
360     rune_list *r;
361     __nbrune_t run;
362
363     while (list->min < _NB_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
562 dump_tables(void)
563 {
564     int n;
565     __nbrune_t x;
566     rune_list *list;
567     _FileRuneLocale file_new_locale;
568     FILE *fp = (ofile ? ofile : stdout);
569
570     memset(&file_new_locale, 0, sizeof(file_new_locale));
571
572     /*
573      * See if we can compress some of the istype arrays
574      */
575     for(list = types.root; list; list = list->next) {
576         list->map = list->types[0];
577         for (x = 1; x < list->max - list->min + 1; ++x) {
578             if (list->types[x] != list->map) {
579                 list->map = 0;
580                 break;
581             }
582         }
583     }
584
585     memcpy(&file_new_locale.frl_magic, new_locale.rl_magic,
586         sizeof(file_new_locale.frl_magic));
587     memcpy(&file_new_locale.frl_encoding, new_locale.rl_encoding,
588         sizeof(file_new_locale.frl_encoding));
589
590     file_new_locale.frl_invalid_rune = htonl(new_locale.rl_invalid_rune);
591
592     /*
593      * Fill in our tables.  Do this in network order so that
594      * diverse machines have a chance of sharing data.
595      * (Machines like Crays cannot share with little machines due to
596      *  word size.  Sigh.  We tried.)
597      */
598     for (x = 0; x < _NB_CACHED_RUNES; ++x) {
599         file_new_locale.frl_runetype[x] = htonl(types.map[x]);
600         file_new_locale.frl_maplower[x] = htonl(maplower.map[x]);
601         file_new_locale.frl_mapupper[x] = htonl(mapupper.map[x]);
602     }
603
604     /*
605      * Count up how many ranges we will need for each of the extents.
606      */
607     list = types.root;
608
609     while (list) {
610         new_locale.rl_runetype_ext.rr_nranges++;
611         list = list->next;
612     }
613     file_new_locale.frl_runetype_ext.frr_nranges =
614         htonl(new_locale.rl_runetype_ext.rr_nranges);
615
616     list = maplower.root;
617
618     while (list) {
619         new_locale.rl_maplower_ext.rr_nranges++;
620         list = list->next;
621     }
622     file_new_locale.frl_maplower_ext.frr_nranges =
623         htonl(new_locale.rl_maplower_ext.rr_nranges);
624
625     list = mapupper.root;
626
627     while (list) {
628         new_locale.rl_mapupper_ext.rr_nranges++;
629         list = list->next;
630     }
631     file_new_locale.frl_mapupper_ext.frr_nranges =
632         htonl(new_locale.rl_mapupper_ext.rr_nranges);
633
634     file_new_locale.frl_variable_len = htonl(new_locale.rl_variable_len);
635
636     /*
637      * Okay, we are now ready to write the new locale file.
638      */
639
640     /*
641      * PART 1: The _RuneLocale structure
642      */
643     if (fwrite((char *)&file_new_locale, sizeof(file_new_locale), 1, fp) != 1)
644         err(1, "writing _RuneLocale to %s", locale_file);
645     /*
646      * PART 2: The runetype_ext structures (not the actual tables)
647      */
648     for (list = types.root, n = 0; list != NULL; list = list->next, n++) {
649         _FileRuneEntry re;
650
651         memset(&re, 0, sizeof(re));
652         re.fre_min = htonl(list->min);
653         re.fre_max = htonl(list->max);
654         re.fre_map = htonl(list->map);
655
656         if (fwrite((char *)&re, sizeof(re), 1, fp) != 1)
657             err(1, "writing runetype_ext #%d to %s", n, locale_file);
658     }
659     /*
660      * PART 3: The maplower_ext structures
661      */
662     for (list = maplower.root, n = 0; list != NULL; list = list->next, n++) {
663         _FileRuneEntry re;
664
665         memset(&re, 0, sizeof(re));
666         re.fre_min = htonl(list->min);
667         re.fre_max = htonl(list->max);
668         re.fre_map = htonl(list->map);
669
670         if (fwrite((char *)&re, sizeof(re), 1, fp) != 1)
671             err(1, "writing maplower_ext #%d to %s", n, locale_file);
672     }
673     /*
674      * PART 4: The mapupper_ext structures
675      */
676     for (list = mapupper.root, n = 0; list != NULL; list = list->next, n++) {
677         _FileRuneEntry re;
678
679         memset(&re, 0, sizeof(re));
680         re.fre_min = htonl(list->min);
681         re.fre_max = htonl(list->max);
682         re.fre_map = htonl(list->map);
683
684         if (fwrite((char *)&re, sizeof(re), 1, fp) != 1)
685             err(1, "writing mapupper_ext #%d to %s", n, locale_file);
686     }
687     /*
688      * PART 5: The runetype_ext tables
689      */
690     for (list = types.root, n = 0; list != NULL; list = list->next, n++) {
691         for (x = 0; x < list->max - list->min + 1; ++x)
692             list->types[x] = htonl(list->types[x]);
693
694         if (!list->map) {
695             if (fwrite((char *)list->types,
696                        (list->max - list->min + 1) * sizeof(uint32_t),
697                        1, fp) != 1)
698                 err(1, "writing runetype_ext table #%d to %s", n, locale_file);
699         }
700     }
701     /*
702      * PART 5: And finally the variable data
703      */
704     if (new_locale.rl_variable_len != 0 &&
705         fwrite((char *)new_locale.rl_variable,
706                new_locale.rl_variable_len, 1, fp) != 1)
707         err(1, "writing variable data to %s", locale_file);
708     fclose(fp);
709
710     if (!debug)
711         return;
712
713     if (new_locale.rl_encoding[0])
714         fprintf(stderr, "ENCODING       %s\n", new_locale.rl_encoding);
715     if (new_locale.rl_variable)
716         fprintf(stderr, "VARIABLE       %s\n",
717                 (char *)new_locale.rl_variable);
718
719     fprintf(stderr, "\nMAPLOWER:\n\n");
720
721     for (x = 0; x < _NB_CACHED_RUNES; ++x) {
722         if (isprint(maplower.map[x]))
723             fprintf(stderr, " '%c'", (int)maplower.map[x]);
724         else if (maplower.map[x])
725             fprintf(stderr, "%04x", maplower.map[x]);
726         else
727             fprintf(stderr, "%4x", 0);
728         if ((x & 0xf) == 0xf)
729             fprintf(stderr, "\n");
730         else
731             fprintf(stderr, " ");
732     }
733     fprintf(stderr, "\n");
734
735     for (list = maplower.root; list; list = list->next)
736         fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map);
737
738     fprintf(stderr, "\nMAPUPPER:\n\n");
739
740     for (x = 0; x < _NB_CACHED_RUNES; ++x) {
741         if (isprint(mapupper.map[x]))
742             fprintf(stderr, " '%c'", (int)mapupper.map[x]);
743         else if (mapupper.map[x])
744             fprintf(stderr, "%04x", mapupper.map[x]);
745         else
746             fprintf(stderr, "%4x", 0);
747         if ((x & 0xf) == 0xf)
748             fprintf(stderr, "\n");
749         else
750             fprintf(stderr, " ");
751     }
752     fprintf(stderr, "\n");
753
754     for (list = mapupper.root; list; list = list->next)
755         fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map);
756
757
758     fprintf(stderr, "\nTYPES:\n\n");
759
760     for (x = 0; x < _NB_CACHED_RUNES; ++x) {
761         uint32_t r = types.map[x];
762
763         if (r) {
764             if (isprint(x))
765                 fprintf(stderr, " '%c':%2d", x, (int)(r & 0xff));
766             else
767                 fprintf(stderr, "%04x:%2d", x, (int)(r & 0xff));
768
769             fprintf(stderr, " %4s", (r & _RUNETYPE_A) ? "alph" : "");
770             fprintf(stderr, " %4s", (r & _RUNETYPE_C) ? "ctrl" : "");
771             fprintf(stderr, " %4s", (r & _RUNETYPE_D) ? "dig" : "");
772             fprintf(stderr, " %4s", (r & _RUNETYPE_G) ? "graf" : "");
773             fprintf(stderr, " %4s", (r & _RUNETYPE_L) ? "low" : "");
774             fprintf(stderr, " %4s", (r & _RUNETYPE_P) ? "punc" : "");
775             fprintf(stderr, " %4s", (r & _RUNETYPE_S) ? "spac" : "");
776             fprintf(stderr, " %4s", (r & _RUNETYPE_U) ? "upp" : "");
777             fprintf(stderr, " %4s", (r & _RUNETYPE_X) ? "xdig" : "");
778             fprintf(stderr, " %4s", (r & _RUNETYPE_B) ? "blnk" : "");
779             fprintf(stderr, " %4s", (r & _RUNETYPE_R) ? "prnt" : "");
780             fprintf(stderr, " %4s", (r & _RUNETYPE_I) ? "ideo" : "");
781             fprintf(stderr, " %4s", (r & _RUNETYPE_T) ? "spec" : "");
782             fprintf(stderr, " %4s", (r & _RUNETYPE_Q) ? "phon" : "");
783             fprintf(stderr, "\n");
784         }
785     }
786
787     for (list = types.root; list; list = list->next) {
788         if (list->map && list->min + 3 < list->max) {
789             uint32_t r = list->map;
790
791             fprintf(stderr, "%04x:%2d", list->min, r & 0xff);
792
793             fprintf(stderr, " %4s", (r & _RUNETYPE_A) ? "alph" : "");
794             fprintf(stderr, " %4s", (r & _RUNETYPE_C) ? "ctrl" : "");
795             fprintf(stderr, " %4s", (r & _RUNETYPE_D) ? "dig" : "");
796             fprintf(stderr, " %4s", (r & _RUNETYPE_G) ? "graf" : "");
797             fprintf(stderr, " %4s", (r & _RUNETYPE_L) ? "low" : "");
798             fprintf(stderr, " %4s", (r & _RUNETYPE_P) ? "punc" : "");
799             fprintf(stderr, " %4s", (r & _RUNETYPE_S) ? "spac" : "");
800             fprintf(stderr, " %4s", (r & _RUNETYPE_U) ? "upp" : "");
801             fprintf(stderr, " %4s", (r & _RUNETYPE_X) ? "xdig" : "");
802             fprintf(stderr, " %4s", (r & _RUNETYPE_B) ? "blnk" : "");
803             fprintf(stderr, " %4s", (r & _RUNETYPE_R) ? "prnt" : "");
804             fprintf(stderr, " %4s", (r & _RUNETYPE_I) ? "ideo" : "");
805             fprintf(stderr, " %4s", (r & _RUNETYPE_T) ? "spec" : "");
806             fprintf(stderr, " %4s", (r & _RUNETYPE_Q) ? "phon" : "");
807             fprintf(stderr, "\n...\n");
808
809             fprintf(stderr, "%04x:%2d", list->max, r & 0xff);
810
811             fprintf(stderr, " %4s", (r & _RUNETYPE_A) ? "alph" : "");
812             fprintf(stderr, " %4s", (r & _RUNETYPE_C) ? "ctrl" : "");
813             fprintf(stderr, " %4s", (r & _RUNETYPE_D) ? "dig" : "");
814             fprintf(stderr, " %4s", (r & _RUNETYPE_G) ? "graf" : "");
815             fprintf(stderr, " %4s", (r & _RUNETYPE_L) ? "low" : "");
816             fprintf(stderr, " %4s", (r & _RUNETYPE_P) ? "punc" : "");
817             fprintf(stderr, " %4s", (r & _RUNETYPE_S) ? "spac" : "");
818             fprintf(stderr, " %4s", (r & _RUNETYPE_U) ? "upp" : "");
819             fprintf(stderr, " %4s", (r & _RUNETYPE_X) ? "xdig" : "");
820             fprintf(stderr, " %4s", (r & _RUNETYPE_B) ? "blnk" : "");
821             fprintf(stderr, " %4s", (r & _RUNETYPE_R) ? "prnt" : "");
822             fprintf(stderr, " %4s", (r & _RUNETYPE_I) ? "ideo" : "");
823             fprintf(stderr, " %4s", (r & _RUNETYPE_T) ? "spec" : "");
824             fprintf(stderr, " %4s", (r & _RUNETYPE_Q) ? "phon" : "");
825             fprintf(stderr, " %1u", (unsigned)((r & _RUNETYPE_SWM)>>_RUNETYPE_SWS));
826             fprintf(stderr, "\n");
827         } else 
828         for (x = list->min; x <= list->max; ++x) {
829             uint32_t r = ntohl(list->types[x - list->min]);
830
831             if (r) {
832                 fprintf(stderr, "%04x:%2d", x, (int)(r & 0xff));
833
834                 fprintf(stderr, " %4s", (r & _RUNETYPE_A) ? "alph" : "");
835                 fprintf(stderr, " %4s", (r & _RUNETYPE_C) ? "ctrl" : "");
836                 fprintf(stderr, " %4s", (r & _RUNETYPE_D) ? "dig" : "");
837                 fprintf(stderr, " %4s", (r & _RUNETYPE_G) ? "graf" : "");
838                 fprintf(stderr, " %4s", (r & _RUNETYPE_L) ? "low" : "");
839                 fprintf(stderr, " %4s", (r & _RUNETYPE_P) ? "punc" : "");
840                 fprintf(stderr, " %4s", (r & _RUNETYPE_S) ? "spac" : "");
841                 fprintf(stderr, " %4s", (r & _RUNETYPE_U) ? "upp" : "");
842                 fprintf(stderr, " %4s", (r & _RUNETYPE_X) ? "xdig" : "");
843                 fprintf(stderr, " %4s", (r & _RUNETYPE_B) ? "blnk" : "");
844                 fprintf(stderr, " %4s", (r & _RUNETYPE_R) ? "prnt" : "");
845                 fprintf(stderr, " %4s", (r & _RUNETYPE_I) ? "ideo" : "");
846                 fprintf(stderr, " %4s", (r & _RUNETYPE_T) ? "spec" : "");
847                 fprintf(stderr, " %4s", (r & _RUNETYPE_Q) ? "phon" : "");
848                 fprintf(stderr, " %1u", (unsigned)((r & _RUNETYPE_SWM)>>_RUNETYPE_SWS));
849                 fprintf(stderr, "\n");
850             }
851         }
852     }
853 }