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