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