xref: /csrg-svn/usr.bin/mklocale/yacc.y (revision 62124)
160624Sbostic %{
260624Sbostic /*-
3*62124Sbostic  * Copyright (c) 1993
4*62124Sbostic  *	The Regents of the University of California.  All rights reserved.
560624Sbostic  *
660624Sbostic  * This code is derived from software contributed to Berkeley by
760624Sbostic  * Paul Borman at Krystal Technologies.
860624Sbostic  *
960624Sbostic  * %sccs.include.redist.c%
1060624Sbostic  */
1160624Sbostic 
1260624Sbostic #ifndef lint
13*62124Sbostic static char sccsid[] = "@(#)yacc.y	8.1 (Berkeley) 06/06/93";
1460624Sbostic #endif /* not lint */
1560624Sbostic 
1660624Sbostic #include <ctype.h>
1760624Sbostic #include <rune.h>
1860624Sbostic #include <stddef.h>
1960624Sbostic #include <stdio.h>
2060624Sbostic #include <stdlib.h>
2160624Sbostic 
2260624Sbostic #include "ldef.h"
2360624Sbostic 
2460624Sbostic char	*locale_file = "<stdout>";
2560624Sbostic 
2660624Sbostic rune_map	maplower = { 0, };
2760624Sbostic rune_map	mapupper = { 0, };
2860624Sbostic rune_map	types = { 0, };
2960624Sbostic 
3060624Sbostic _RuneLocale	new_locale = { 0, };
3160624Sbostic 
3260624Sbostic void set_map __P((rune_map *, rune_list *, u_long));
3360624Sbostic void set_digitmap __P((rune_map *, rune_list *));
3460624Sbostic void add_map __P((rune_map *, rune_list *, u_long));
3560624Sbostic %}
3660624Sbostic 
3760624Sbostic %union	{
3860624Sbostic     rune_t	rune;
3960624Sbostic     int		i;
4060624Sbostic     char	*str;
4160624Sbostic 
4260624Sbostic     rune_list	*list;
4360624Sbostic }
4460624Sbostic 
4560624Sbostic %token	<rune>	RUNE
4660624Sbostic %token		LBRK
4760624Sbostic %token		RBRK
4860624Sbostic %token		THRU
4960624Sbostic %token		MAPLOWER
5060624Sbostic %token		MAPUPPER
5160624Sbostic %token		DIGITMAP
5260624Sbostic %token	<i>	LIST
5360624Sbostic %token	<str>	VARIABLE
5460624Sbostic %token		ENCODING
5560624Sbostic %token		INVALID
5660624Sbostic %token	<str>	STRING
5760624Sbostic 
5860624Sbostic %type	<list>	list
5960624Sbostic %type	<list>	map
6060624Sbostic 
6160624Sbostic 
6260624Sbostic %%
6360624Sbostic 
6460624Sbostic locale	:	/* empty */
6560624Sbostic 	|	table
6660624Sbostic 	    	{ dump_tables(); }
6760624Sbostic 	;
6860624Sbostic 
6960624Sbostic table	:	entry
7060624Sbostic 	|	table entry
7160624Sbostic 	;
7260624Sbostic 
7360624Sbostic entry	:	ENCODING STRING
7460624Sbostic 		{ strncpy(new_locale.encoding, $2, sizeof(new_locale.encoding)); }
7560624Sbostic 	|	VARIABLE
7660624Sbostic 		{ new_locale.variable_len = strlen($1) + 1;
7760624Sbostic 		  new_locale.variable = malloc(new_locale.variable_len);
7860624Sbostic 		  strcpy((char *)new_locale.variable, $1);
7960624Sbostic 		}
8060624Sbostic 	|	INVALID RUNE
8160624Sbostic 		{ new_locale.invalid_rune = $2; }
8260624Sbostic 	|	LIST list
8360624Sbostic 		{ set_map(&types, $2, $1); }
8460624Sbostic 	|	MAPLOWER map
8560624Sbostic 		{ set_map(&maplower, $2, 0); }
8660624Sbostic 	|	MAPUPPER map
8760624Sbostic 		{ set_map(&mapupper, $2, 0); }
8860624Sbostic 	|	DIGITMAP map
8960624Sbostic 		{ set_digitmap(&types, $2); }
9060624Sbostic 	;
9160624Sbostic 
9260624Sbostic list	:	RUNE
9360624Sbostic 		{
9460624Sbostic 		    $$ = (rune_list *)malloc(sizeof(rune_list));
9560624Sbostic 		    $$->min = $1;
9660624Sbostic 		    $$->max = $1;
9760624Sbostic 		    $$->next = 0;
9860624Sbostic 		}
9960624Sbostic 	|	RUNE THRU RUNE
10060624Sbostic 		{
10160624Sbostic 		    $$ = (rune_list *)malloc(sizeof(rune_list));
10260624Sbostic 		    $$->min = $1;
10360624Sbostic 		    $$->max = $3;
10460624Sbostic 		    $$->next = 0;
10560624Sbostic 		}
10660624Sbostic 	|	list RUNE
10760624Sbostic 		{
10860624Sbostic 		    $$ = (rune_list *)malloc(sizeof(rune_list));
10960624Sbostic 		    $$->min = $2;
11060624Sbostic 		    $$->max = $2;
11160624Sbostic 		    $$->next = $1;
11260624Sbostic 		}
11360624Sbostic 	|	list RUNE THRU RUNE
11460624Sbostic 		{
11560624Sbostic 		    $$ = (rune_list *)malloc(sizeof(rune_list));
11660624Sbostic 		    $$->min = $2;
11760624Sbostic 		    $$->max = $4;
11860624Sbostic 		    $$->next = $1;
11960624Sbostic 		}
12060624Sbostic 	;
12160624Sbostic 
12260624Sbostic map	:	LBRK RUNE RUNE RBRK
12360624Sbostic 		{
12460624Sbostic 		    $$ = (rune_list *)malloc(sizeof(rune_list));
12560624Sbostic 		    $$->min = $2;
12660624Sbostic 		    $$->max = $2;
12760624Sbostic 		    $$->map = $3;
12860624Sbostic 		    $$->next = 0;
12960624Sbostic 		}
13060624Sbostic 	|	map LBRK RUNE RUNE RBRK
13160624Sbostic 		{
13260624Sbostic 		    $$ = (rune_list *)malloc(sizeof(rune_list));
13360624Sbostic 		    $$->min = $3;
13460624Sbostic 		    $$->max = $3;
13560624Sbostic 		    $$->map = $4;
13660624Sbostic 		    $$->next = $1;
13760624Sbostic 		}
13860624Sbostic 	|	LBRK RUNE THRU RUNE ':' RUNE RBRK
13960624Sbostic 		{
14060624Sbostic 		    $$ = (rune_list *)malloc(sizeof(rune_list));
14160624Sbostic 		    $$->min = $2;
14260624Sbostic 		    $$->max = $4;
14360624Sbostic 		    $$->map = $6;
14460624Sbostic 		    $$->next = 0;
14560624Sbostic 		}
14660624Sbostic 	|	map LBRK RUNE THRU RUNE ':' RUNE RBRK
14760624Sbostic 		{
14860624Sbostic 		    $$ = (rune_list *)malloc(sizeof(rune_list));
14960624Sbostic 		    $$->min = $3;
15060624Sbostic 		    $$->max = $5;
15160624Sbostic 		    $$->map = $7;
15260624Sbostic 		    $$->next = $1;
15360624Sbostic 		}
15460624Sbostic 	;
15560624Sbostic %%
15660624Sbostic 
15760624Sbostic int debug = 0;
15860624Sbostic FILE *fp = stdout;
15960624Sbostic 
main(ac,av)16060624Sbostic main(ac, av)
16160624Sbostic 	int ac;
16260624Sbostic 	char *av[];
16360624Sbostic {
16460624Sbostic     int x;
16560624Sbostic 
16660624Sbostic     extern char *optarg;
16760624Sbostic     extern int optind;
16860624Sbostic 
16960624Sbostic     while ((x = getopt(ac, av, "do:")) != EOF) {
17060624Sbostic 	switch(x) {
17160624Sbostic 	case 'd':
17260624Sbostic 	    debug = 1;
17360624Sbostic 	    break;
17460624Sbostic 	case 'o':
17560624Sbostic 	    locale_file = optarg;
17660624Sbostic 	    if ((fp = fopen(locale_file, "w")) == 0) {
17760624Sbostic 		perror(locale_file);
17860624Sbostic 		exit(1);
17960624Sbostic 	    }
18060624Sbostic 	    break;
18160624Sbostic 	default:
18260624Sbostic 	usage:
18360624Sbostic 	    fprintf(stderr, "Usage: mklocale [-d] [-o output] [source]\n");
18460624Sbostic 	    exit(1);
18560624Sbostic 	}
18660624Sbostic     }
18760624Sbostic 
18860624Sbostic     switch (ac - optind) {
18960624Sbostic     case 0:
19060624Sbostic 	break;
19160624Sbostic     case 1:
19260624Sbostic 	if (freopen(av[optind], "r", stdin) == 0) {
19360624Sbostic 	    perror(av[optind]);
19460624Sbostic 	    exit(1);
19560624Sbostic 	}
19660624Sbostic 	break;
19760624Sbostic     default:
19860624Sbostic 	goto usage;
19960624Sbostic     }
20060624Sbostic     for (x = 0; x < _CACHED_RUNES; ++x) {
20160624Sbostic 	mapupper.map[x] = x;
20260624Sbostic 	maplower.map[x] = x;
20360624Sbostic     }
20460624Sbostic     new_locale.invalid_rune = _INVALID_RUNE;
20560624Sbostic     memcpy(new_locale.magic, _RUNE_MAGIC_1, sizeof(new_locale.magic));
20660624Sbostic 
20760624Sbostic     yyparse();
20860624Sbostic }
20960624Sbostic 
yyerror(s)21060624Sbostic yyerror(s)
21160624Sbostic 	char *s;
21260624Sbostic {
21360624Sbostic     fprintf(stderr, "%s\n", s);
21460624Sbostic }
21560624Sbostic 
21660624Sbostic void *
xmalloc(sz)21760624Sbostic xmalloc(sz)
21860624Sbostic 	unsigned int sz;
21960624Sbostic {
22060624Sbostic     void *r = malloc(sz);
22160624Sbostic     if (!r) {
22260624Sbostic 	perror("xmalloc");
22360624Sbostic 	abort();
22460624Sbostic     }
22560624Sbostic     return(r);
22660624Sbostic }
22760624Sbostic 
22860624Sbostic u_long *
xlalloc(sz)22960624Sbostic xlalloc(sz)
23060624Sbostic 	unsigned int sz;
23160624Sbostic {
23260624Sbostic     u_long *r = (u_long *)malloc(sz * sizeof(u_long));
23360624Sbostic     if (!r) {
23460624Sbostic 	perror("xlalloc");
23560624Sbostic 	abort();
23660624Sbostic     }
23760624Sbostic     return(r);
23860624Sbostic }
23960624Sbostic 
24060624Sbostic u_long *
xrelalloc(old,sz)24160624Sbostic xrelalloc(old, sz)
24260624Sbostic 	u_long *old;
24360624Sbostic 	unsigned int sz;
24460624Sbostic {
24560624Sbostic     u_long *r = (u_long *)realloc((char *)old, sz * sizeof(u_long));
24660624Sbostic     if (!r) {
24760624Sbostic 	perror("xrelalloc");
24860624Sbostic 	abort();
24960624Sbostic     }
25060624Sbostic     return(r);
25160624Sbostic }
25260624Sbostic 
25360624Sbostic void
set_map(map,list,flag)25460624Sbostic set_map(map, list, flag)
25560624Sbostic 	rune_map *map;
25660624Sbostic 	rune_list *list;
25760624Sbostic 	u_long flag;
25860624Sbostic {
25960624Sbostic     while (list) {
26060624Sbostic 	rune_list *nlist = list->next;
26160624Sbostic 	add_map(map, list, flag);
26260624Sbostic 	list = nlist;
26360624Sbostic     }
26460624Sbostic }
26560624Sbostic 
26660624Sbostic void
set_digitmap(map,list)26760624Sbostic set_digitmap(map, list)
26860624Sbostic 	rune_map *map;
26960624Sbostic 	rune_list *list;
27060624Sbostic {
27160624Sbostic     rune_t i;
27260624Sbostic 
27360624Sbostic     while (list) {
27460624Sbostic 	rune_list *nlist = list->next;
27560624Sbostic 	for (i = list->min; i <= list->max; ++i) {
27660624Sbostic 	    if (list->map + (i - list->min)) {
27760624Sbostic 		rune_list *tmp = (rune_list *)xmalloc(sizeof(rune_list));
27860624Sbostic 		tmp->min = i;
27960624Sbostic 		tmp->max = i;
28060624Sbostic 		add_map(map, tmp, list->map + (i - list->min));
28160624Sbostic 	    }
28260624Sbostic 	}
28360624Sbostic 	free(list);
28460624Sbostic 	list = nlist;
28560624Sbostic     }
28660624Sbostic }
28760624Sbostic 
28860624Sbostic void
add_map(map,list,flag)28960624Sbostic add_map(map, list, flag)
29060624Sbostic 	rune_map *map;
29160624Sbostic 	rune_list *list;
29260624Sbostic 	u_long flag;
29360624Sbostic {
29460624Sbostic     rune_t i;
29560624Sbostic     rune_list *lr = 0;
29660624Sbostic     rune_list *r;
29760624Sbostic     rune_t run;
29860624Sbostic 
29960624Sbostic     while (list->min < _CACHED_RUNES && list->min <= list->max) {
30060624Sbostic 	if (flag)
30160624Sbostic 	    map->map[list->min++] |= flag;
30260624Sbostic 	else
30360624Sbostic 	    map->map[list->min++] = list->map++;
30460624Sbostic     }
30560624Sbostic 
30660624Sbostic     if (list->min > list->max) {
30760624Sbostic 	free(list);
30860624Sbostic 	return;
30960624Sbostic     }
31060624Sbostic 
31160624Sbostic     run = list->max - list->min + 1;
31260624Sbostic 
31360624Sbostic     if (!(r = map->root) || (list->max < r->min - 1)
31460624Sbostic 			 || (!flag && list->max == r->min - 1)) {
31560624Sbostic 	if (flag) {
31660624Sbostic 	    list->types = xlalloc(run);
31760624Sbostic 	    for (i = 0; i < run; ++i)
31860624Sbostic 		list->types[i] = flag;
31960624Sbostic 	}
32060624Sbostic 	list->next = map->root;
32160624Sbostic 	map->root = list;
32260624Sbostic 	return;
32360624Sbostic     }
32460624Sbostic 
32560624Sbostic     for (r = map->root; r && r->max + 1 < list->min; r = r->next)
32660624Sbostic 	lr = r;
32760624Sbostic 
32860624Sbostic     if (!r) {
32960624Sbostic 	/*
33060624Sbostic 	 * We are off the end.
33160624Sbostic 	 */
33260624Sbostic 	if (flag) {
33360624Sbostic 	    list->types = xlalloc(run);
33460624Sbostic 	    for (i = 0; i < run; ++i)
33560624Sbostic 		list->types[i] = flag;
33660624Sbostic 	}
33760624Sbostic 	list->next = 0;
33860624Sbostic 	lr->next = list;
33960624Sbostic 	return;
34060624Sbostic     }
34160624Sbostic 
34260624Sbostic     if (list->max < r->min - 1) {
34360624Sbostic 	/*
34460624Sbostic 	 * We come before this range and we do not intersect it.
34560624Sbostic 	 * We are not before the root node, it was checked before the loop
34660624Sbostic 	 */
34760624Sbostic 	if (flag) {
34860624Sbostic 	    list->types = xlalloc(run);
34960624Sbostic 	    for (i = 0; i < run; ++i)
35060624Sbostic 		list->types[i] = flag;
35160624Sbostic 	}
35260624Sbostic 	list->next = lr->next;
35360624Sbostic 	lr->next = list;
35460624Sbostic 	return;
35560624Sbostic     }
35660624Sbostic 
35760624Sbostic     /*
35860624Sbostic      * At this point we have found that we at least intersect with
35960624Sbostic      * the range pointed to by `r', we might intersect with one or
36060624Sbostic      * more ranges beyond `r' as well.
36160624Sbostic      */
36260624Sbostic 
36360624Sbostic     if (!flag && list->map - list->min != r->map - r->min) {
36460624Sbostic 	/*
36560624Sbostic 	 * There are only two cases when we are doing case maps and
36660624Sbostic 	 * our maps needn't have the same offset.  When we are adjoining
36760624Sbostic 	 * but not intersecting.
36860624Sbostic 	 */
36960624Sbostic 	if (list->max + 1 == r->min) {
37060624Sbostic 	    lr->next = list;
37160624Sbostic 	    list->next = r;
37260624Sbostic 	    return;
37360624Sbostic 	}
37460624Sbostic 	if (list->min - 1 == r->max) {
37560624Sbostic 	    list->next = r->next;
37660624Sbostic 	    r->next = list;
37760624Sbostic 	    return;
37860624Sbostic 	}
37960624Sbostic 	fprintf(stderr, "Error: conflicting map entries\n");
38060624Sbostic 	exit(1);
38160624Sbostic     }
38260624Sbostic 
38360624Sbostic     if (list->min >= r->min && list->max <= r->max) {
38460624Sbostic 	/*
38560624Sbostic 	 * Subset case.
38660624Sbostic 	 */
38760624Sbostic 
38860624Sbostic 	if (flag) {
38960624Sbostic 	    for (i = list->min; i <= list->max; ++i)
39060624Sbostic 		r->types[i - r->min] |= flag;
39160624Sbostic 	}
39260624Sbostic 	free(list);
39360624Sbostic 	return;
39460624Sbostic     }
39560624Sbostic     if (list->min <= r->min && list->max >= r->max) {
39660624Sbostic 	/*
39760624Sbostic 	 * Superset case.  Make him big enough to hold us.
39860624Sbostic 	 * We might need to merge with the guy after him.
39960624Sbostic 	 */
40060624Sbostic 	if (flag) {
40160624Sbostic 	    list->types = xlalloc(list->max - list->min + 1);
40260624Sbostic 
40360624Sbostic 	    for (i = list->min; i <= list->max; ++i)
40460624Sbostic 		list->types[i - list->min] = flag;
40560624Sbostic 
40660624Sbostic 	    for (i = r->min; i <= r->max; ++i)
40760624Sbostic 		list->types[i - list->min] |= r->types[i - r->min];
40860624Sbostic 
40960624Sbostic 	    free(r->types);
41060624Sbostic 	    r->types = list->types;
41160624Sbostic 	} else {
41260624Sbostic 	    r->map = list->map;
41360624Sbostic 	}
41460624Sbostic 	r->min = list->min;
41560624Sbostic 	r->max = list->max;
41660624Sbostic 	free(list);
41760624Sbostic     } else if (list->min < r->min) {
41860624Sbostic 	/*
41960624Sbostic 	 * Our tail intersects his head.
42060624Sbostic 	 */
42160624Sbostic 	if (flag) {
42260624Sbostic 	    list->types = xlalloc(r->max - list->min + 1);
42360624Sbostic 
42460624Sbostic 	    for (i = r->min; i <= r->max; ++i)
42560624Sbostic 		list->types[i - list->min] = r->types[i - r->min];
42660624Sbostic 
42760624Sbostic 	    for (i = list->min; i < r->min; ++i)
42860624Sbostic 		list->types[i - list->min] = flag;
42960624Sbostic 
43060624Sbostic 	    for (i = r->min; i <= list->max; ++i)
43160624Sbostic 		list->types[i - list->min] |= flag;
43260624Sbostic 
43360624Sbostic 	    free(r->types);
43460624Sbostic 	    r->types = list->types;
43560624Sbostic 	} else {
43660624Sbostic 	    r->map = list->map;
43760624Sbostic 	}
43860624Sbostic 	r->min = list->min;
43960624Sbostic 	free(list);
44060624Sbostic 	return;
44160624Sbostic     } else {
44260624Sbostic 	/*
44360624Sbostic 	 * Our head intersects his tail.
44460624Sbostic 	 * We might need to merge with the guy after him.
44560624Sbostic 	 */
44660624Sbostic 	if (flag) {
44760624Sbostic 	    r->types = xrelalloc(r->types, list->max - r->min + 1);
44860624Sbostic 
44960624Sbostic 	    for (i = list->min; i <= r->max; ++i)
45060624Sbostic 		r->types[i - r->min] |= flag;
45160624Sbostic 
45260624Sbostic 	    for (i = r->max+1; i <= list->max; ++i)
45360624Sbostic 		r->types[i - r->min] = flag;
45460624Sbostic 	}
45560624Sbostic 	r->max = r->max;
45660624Sbostic 	free(list);
45760624Sbostic     }
45860624Sbostic 
45960624Sbostic     /*
46060624Sbostic      * Okay, check to see if we grew into the next guy(s)
46160624Sbostic      */
46260624Sbostic     while ((lr = r->next) && r->max >= lr->min) {
46360624Sbostic 	if (flag) {
46460624Sbostic 	    if (r->max >= lr->max) {
46560624Sbostic 		/*
46660624Sbostic 		 * Good, we consumed all of him.
46760624Sbostic 		 */
46860624Sbostic 		for (i = lr->min; i <= lr->max; ++i)
46960624Sbostic 		    r->types[i - r->min] |= lr->types[i - lr->min];
47060624Sbostic 	    } else {
47160624Sbostic 		/*
47260624Sbostic 		 * "append" him on to the end of us.
47360624Sbostic 		 */
47460624Sbostic 		r->types = xrelalloc(r->types, lr->max - r->min + 1);
47560624Sbostic 
47660624Sbostic 		for (i = lr->min; i <= r->max; ++i)
47760624Sbostic 		    r->types[i - r->min] |= lr->types[i - lr->min];
47860624Sbostic 
47960624Sbostic 		for (i = r->max+1; i <= lr->max; ++i)
48060624Sbostic 		    r->types[i - r->min] = lr->types[i - lr->min];
48160624Sbostic 
48260624Sbostic 		r->max = lr->max;
48360624Sbostic 	    }
48460624Sbostic 	} else {
48560624Sbostic 	    if (lr->max > r->max)
48660624Sbostic 		r->max = lr->max;
48760624Sbostic 	}
48860624Sbostic 
48960624Sbostic 	r->next = lr->next;
49060624Sbostic 
49160624Sbostic 	if (flag)
49260624Sbostic 	    free(lr->types);
49360624Sbostic 	free(lr);
49460624Sbostic     }
49560624Sbostic }
49660624Sbostic 
49760624Sbostic void
dump_tables()49860624Sbostic dump_tables()
49960624Sbostic {
50060624Sbostic     int x;
50160624Sbostic     rune_list *list;
50260624Sbostic 
50360624Sbostic     /*
50460624Sbostic      * See if we can compress some of the istype arrays
50560624Sbostic      */
50660624Sbostic     for(list = types.root; list; list = list->next) {
50760624Sbostic 	list->map = list->types[0];
50860624Sbostic 	for (x = 1; x < list->max - list->min + 1; ++x) {
50960624Sbostic 	    if (list->types[x] != list->map) {
51060624Sbostic 		list->map = 0;
51160624Sbostic 		break;
51260624Sbostic 	    }
51360624Sbostic 	}
51460624Sbostic     }
51560624Sbostic 
51660624Sbostic     new_locale.invalid_rune = htonl(new_locale.invalid_rune);
51760624Sbostic 
51860624Sbostic     /*
51960624Sbostic      * Fill in our tables.  Do this in network order so that
52060624Sbostic      * diverse machines have a chance of sharing data.
52160624Sbostic      * (Machines like Crays cannot share with little machines due to
52260624Sbostic      *  word size.  Sigh.  We tried.)
52360624Sbostic      */
52460624Sbostic     for (x = 0; x < _CACHED_RUNES; ++x) {
52560624Sbostic 	new_locale.runetype[x] = htonl(types.map[x]);
52660624Sbostic 	new_locale.maplower[x] = htonl(maplower.map[x]);
52760624Sbostic 	new_locale.mapupper[x] = htonl(mapupper.map[x]);
52860624Sbostic     }
52960624Sbostic 
53060624Sbostic     /*
53160624Sbostic      * Count up how many ranges we will need for each of the extents.
53260624Sbostic      */
53360624Sbostic     list = types.root;
53460624Sbostic 
53560624Sbostic     while (list) {
53660624Sbostic 	new_locale.runetype_ext.nranges++;
53760624Sbostic 	list = list->next;
53860624Sbostic     }
53960624Sbostic     new_locale.runetype_ext.nranges = htonl(new_locale.runetype_ext.nranges);
54060624Sbostic 
54160624Sbostic     list = maplower.root;
54260624Sbostic 
54360624Sbostic     while (list) {
54460624Sbostic 	new_locale.maplower_ext.nranges++;
54560624Sbostic 	list = list->next;
54660624Sbostic     }
54760624Sbostic     new_locale.maplower_ext.nranges = htonl(new_locale.maplower_ext.nranges);
54860624Sbostic 
54960624Sbostic     list = mapupper.root;
55060624Sbostic 
55160624Sbostic     while (list) {
55260624Sbostic 	new_locale.mapupper_ext.nranges++;
55360624Sbostic 	list = list->next;
55460624Sbostic     }
55560624Sbostic     new_locale.mapupper_ext.nranges = htonl(new_locale.mapupper_ext.nranges);
55660624Sbostic 
55760624Sbostic     new_locale.variable_len = htonl(new_locale.variable_len);
55860624Sbostic 
55960624Sbostic     /*
56060624Sbostic      * Okay, we are now ready to write the new locale file.
56160624Sbostic      */
56260624Sbostic 
56360624Sbostic     /*
56460624Sbostic      * PART 1: The _RuneLocale structure
56560624Sbostic      */
56660624Sbostic     if (fwrite((char *)&new_locale, sizeof(new_locale), 1, fp) != 1) {
56760624Sbostic 	perror(locale_file);
56860624Sbostic 	exit(1);
56960624Sbostic     }
57060624Sbostic     /*
57160624Sbostic      * PART 2: The runetype_ext structures (not the actual tables)
57260624Sbostic      */
57360624Sbostic     list = types.root;
57460624Sbostic 
57560624Sbostic     while (list) {
57660624Sbostic 	_RuneEntry re;
57760624Sbostic 
57860624Sbostic 	re.min = htonl(list->min);
57960624Sbostic 	re.max = htonl(list->max);
58060624Sbostic 	re.map = htonl(list->map);
58160624Sbostic 
58260624Sbostic 	if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) {
58360624Sbostic 	    perror(locale_file);
58460624Sbostic 	    exit(1);
58560624Sbostic 	}
58660624Sbostic 
58760624Sbostic         list = list->next;
58860624Sbostic     }
58960624Sbostic     /*
59060624Sbostic      * PART 3: The maplower_ext structures
59160624Sbostic      */
59260624Sbostic     list = maplower.root;
59360624Sbostic 
59460624Sbostic     while (list) {
59560624Sbostic 	_RuneEntry re;
59660624Sbostic 
59760624Sbostic 	re.min = htonl(list->min);
59860624Sbostic 	re.max = htonl(list->max);
59960624Sbostic 	re.map = htonl(list->map);
60060624Sbostic 
60160624Sbostic 	if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) {
60260624Sbostic 	    perror(locale_file);
60360624Sbostic 	    exit(1);
60460624Sbostic 	}
60560624Sbostic 
60660624Sbostic         list = list->next;
60760624Sbostic     }
60860624Sbostic     /*
60960624Sbostic      * PART 4: The mapupper_ext structures
61060624Sbostic      */
61160624Sbostic     list = mapupper.root;
61260624Sbostic 
61360624Sbostic     while (list) {
61460624Sbostic 	_RuneEntry re;
61560624Sbostic 
61660624Sbostic 	re.min = htonl(list->min);
61760624Sbostic 	re.max = htonl(list->max);
61860624Sbostic 	re.map = htonl(list->map);
61960624Sbostic 
62060624Sbostic 	if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) {
62160624Sbostic 	    perror(locale_file);
62260624Sbostic 	    exit(1);
62360624Sbostic 	}
62460624Sbostic 
62560624Sbostic         list = list->next;
62660624Sbostic     }
62760624Sbostic     /*
62860624Sbostic      * PART 5: The runetype_ext tables
62960624Sbostic      */
63060624Sbostic     list = types.root;
63160624Sbostic 
63260624Sbostic     while (list) {
63360624Sbostic 	for (x = 0; x < list->max - list->min + 1; ++x)
63460624Sbostic 	    list->types[x] = htonl(list->types[x]);
63560624Sbostic 
63660624Sbostic 	if (!list->map) {
63760624Sbostic 	    if (fwrite((char *)&list->types,
63860624Sbostic 		(list->max - list->min + 1)*sizeof(u_long), 1, fp) != 1) {
63960624Sbostic 		perror(locale_file);
64060624Sbostic 		exit(1);
64160624Sbostic 	    }
64260624Sbostic 	}
64360624Sbostic         list = list->next;
64460624Sbostic     }
64560624Sbostic     /*
64660624Sbostic      * PART 5: And finally the variable data
64760624Sbostic      */
64860624Sbostic     if (fwrite((char *)new_locale.variable,
64960624Sbostic 	       ntohl(new_locale.variable_len), 1, fp) != 1) {
65060624Sbostic 	perror(locale_file);
65160624Sbostic 	exit(1);
65260624Sbostic     }
65360624Sbostic     fclose(fp);
65460624Sbostic 
65560624Sbostic     if (!debug)
65660624Sbostic 	return;
65760624Sbostic 
65860624Sbostic     if (new_locale.encoding[0])
65960624Sbostic 	fprintf(stderr, "ENCODING	%s\n", new_locale.encoding);
66060624Sbostic     if (new_locale.variable)
66160624Sbostic 	fprintf(stderr, "VARIABLE	%s\n", new_locale.variable);
66260624Sbostic 
66360624Sbostic     fprintf(stderr, "\nMAPLOWER:\n\n");
66460624Sbostic 
66560624Sbostic     for (x = 0; x < _CACHED_RUNES; ++x) {
66660624Sbostic 	if (isprint(maplower.map[x]))
66760624Sbostic 	    fprintf(stderr, " '%c'", maplower.map[x]);
66860624Sbostic 	else if (maplower.map[x])
66960624Sbostic 	    fprintf(stderr, "%04x", maplower.map[x]);
67060624Sbostic 	else
67160624Sbostic 	    fprintf(stderr, "%4x", 0);
67260624Sbostic 	if ((x & 0xf) == 0xf)
67360624Sbostic 	    fprintf(stderr, "\n");
67460624Sbostic 	else
67560624Sbostic 	    fprintf(stderr, " ");
67660624Sbostic     }
67760624Sbostic     fprintf(stderr, "\n");
67860624Sbostic 
67960624Sbostic     for (list = maplower.root; list; list = list->next)
68060624Sbostic 	fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map);
68160624Sbostic 
68260624Sbostic     fprintf(stderr, "\nMAPUPPER:\n\n");
68360624Sbostic 
68460624Sbostic     for (x = 0; x < _CACHED_RUNES; ++x) {
68560624Sbostic 	if (isprint(mapupper.map[x]))
68660624Sbostic 	    fprintf(stderr, " '%c'", mapupper.map[x]);
68760624Sbostic 	else if (mapupper.map[x])
68860624Sbostic 	    fprintf(stderr, "%04x", mapupper.map[x]);
68960624Sbostic 	else
69060624Sbostic 	    fprintf(stderr, "%4x", 0);
69160624Sbostic 	if ((x & 0xf) == 0xf)
69260624Sbostic 	    fprintf(stderr, "\n");
69360624Sbostic 	else
69460624Sbostic 	    fprintf(stderr, " ");
69560624Sbostic     }
69660624Sbostic     fprintf(stderr, "\n");
69760624Sbostic 
69860624Sbostic     for (list = mapupper.root; list; list = list->next)
69960624Sbostic 	fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map);
70060624Sbostic 
70160624Sbostic 
70260624Sbostic     fprintf(stderr, "\nTYPES:\n\n");
70360624Sbostic 
70460624Sbostic     for (x = 0; x < _CACHED_RUNES; ++x) {
70560624Sbostic 	u_long r = types.map[x];
70660624Sbostic 
70760624Sbostic 	if (r) {
70860624Sbostic 	    if (isprint(x))
70960624Sbostic 		fprintf(stderr, " '%c': %2d", x, r & 0xff);
71060624Sbostic 	    else
71160624Sbostic 		fprintf(stderr, "%04x: %2d", x, r & 0xff);
71260624Sbostic 
71360624Sbostic 	    fprintf(stderr, " %4s", (r & _A) ? "alph" : "");
71460624Sbostic 	    fprintf(stderr, " %4s", (r & _C) ? "ctrl" : "");
71560624Sbostic 	    fprintf(stderr, " %4s", (r & _D) ? "dig" : "");
71660624Sbostic 	    fprintf(stderr, " %4s", (r & _G) ? "graf" : "");
71760624Sbostic 	    fprintf(stderr, " %4s", (r & _L) ? "low" : "");
71860624Sbostic 	    fprintf(stderr, " %4s", (r & _P) ? "punc" : "");
71960624Sbostic 	    fprintf(stderr, " %4s", (r & _S) ? "spac" : "");
72060624Sbostic 	    fprintf(stderr, " %4s", (r & _U) ? "upp" : "");
72160624Sbostic 	    fprintf(stderr, " %4s", (r & _X) ? "xdig" : "");
72260624Sbostic 	    fprintf(stderr, " %4s", (r & _B) ? "blnk" : "");
72360624Sbostic 	    fprintf(stderr, " %4s", (r & _R) ? "prnt" : "");
72460624Sbostic 	    fprintf(stderr, " %4s", (r & _I) ? "ideo" : "");
72560624Sbostic 	    fprintf(stderr, " %4s", (r & _T) ? "spec" : "");
72660624Sbostic 	    fprintf(stderr, " %4s", (r & _Q) ? "phon" : "");
72760624Sbostic 	    fprintf(stderr, "\n");
72860624Sbostic 	}
72960624Sbostic     }
73060624Sbostic 
73160624Sbostic     for (list = types.root; list; list = list->next) {
73260624Sbostic 	if (list->map && list->min + 3 < list->max) {
73360624Sbostic 	    u_long r = list->map;
73460624Sbostic 
73560624Sbostic 	    fprintf(stderr, "%04x: %2d", list->min, r & 0xff);
73660624Sbostic 
73760624Sbostic 	    fprintf(stderr, " %4s", (r & _A) ? "alph" : "");
73860624Sbostic 	    fprintf(stderr, " %4s", (r & _C) ? "ctrl" : "");
73960624Sbostic 	    fprintf(stderr, " %4s", (r & _D) ? "dig" : "");
74060624Sbostic 	    fprintf(stderr, " %4s", (r & _G) ? "graf" : "");
74160624Sbostic 	    fprintf(stderr, " %4s", (r & _L) ? "low" : "");
74260624Sbostic 	    fprintf(stderr, " %4s", (r & _P) ? "punc" : "");
74360624Sbostic 	    fprintf(stderr, " %4s", (r & _S) ? "spac" : "");
74460624Sbostic 	    fprintf(stderr, " %4s", (r & _U) ? "upp" : "");
74560624Sbostic 	    fprintf(stderr, " %4s", (r & _X) ? "xdig" : "");
74660624Sbostic 	    fprintf(stderr, " %4s", (r & _B) ? "blnk" : "");
74760624Sbostic 	    fprintf(stderr, " %4s", (r & _R) ? "prnt" : "");
74860624Sbostic 	    fprintf(stderr, " %4s", (r & _I) ? "ideo" : "");
74960624Sbostic 	    fprintf(stderr, " %4s", (r & _T) ? "spec" : "");
75060624Sbostic 	    fprintf(stderr, " %4s", (r & _Q) ? "phon" : "");
75160624Sbostic 	    fprintf(stderr, "\n...\n");
75260624Sbostic 
75360624Sbostic 	    fprintf(stderr, "%04x: %2d", list->max, r & 0xff);
75460624Sbostic 
75560624Sbostic 	    fprintf(stderr, " %4s", (r & _A) ? "alph" : "");
75660624Sbostic 	    fprintf(stderr, " %4s", (r & _C) ? "ctrl" : "");
75760624Sbostic 	    fprintf(stderr, " %4s", (r & _D) ? "dig" : "");
75860624Sbostic 	    fprintf(stderr, " %4s", (r & _G) ? "graf" : "");
75960624Sbostic 	    fprintf(stderr, " %4s", (r & _L) ? "low" : "");
76060624Sbostic 	    fprintf(stderr, " %4s", (r & _P) ? "punc" : "");
76160624Sbostic 	    fprintf(stderr, " %4s", (r & _S) ? "spac" : "");
76260624Sbostic 	    fprintf(stderr, " %4s", (r & _U) ? "upp" : "");
76360624Sbostic 	    fprintf(stderr, " %4s", (r & _X) ? "xdig" : "");
76460624Sbostic 	    fprintf(stderr, " %4s", (r & _B) ? "blnk" : "");
76560624Sbostic 	    fprintf(stderr, " %4s", (r & _R) ? "prnt" : "");
76660624Sbostic 	    fprintf(stderr, " %4s", (r & _I) ? "ideo" : "");
76760624Sbostic 	    fprintf(stderr, " %4s", (r & _T) ? "spec" : "");
76860624Sbostic 	    fprintf(stderr, " %4s", (r & _Q) ? "phon" : "");
76960624Sbostic 	    fprintf(stderr, "\n");
77060624Sbostic 	} else
77160624Sbostic 	for (x = list->min; x <= list->max; ++x) {
77260624Sbostic 	    u_long r = ntohl(list->types[x - list->min]);
77360624Sbostic 
77460624Sbostic 	    if (r) {
77560624Sbostic 		fprintf(stderr, "%04x: %2d", x, r & 0xff);
77660624Sbostic 
77760624Sbostic 		fprintf(stderr, " %4s", (r & _A) ? "alph" : "");
77860624Sbostic 		fprintf(stderr, " %4s", (r & _C) ? "ctrl" : "");
77960624Sbostic 		fprintf(stderr, " %4s", (r & _D) ? "dig" : "");
78060624Sbostic 		fprintf(stderr, " %4s", (r & _G) ? "graf" : "");
78160624Sbostic 		fprintf(stderr, " %4s", (r & _L) ? "low" : "");
78260624Sbostic 		fprintf(stderr, " %4s", (r & _P) ? "punc" : "");
78360624Sbostic 		fprintf(stderr, " %4s", (r & _S) ? "spac" : "");
78460624Sbostic 		fprintf(stderr, " %4s", (r & _U) ? "upp" : "");
78560624Sbostic 		fprintf(stderr, " %4s", (r & _X) ? "xdig" : "");
78660624Sbostic 		fprintf(stderr, " %4s", (r & _B) ? "blnk" : "");
78760624Sbostic 		fprintf(stderr, " %4s", (r & _R) ? "prnt" : "");
78860624Sbostic 		fprintf(stderr, " %4s", (r & _I) ? "ideo" : "");
78960624Sbostic 		fprintf(stderr, " %4s", (r & _T) ? "spec" : "");
79060624Sbostic 		fprintf(stderr, " %4s", (r & _Q) ? "phon" : "");
79160624Sbostic 		fprintf(stderr, "\n");
79260624Sbostic 	    }
79360624Sbostic 	}
79460624Sbostic     }
79560624Sbostic }
796