xref: /onnv-gate/usr/src/lib/libast/common/port/lcgen.c (revision 4887:feebf9260c2e)
1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
18*4887Schin *                  David Korn <dgk@research.att.com>                   *
19*4887Schin *                   Phong Vo <kpv@research.att.com>                    *
20*4887Schin *                                                                      *
21*4887Schin ***********************************************************************/
22*4887Schin /*
23*4887Schin  * generate <lc.h> implementation tables from lc.tab
24*4887Schin  * this must make it through vanilla cc with no -last
25*4887Schin  *
26*4887Schin  *	# comment
27*4887Schin  *	:charset:
28*4887Schin  *		code	name	ms-codepage
29*4887Schin  *	:language:
30*4887Schin  *		code	name	alt1|alt2...	charset|... attr1|attr2|...
31*4887Schin  *		...
32*4887Schin  *	:territory:
33*4887Schin  *		code	name	lang1|lang2...
34*4887Schin  *	:abbreviation:
35*4887Schin  */
36*4887Schin 
37*4887Schin #include <stdio.h>
38*4887Schin #include <ctype.h>
39*4887Schin #ifdef __STDC__
40*4887Schin #include <stdlib.h>
41*4887Schin #include <string.h>
42*4887Schin #endif
43*4887Schin 
44*4887Schin typedef struct Link_s
45*4887Schin {
46*4887Schin 	struct Link_s*		next;
47*4887Schin 	char*			code;
48*4887Schin 	int			index;
49*4887Schin } Link_t;
50*4887Schin 
51*4887Schin typedef struct Table_s
52*4887Schin {
53*4887Schin 	Link_t*			root;
54*4887Schin 	int			count;
55*4887Schin } Table_t;
56*4887Schin 
57*4887Schin typedef struct Abbreviation_s
58*4887Schin {
59*4887Schin 	Link_t			link;
60*4887Schin 	char*			value;
61*4887Schin } Abbreviation_t;
62*4887Schin 
63*4887Schin typedef struct Attribute_s
64*4887Schin {
65*4887Schin 	Link_t			link;
66*4887Schin } Attribute_t;
67*4887Schin 
68*4887Schin typedef struct Attribute_list_s
69*4887Schin {
70*4887Schin 	struct Attribute_list_s*next;
71*4887Schin 	Attribute_t*		attribute;
72*4887Schin } Attribute_list_t;
73*4887Schin 
74*4887Schin typedef struct Charset_s
75*4887Schin {
76*4887Schin 	Link_t			link;
77*4887Schin 	char*			alternates;
78*4887Schin 	char*			ms;
79*4887Schin } Charset_t;
80*4887Schin 
81*4887Schin typedef struct Language_s
82*4887Schin {
83*4887Schin 	Link_t			link;
84*4887Schin 	char*			name;
85*4887Schin 	char*			alternates;
86*4887Schin 	Charset_t*		charset;
87*4887Schin 	Attribute_list_t*	attributes;
88*4887Schin } Language_t;
89*4887Schin 
90*4887Schin typedef struct Language_list_s
91*4887Schin {
92*4887Schin 	struct Language_list_s*	next;
93*4887Schin 	Language_t*		language;
94*4887Schin } Language_list_t;
95*4887Schin 
96*4887Schin typedef struct Territory_s
97*4887Schin {
98*4887Schin 	Link_t			link;
99*4887Schin 	char*			name;
100*4887Schin 	Language_list_t*	languages;
101*4887Schin 	int			primary;
102*4887Schin 	int			index;
103*4887Schin } Territory_t;
104*4887Schin 
105*4887Schin typedef struct Map_s
106*4887Schin {
107*4887Schin 	Link_t			link;
108*4887Schin 	Language_t*		language;
109*4887Schin 	Territory_t*		territory;
110*4887Schin 	Charset_t*		charset;
111*4887Schin 	Attribute_t*		attribute;
112*4887Schin } Map_t;
113*4887Schin 
114*4887Schin static struct State_s
115*4887Schin {
116*4887Schin 	Table_t			attribute;
117*4887Schin 	Table_t			charset;
118*4887Schin 	Table_t			language;
119*4887Schin 	Table_t			territory;
120*4887Schin 	Table_t			map;
121*4887Schin } state;
122*4887Schin 
123*4887Schin #define INIT		0
124*4887Schin #define CHARSET		1
125*4887Schin #define LANGUAGE	2
126*4887Schin #define TERRITORY	3
127*4887Schin #define MAP		4
128*4887Schin 
129*4887Schin #define elementsof(x)	(sizeof(x)/sizeof(x[0]))
130*4887Schin #define newof(p,t,n,x)	((t*)malloc(sizeof(t)*(n)+(x)))
131*4887Schin 
132*4887Schin static Link_t*
133*4887Schin #if defined(__STDC__) || defined(__cplusplus)
134*4887Schin enter(register Table_t* tab, register Link_t* v)
135*4887Schin #else
136*4887Schin enter(tab, v)
137*4887Schin register Table_t*	tab;
138*4887Schin register Link_t*	v;
139*4887Schin #endif
140*4887Schin {
141*4887Schin 	register Link_t*	x;
142*4887Schin 	register Link_t*	p;
143*4887Schin 
144*4887Schin 	for (p = 0, x = tab->root; x; p = x, x = x->next)
145*4887Schin 		if (!strcmp(x->code, v->code))
146*4887Schin 			return x;
147*4887Schin 	if (p)
148*4887Schin 		p->next = v;
149*4887Schin 	else
150*4887Schin 		tab->root = v;
151*4887Schin 	v->next = 0;
152*4887Schin 	v->index = tab->count++;
153*4887Schin 	return v;
154*4887Schin }
155*4887Schin 
156*4887Schin static Link_t*
157*4887Schin #if defined(__STDC__) || defined(__cplusplus)
158*4887Schin lookup(register Table_t* tab, register char* s)
159*4887Schin #else
160*4887Schin lookup(tab, s)
161*4887Schin register Table_t*	tab;
162*4887Schin register char*		s;
163*4887Schin #endif
164*4887Schin {
165*4887Schin 	register Link_t*	x;
166*4887Schin 
167*4887Schin 	for (x = tab->root; x; x = x->next)
168*4887Schin 		if (!strcmp(x->code, s))
169*4887Schin 			return x;
170*4887Schin 	return 0;
171*4887Schin }
172*4887Schin 
173*4887Schin static char*
174*4887Schin #if defined(__STDC__) || defined(__cplusplus)
175*4887Schin copy(char** p, register char* f)
176*4887Schin #else
177*4887Schin copy(p, f)
178*4887Schin char**		p;
179*4887Schin register char*	f;
180*4887Schin #endif
181*4887Schin {
182*4887Schin 	register char*	t;
183*4887Schin 	char*		b;
184*4887Schin 
185*4887Schin 	if (!f)
186*4887Schin 		return 0;
187*4887Schin 	b = t = *p;
188*4887Schin 	while (*t++ = *f++);
189*4887Schin 	*p = t;
190*4887Schin 	return b;
191*4887Schin }
192*4887Schin 
193*4887Schin static void
194*4887Schin #if defined(__STDC__) || defined(__cplusplus)
195*4887Schin macro(FILE* f, char* p1, char* p2, char* p3)
196*4887Schin #else
197*4887Schin macro(f, p1, p2, p3)
198*4887Schin FILE*		f;
199*4887Schin char*		p1;
200*4887Schin char*		p2;
201*4887Schin char*		p3;
202*4887Schin #endif
203*4887Schin {
204*4887Schin 	register int	c;
205*4887Schin 	register char*	s;
206*4887Schin 	register char*	b;
207*4887Schin 	register char*	e;
208*4887Schin 	int		i;
209*4887Schin 	int		m;
210*4887Schin 	int		n;
211*4887Schin 	char*		part[4];
212*4887Schin 	char		buf[128];
213*4887Schin 
214*4887Schin 	part[0] = p1;
215*4887Schin 	part[1] = p2;
216*4887Schin 	part[2] = p3;
217*4887Schin 	part[3] = 0;
218*4887Schin 	n = 0;
219*4887Schin 	fprintf(f, "\n");
220*4887Schin 	do
221*4887Schin 	{
222*4887Schin 		i = m = 0;
223*4887Schin 		b = buf;
224*4887Schin 		e = &buf[sizeof(buf)-1];
225*4887Schin 		while (b < e)
226*4887Schin 		{
227*4887Schin 			if (!(s = part[i++]))
228*4887Schin 				break;
229*4887Schin 			if (i > 1)
230*4887Schin 				*b++ = '_';
231*4887Schin 			while ((c = *s++) && b < e)
232*4887Schin 			{
233*4887Schin 				if (c == '|')
234*4887Schin 				{
235*4887Schin 					part[i-1] = s;
236*4887Schin 					m = 1;
237*4887Schin 					break;
238*4887Schin 				}
239*4887Schin 				else if (islower(c))
240*4887Schin 					c = toupper(c);
241*4887Schin 				else if (!isalnum(c))
242*4887Schin 					c = '_';
243*4887Schin 				*b++ = c;
244*4887Schin 			}
245*4887Schin 		}
246*4887Schin 		*b = 0;
247*4887Schin 		fprintf(f, "#ifdef %s\n%s,\n#else\n", buf, buf);
248*4887Schin 		n++;
249*4887Schin 	} while (m);
250*4887Schin 	fprintf(f, "0,\n");
251*4887Schin 	while (n-- > 0)
252*4887Schin 		fprintf(f, "#endif\n");
253*4887Schin }
254*4887Schin 
255*4887Schin #if defined(__STDC__) || defined(__cplusplus)
256*4887Schin int
257*4887Schin main(int argc, char** argv)
258*4887Schin #else
259*4887Schin int
260*4887Schin main(argc, argv)
261*4887Schin int		argc;
262*4887Schin char**		argv;
263*4887Schin #endif
264*4887Schin {
265*4887Schin 	register char*		s;
266*4887Schin 	register char**		vp;
267*4887Schin 	register char**		ve;
268*4887Schin 	Attribute_t*		ap;
269*4887Schin 	Attribute_list_t*	al;
270*4887Schin 	Attribute_list_t*	az;
271*4887Schin 	Charset_t*		cp;
272*4887Schin 	Territory_t*		tp;
273*4887Schin 	Language_t*		lp;
274*4887Schin 	Language_list_t*	ll;
275*4887Schin 	Language_list_t*	lz;
276*4887Schin 	Map_t*			mp;
277*4887Schin 	char*			b;
278*4887Schin 	char*			f;
279*4887Schin 	char*			command;
280*4887Schin 	char*			hdr;
281*4887Schin 	char*			lib;
282*4887Schin 	FILE*			hf;
283*4887Schin 	FILE*			lf;
284*4887Schin 	int			c;
285*4887Schin 	int			i;
286*4887Schin 	int			line;
287*4887Schin 	int			type;
288*4887Schin 	int			language_attribute_max;
289*4887Schin 	int			territory_language_max;
290*4887Schin 	char*			arg[5];
291*4887Schin 	char			buf[1024];
292*4887Schin 
293*4887Schin 	command = *argv++;
294*4887Schin 	line = 0;
295*4887Schin 	if (!(hdr = *argv++) || !(lib = *argv++) || *argv)
296*4887Schin 	{
297*4887Schin 		fprintf(stderr, "%s: hdr and lib arguments expected\n", command);
298*4887Schin 		return 1;
299*4887Schin 	}
300*4887Schin 	if (!(hf = fopen(hdr, "w")))
301*4887Schin 	{
302*4887Schin 		fprintf(stderr, "%s: %s: cannot write\n", command, hdr);
303*4887Schin 		return 1;
304*4887Schin 	}
305*4887Schin 	if (!(lf = fopen(lib, "w")))
306*4887Schin 	{
307*4887Schin 		fprintf(stderr, "%s: %s: cannot write\n", command, lib);
308*4887Schin 		return 1;
309*4887Schin 	}
310*4887Schin 	type = 0;
311*4887Schin 	language_attribute_max = 0;
312*4887Schin 	territory_language_max = 0;
313*4887Schin 	state.language.count = 2;
314*4887Schin 	state.territory.count = 2;
315*4887Schin 	ve = &arg[elementsof(arg)];
316*4887Schin 	fprintf(hf, "/* : : generated by %s : : */\n", command);
317*4887Schin 	fprintf(hf, "#pragma prototyped\n");
318*4887Schin 	fprintf(hf, "\n");
319*4887Schin 	fprintf(hf, "#ifndef _LC_H\n");
320*4887Schin 	fprintf(hf, "#define _LC_H\t\t\t1\n");
321*4887Schin 	fprintf(hf, "\n");
322*4887Schin 	fprintf(hf, "#include <ast.h>\n");
323*4887Schin 	fprintf(hf, "\n");
324*4887Schin 	fprintf(hf, "#define LC_abbreviated\t\t0x00001\n");
325*4887Schin 	fprintf(hf, "#define LC_checked\t\t0x00002\n");
326*4887Schin 	fprintf(hf, "#define LC_default\t\t0x00004\n");
327*4887Schin 	fprintf(hf, "#define LC_defined\t\t0x00008\n");
328*4887Schin 	fprintf(hf, "#define LC_debug\t\t0x00010\n");
329*4887Schin 	fprintf(hf, "#define LC_local\t\t0x00020\n");
330*4887Schin 	fprintf(hf, "#define LC_primary\t\t0x00040\n");
331*4887Schin 	fprintf(hf, "#define LC_qualified\t\t0x00080\n");
332*4887Schin 	fprintf(hf, "#define LC_undefined\t\t0x00100\n");
333*4887Schin 	fprintf(hf, "#define LC_verbose\t\t0x00200\n");
334*4887Schin 	fprintf(hf, "#define LC_user\t\t\t0x10000\n");
335*4887Schin 	fprintf(lf, "/* : : generated by %s : : */\n", command);
336*4887Schin 	while (s = fgets(buf, sizeof(buf), stdin))
337*4887Schin 	{
338*4887Schin 		line++;
339*4887Schin 		while (isspace(*s))
340*4887Schin 			s++;
341*4887Schin 		if (!*s || *s == '#')
342*4887Schin 			continue;
343*4887Schin 		b = s;
344*4887Schin 		vp = arg;
345*4887Schin 		for (;;)
346*4887Schin 		{
347*4887Schin 			for (*vp++ = s; *s && !isspace(*s); s++);
348*4887Schin 			if (!*s)
349*4887Schin 				break;
350*4887Schin 			for (*s++ = 0; isspace(*s); s++);
351*4887Schin 			if (!strcmp(*(vp - 1), "-"))
352*4887Schin 				*(vp - 1) = 0;
353*4887Schin 			if (!*s || vp >= ve)
354*4887Schin 				break;
355*4887Schin 		}
356*4887Schin 		while (vp < ve)
357*4887Schin 			*vp++ = 0;
358*4887Schin 		if (*arg[0] == ':')
359*4887Schin 		{
360*4887Schin 			if (!strcmp(arg[0], ":map:"))
361*4887Schin 			{
362*4887Schin 				if (type != TERRITORY)
363*4887Schin 				{
364*4887Schin 					fprintf(stderr, "%s: %d: %s: must be specified after :territory:\n", command, line, arg[0]);
365*4887Schin 					return 1;
366*4887Schin 				}
367*4887Schin 				type = MAP;
368*4887Schin 				continue;
369*4887Schin 			}
370*4887Schin 			else if (!strcmp(arg[0], ":charset:"))
371*4887Schin 			{
372*4887Schin 				if (type != INIT)
373*4887Schin 				{
374*4887Schin 					fprintf(stderr, "%s: %d: %s must be specified first\n", command, line, arg[0]);
375*4887Schin 					return 1;
376*4887Schin 				}
377*4887Schin 				type = CHARSET;
378*4887Schin 				continue;
379*4887Schin 			}
380*4887Schin 			else if (!strcmp(arg[0], ":territory:"))
381*4887Schin 			{
382*4887Schin 				if (type != LANGUAGE)
383*4887Schin 				{
384*4887Schin 					fprintf(stderr, "%s: %d: %s: must be specified after :language:\n", command, line, arg[0]);
385*4887Schin 					return 1;
386*4887Schin 				}
387*4887Schin 				type = TERRITORY;
388*4887Schin 				continue;
389*4887Schin 			}
390*4887Schin 			else if (!strcmp(arg[0], ":language:"))
391*4887Schin 			{
392*4887Schin 				if (type != CHARSET)
393*4887Schin 				{
394*4887Schin 					fprintf(stderr, "%s: %d: %s must be specified after :charset:\n", command, line, arg[0]);
395*4887Schin 					return 1;
396*4887Schin 				}
397*4887Schin 				type = LANGUAGE;
398*4887Schin 				continue;
399*4887Schin 			}
400*4887Schin 			else
401*4887Schin 			{
402*4887Schin 				fprintf(stderr, "%s: %d: %s invalid\n", command, line, arg[0]);
403*4887Schin 				return 1;
404*4887Schin 			}
405*4887Schin 		}
406*4887Schin 		if (!arg[1])
407*4887Schin 		{
408*4887Schin 			fprintf(stderr, "%s: %d: at least two arguments expected\n", command, line);
409*4887Schin 			return 1;
410*4887Schin 		}
411*4887Schin 		switch (type)
412*4887Schin 		{
413*4887Schin 		case CHARSET:
414*4887Schin 			if (!(cp = newof(0, Charset_t, 1, s - b + 1)))
415*4887Schin 			{
416*4887Schin 				fprintf(stderr, "%s: %d: out of space\n", command, line);
417*4887Schin 				return 1;
418*4887Schin 			}
419*4887Schin 			b = (char*)(cp + 1);
420*4887Schin 			cp->link.code = copy(&b, arg[0]);
421*4887Schin 			cp->alternates = copy(&b, arg[1]);
422*4887Schin 			cp->ms = copy(&b, arg[2]);
423*4887Schin 			if (cp != (Charset_t*)enter(&state.charset, (Link_t*)cp))
424*4887Schin 			{
425*4887Schin 				fprintf(stderr, "%s: %d: %s: duplicate charset\n", command, line, cp->link.code);
426*4887Schin 				return 1;
427*4887Schin 			}
428*4887Schin 			break;
429*4887Schin 		case TERRITORY:
430*4887Schin 			if (!(tp = newof(0, Territory_t, 1, s - b + 1)))
431*4887Schin 			{
432*4887Schin 				fprintf(stderr, "%s: %d: out of space\n", command, line);
433*4887Schin 				return 1;
434*4887Schin 			}
435*4887Schin 			b = (char*)(tp + 1);
436*4887Schin 			tp->link.code = copy(&b, arg[0]);
437*4887Schin 			tp->name = copy(&b, arg[1]);
438*4887Schin 			tp->languages = 0;
439*4887Schin 			if (s = copy(&b, arg[2]))
440*4887Schin 			{
441*4887Schin 				i = 0;
442*4887Schin 				while (*(b = s))
443*4887Schin 				{
444*4887Schin 					for (; *s && *s != ':' && *s != '|'; s++);
445*4887Schin 					if (c = *s)
446*4887Schin 						*s++ = 0;
447*4887Schin 					if (!(lp = (Language_t*)lookup(&state.language, b)))
448*4887Schin 					{
449*4887Schin 						fprintf(stderr, "%s: %d: %s: unknown language\n", command, line, b);
450*4887Schin 						return 1;
451*4887Schin 					}
452*4887Schin 					if (!(ll = newof(0, Language_list_t, 1, 0)))
453*4887Schin 					{
454*4887Schin 						fprintf(stderr, "%s: %d: out of space\n", command, line);
455*4887Schin 						return 1;
456*4887Schin 					}
457*4887Schin 					if (!tp->languages)
458*4887Schin 						tp->languages = ll;
459*4887Schin 					else
460*4887Schin 						lz->next = ll;
461*4887Schin 					lz = ll;
462*4887Schin 					ll->language = lp;
463*4887Schin 					ll->next = 0;
464*4887Schin 					i++;
465*4887Schin 					if (c == ':')
466*4887Schin 					{
467*4887Schin 						for (b = s; *s && *s != '|'; s++);
468*4887Schin 						if (*s)
469*4887Schin 							*s++ = 0;
470*4887Schin 						if (!strcmp(b, "primary"))
471*4887Schin 							tp->primary = 1;
472*4887Schin 					}
473*4887Schin 				}
474*4887Schin 				if (territory_language_max < i)
475*4887Schin 					territory_language_max = i;
476*4887Schin 			}
477*4887Schin 			if (tp != (Territory_t*)enter(&state.territory, (Link_t*)tp))
478*4887Schin 			{
479*4887Schin 				fprintf(stderr, "%s: %d: %s: duplicate territory\n", command, line, tp->link.code);
480*4887Schin 				return 1;
481*4887Schin 			}
482*4887Schin 			break;
483*4887Schin 		case LANGUAGE:
484*4887Schin 			if (!(lp = newof(0, Language_t, 1, s - b + 1)))
485*4887Schin 			{
486*4887Schin 				fprintf(stderr, "%s: %d: out of space\n", command, line);
487*4887Schin 				return 1;
488*4887Schin 			}
489*4887Schin 			b = (char*)(lp + 1);
490*4887Schin 			lp->link.code = copy(&b, arg[0]);
491*4887Schin 			lp->name = copy(&b, arg[1]);
492*4887Schin 			lp->alternates = copy(&b, arg[2]);
493*4887Schin 			if (!arg[3])
494*4887Schin 				lp->charset = 0;
495*4887Schin 			else if (!(lp->charset = (Charset_t*)lookup(&state.charset, arg[3])))
496*4887Schin 			{
497*4887Schin 				fprintf(stderr, "%s: %d: %s: unknown charset\n", command, line, arg[3]);
498*4887Schin 				return 1;
499*4887Schin 			}
500*4887Schin 			lp->attributes = 0;
501*4887Schin 			if (s = copy(&b, arg[4]))
502*4887Schin 			{
503*4887Schin 				i = 0;
504*4887Schin 				fprintf(lf, "\nstatic Lc_attribute_t attribute_%s[] =\n{\n", lp->link.code);
505*4887Schin 				while (*(b = s))
506*4887Schin 				{
507*4887Schin 					for (f = 0; *s && *s != '|'; s++)
508*4887Schin 						if (*s == ':')
509*4887Schin 						{
510*4887Schin 							*s++ = 0;
511*4887Schin 							f = s;
512*4887Schin 						}
513*4887Schin 					if (*s)
514*4887Schin 						*s++ = 0;
515*4887Schin 					fprintf(lf, "{\"%s\",", b);
516*4887Schin 					if (f)
517*4887Schin 						fprintf(lf, "LC_%s,", f);
518*4887Schin 					else
519*4887Schin 						fprintf(lf, "0,");
520*4887Schin 					if (!(ap = newof(0, Attribute_t, 1, 0)))
521*4887Schin 					{
522*4887Schin 						fprintf(stderr, "%s: %d: out of space\n", command, line);
523*4887Schin 						return 1;
524*4887Schin 					}
525*4887Schin 					ap->link.code = b;
526*4887Schin 					ap->link.index = i++;
527*4887Schin 					if (!(al = newof(0, Attribute_list_t, 1, 0)))
528*4887Schin 					{
529*4887Schin 						fprintf(stderr, "%s: %d: out of space\n", command, line);
530*4887Schin 						return 1;
531*4887Schin 					}
532*4887Schin 					if (!lp->attributes)
533*4887Schin 						lp->attributes = al;
534*4887Schin 					else
535*4887Schin 						az->next = al;
536*4887Schin 					az = al;
537*4887Schin 					al->attribute = ap;
538*4887Schin 					al->next = 0;
539*4887Schin 					macro(lf, "SUBLANG", lp->name, b);
540*4887Schin 					fprintf(lf, "\n},\n");
541*4887Schin 				}
542*4887Schin 				if (language_attribute_max < i)
543*4887Schin 					language_attribute_max = i;
544*4887Schin 				fprintf(lf, "};\n");
545*4887Schin 			}
546*4887Schin 			if (lp != (Language_t*)enter(&state.language, (Link_t*)lp))
547*4887Schin 			{
548*4887Schin 				fprintf(stderr, "%s: %d: %s: duplicate language\n", command, line, lp->link.code);
549*4887Schin 				return 1;
550*4887Schin 			}
551*4887Schin 			break;
552*4887Schin 		case MAP:
553*4887Schin 			if (!(mp = newof(0, Map_t, 1, s - b + 1)))
554*4887Schin 			{
555*4887Schin 				fprintf(stderr, "%s: %d: out of space\n", command, line);
556*4887Schin 				return 1;
557*4887Schin 			}
558*4887Schin 			b = (char*)(mp + 1);
559*4887Schin 			mp->link.code = copy(&b, arg[0]);
560*4887Schin 			if (!arg[2])
561*4887Schin 			{
562*4887Schin 				fprintf(stderr, "%s: %d: territory code expected\n", command, line);
563*4887Schin 				return 1;
564*4887Schin 			}
565*4887Schin 			if (!(mp->language = (Language_t*)lookup(&state.language, arg[1])))
566*4887Schin 			{
567*4887Schin 				fprintf(stderr, "%s: %d: %s: unknown language\n", command, line, arg[1]);
568*4887Schin 				return 1;
569*4887Schin 			}
570*4887Schin 			if (!(mp->territory = (Territory_t*)lookup(&state.territory, arg[2])))
571*4887Schin 			{
572*4887Schin 				fprintf(stderr, "%s: %d: %s: unknown territory\n", command, line, arg[2]);
573*4887Schin 				return 1;
574*4887Schin 			}
575*4887Schin 			if (!arg[3])
576*4887Schin 				mp->charset = 0;
577*4887Schin 			else if (!(mp->charset = (Charset_t*)lookup(&state.charset, arg[3])))
578*4887Schin 			{
579*4887Schin 				fprintf(stderr, "%s: %d: %s: unknown charset\n", command, line, arg[3]);
580*4887Schin 				return 1;
581*4887Schin 			}
582*4887Schin 			mp->attribute = 0;
583*4887Schin 			if (arg[4])
584*4887Schin 			{
585*4887Schin 				for (al = mp->language->attributes; al; al = al->next)
586*4887Schin 					if (!strcmp(al->attribute->link.code, arg[4]))
587*4887Schin 					{
588*4887Schin 						mp->attribute = al->attribute;
589*4887Schin 						break;
590*4887Schin 					}
591*4887Schin 				if (!mp->attribute)
592*4887Schin 				{
593*4887Schin 					fprintf(stderr, "%s: %d: %s: unknown attribute\n", command, line, arg[4]);
594*4887Schin 					return 1;
595*4887Schin 				}
596*4887Schin 			}
597*4887Schin 			if (mp != (Map_t*)enter(&state.map, (Link_t*)mp))
598*4887Schin 			{
599*4887Schin 				fprintf(stderr, "%s: %d: %s: duplicate map\n", command, line, mp->link.code);
600*4887Schin 				return 1;
601*4887Schin 			}
602*4887Schin 			break;
603*4887Schin 		}
604*4887Schin 	}
605*4887Schin 	fprintf(hf, "#define LC_language_attribute_max\t\t%d\n", language_attribute_max);
606*4887Schin 	fprintf(hf, "#define LC_territory_language_max\t\t%d\n", territory_language_max);
607*4887Schin 	fprintf(hf, "\nstruct Lc_s;\n");
608*4887Schin 	fprintf(hf, "\ntypedef struct Lc_info_s\n{\n");
609*4887Schin 	fprintf(hf, "\tconst struct Lc_s*\tlc;\n");
610*4887Schin 	fprintf(hf, "\tunsigned long\t\tnumber;\n");
611*4887Schin 	fprintf(hf, "\tvoid*\t\t\tdata;\n");
612*4887Schin 	fprintf(hf, "} Lc_info_t;\n");
613*4887Schin 	fprintf(hf, "\ntypedef struct Lc_attribute_s\n{\n");
614*4887Schin 	fprintf(hf, "\tconst char*\t\tname;\n");
615*4887Schin 	fprintf(hf, "\tunsigned long\t\tflags;\n");
616*4887Schin 	fprintf(hf, "\tunsigned long\t\tindex;\n");
617*4887Schin 	fprintf(hf, "} Lc_attribute_t;\n");
618*4887Schin 	fprintf(hf, "\ntypedef struct Lc_charset_s\n{\n");
619*4887Schin 	fprintf(hf, "\tconst char*\t\tcode;\n");
620*4887Schin 	fprintf(hf, "\tconst char*\t\talternates;\n");
621*4887Schin 	fprintf(hf, "\tconst char*\t\tms;\n");
622*4887Schin 	fprintf(hf, "\tunsigned long\t\tindex;\n");
623*4887Schin 	fprintf(hf, "} Lc_charset_t;\n");
624*4887Schin 	fprintf(hf, "\ntypedef struct Lc_language_s\n{\n");
625*4887Schin 	fprintf(hf, "\tconst char*\t\tcode;\n");
626*4887Schin 	fprintf(hf, "\tconst char*\t\tname;\n");
627*4887Schin 	fprintf(hf, "\tconst char*\t\talternates;\n");
628*4887Schin 	fprintf(hf, "\tconst Lc_charset_t*\tcharset;\n");
629*4887Schin 	fprintf(hf, "\tunsigned long\t\tflags;\n");
630*4887Schin 	fprintf(hf, "\tunsigned long\t\tindex;\n");
631*4887Schin 	fprintf(hf, "\tconst Lc_attribute_t*\tattributes[LC_language_attribute_max];\n");
632*4887Schin 	fprintf(hf, "} Lc_language_t;\n");
633*4887Schin 	fprintf(hf, "\ntypedef struct Lc_territory_s\n{\n");
634*4887Schin 	fprintf(hf, "\tconst char*\t\tcode;\n");
635*4887Schin 	fprintf(hf, "\tconst char*\t\tname;\n");
636*4887Schin 	fprintf(hf, "\tunsigned long\t\tflags;\n");
637*4887Schin 	fprintf(hf, "\tunsigned long\t\tindex;\n");
638*4887Schin 	fprintf(hf, "\tconst Lc_language_t*\tlanguages[LC_territory_language_max];\n");
639*4887Schin 	fprintf(hf, "#ifdef _LC_TERRITORY_PRIVATE_\n");
640*4887Schin 	fprintf(hf, "\t_LC_TERRITORY_PRIVATE_\n");
641*4887Schin 	fprintf(hf, "#endif\n");
642*4887Schin 	fprintf(hf, "} Lc_territory_t;\n");
643*4887Schin 	fprintf(hf, "\ntypedef struct Lc_map_s\n{\n");
644*4887Schin 	fprintf(hf, "\tconst char*\t\tcode;\n");
645*4887Schin 	fprintf(hf, "\tconst Lc_language_t*\tlanguage;\n");
646*4887Schin 	fprintf(hf, "\tconst Lc_territory_t*\tterritory;\n");
647*4887Schin 	fprintf(hf, "\tconst Lc_charset_t*\tcharset;\n");
648*4887Schin 	fprintf(hf, "\tconst Lc_attribute_t*\tattribute;\n");
649*4887Schin 	fprintf(hf, "} Lc_map_t;\n");
650*4887Schin 	fprintf(hf, "\ntypedef struct Lc_attribute_list_s\n{\n");
651*4887Schin 	fprintf(hf, "\tstruct Lc_attribute_list_s*\tnext;\n");
652*4887Schin 	fprintf(hf, "\tconst Lc_attribute_t*\t\tattribute;\n");
653*4887Schin 	fprintf(hf, "} Lc_attribute_list_t;\n");
654*4887Schin 	fprintf(hf, "\ntypedef struct Lc_s\n{\n");
655*4887Schin 	fprintf(hf, "\tconst char*\t\tname;\n");
656*4887Schin 	fprintf(hf, "\tconst char*\t\tcode;\n");
657*4887Schin 	fprintf(hf, "\tconst Lc_language_t*\tlanguage;\n");
658*4887Schin 	fprintf(hf, "\tconst Lc_territory_t*\tterritory;\n");
659*4887Schin 	fprintf(hf, "\tconst Lc_charset_t*\tcharset;\n");
660*4887Schin 	fprintf(hf, "\tconst Lc_attribute_list_t*\tattributes;\n");
661*4887Schin 	fprintf(hf, "\tunsigned long\t\tflags;\n");
662*4887Schin 	fprintf(hf, "\tunsigned long\t\tindex;\n");
663*4887Schin 	fprintf(hf, "#ifdef _LC_PRIVATE_\n");
664*4887Schin 	fprintf(hf, "\t_LC_PRIVATE_\n");
665*4887Schin 	fprintf(hf, "#endif\n");
666*4887Schin 	fprintf(hf, "} Lc_t;\n");
667*4887Schin 	fprintf(hf, "\nstruct Lc_category_s;\n");
668*4887Schin 	fprintf(hf, "\ntypedef int (*Lc_category_set_f)(struct Lc_category_s*);\n");
669*4887Schin 	fprintf(hf, "\ntypedef struct Lc_category_s\n{\n");
670*4887Schin 	fprintf(hf, "\tconst char*\t\tname;\n");
671*4887Schin 	fprintf(hf, "\tint\t\t\texternal;\n");
672*4887Schin 	fprintf(hf, "\tint\t\t\tinternal;\n");
673*4887Schin 	fprintf(hf, "\tLc_category_set_f\tsetf;\n");
674*4887Schin 	fprintf(hf, "\tLc_t*\t\t\tprev;\n");
675*4887Schin 	fprintf(hf, "} Lc_category_t;\n");
676*4887Schin 	fprintf(hf, "\n");
677*4887Schin 	fprintf(hf, "#if _BLD_ast && defined(__EXPORT__)\n");
678*4887Schin 	fprintf(hf, "#define extern\t\t__EXPORT__\n");
679*4887Schin 	fprintf(hf, "#endif\n");
680*4887Schin 	fprintf(hf, "\n");
681*4887Schin 	fprintf(hf, "extern size_t\t\tlccanon(Lc_t*, unsigned long flags, char*, size_t);\n");
682*4887Schin 	fprintf(hf, "extern Lc_category_t*\tlccategories(void);\n");
683*4887Schin 	fprintf(hf, "extern int\t\tlcindex(int, int);\n");
684*4887Schin 	fprintf(hf, "extern Lc_info_t*\tlcinfo(int);\n");
685*4887Schin 	fprintf(hf, "extern Lc_t*\t\tlcmake(const char*);\n");
686*4887Schin 	fprintf(hf, "extern Lc_t*\t\tlcscan(Lc_t*);\n");
687*4887Schin 	fprintf(hf, "\n");
688*4887Schin 	fprintf(hf, "#undef\textern\n");
689*4887Schin 	fprintf(lf, "\nstatic const Lc_charset_t charset[] =\n{\n");
690*4887Schin 	for (cp = (Charset_t*)state.charset.root; cp; cp = (Charset_t*)cp->link.next)
691*4887Schin 	{
692*4887Schin 		fprintf(lf, "{\"%s\",", cp->link.code);
693*4887Schin 		if (cp->alternates)
694*4887Schin 			fprintf(lf, "\"%s\",", cp->alternates);
695*4887Schin 		else
696*4887Schin 			fprintf(lf, "0,");
697*4887Schin 		if (cp->ms)
698*4887Schin 			fprintf(lf, "\"%s\",", cp->ms);
699*4887Schin 		else
700*4887Schin 			fprintf(lf, "0");
701*4887Schin 		fprintf(lf, "},\n");
702*4887Schin 	}
703*4887Schin 	fprintf(lf, "\t0\n};\n");
704*4887Schin 	fprintf(lf, "\nstatic const Lc_language_t language[] =\n{\n");
705*4887Schin 	fprintf(lf, "{\"C\",\"C\",\"POSIX\",&charset[0],LC_default,0,");
706*4887Schin 	for (i = 0; i < language_attribute_max; i++)
707*4887Schin 		fprintf(lf, "0,");
708*4887Schin 	fprintf(lf, "},\n");
709*4887Schin 	fprintf(lf, "{\"debug\",\"debug\",0,&charset[0],LC_debug,0,");
710*4887Schin 	for (i = 0; i < language_attribute_max; i++)
711*4887Schin 		fprintf(lf, "0,");
712*4887Schin 	fprintf(lf, "},\n");
713*4887Schin 	for (lp = (Language_t*)state.language.root; lp; lp = (Language_t*)lp->link.next)
714*4887Schin 	{
715*4887Schin 		fprintf(lf, "{\"%s\",\"%s\",", lp->link.code, lp->name);
716*4887Schin 		if (lp->alternates)
717*4887Schin 			fprintf(lf, "\"%s\",", lp->alternates);
718*4887Schin 		else
719*4887Schin 			fprintf(lf, "0,");
720*4887Schin 		fprintf(lf, "&charset[%d],0,", lp->charset ? lp->charset->link.index : 0);
721*4887Schin 		macro(lf, "LANG", lp->name, (char*)0);
722*4887Schin 		for (i = 0, al = lp->attributes; al; al = al->next, i++)
723*4887Schin 			fprintf(lf, "&attribute_%s[%d],", lp->link.code, al->attribute->link.index);
724*4887Schin 		for (; i < language_attribute_max; i++)
725*4887Schin 			fprintf(lf, "0,");
726*4887Schin 		fprintf(lf, "\n},\n");
727*4887Schin 	}
728*4887Schin 	fprintf(lf, "\t0\n};\n");
729*4887Schin 	fprintf(lf, "\nstatic const Lc_territory_t territory[] =\n{\n");
730*4887Schin 	fprintf(lf, "{\"C\",\"C\",LC_default,0,&language[0],");
731*4887Schin 	for (i = 1; i < 2 * territory_language_max; i++)
732*4887Schin 		fprintf(lf, "0,");
733*4887Schin 	fprintf(lf, "},\n");
734*4887Schin 	fprintf(lf, "{\"debug\",\"debug\",LC_debug,0,&language[1],");
735*4887Schin 	for (i = 1; i < 2 * territory_language_max; i++)
736*4887Schin 		fprintf(lf, "0,");
737*4887Schin 	fprintf(lf, "},\n");
738*4887Schin 	for (tp = (Territory_t*)state.territory.root; tp; tp = (Territory_t*)tp->link.next)
739*4887Schin 	{
740*4887Schin 		fprintf(lf, "{\"%s\",\"%s\",", tp->link.code, tp->name);
741*4887Schin 		if (tp->primary)
742*4887Schin 			fprintf(lf, "LC_primary,");
743*4887Schin 		else
744*4887Schin 			fprintf(lf, "0,");
745*4887Schin 		macro(lf, "CTRY", tp->name, (char*)0);
746*4887Schin 		for (i = 0, ll = tp->languages; ll; ll = ll->next, i++)
747*4887Schin 			fprintf(lf, "&language[%d],", ll->language->link.index);
748*4887Schin 		for (; i < territory_language_max; i++)
749*4887Schin 			fprintf(lf, "0,");
750*4887Schin 		for (i = 0, ll = tp->languages; ll; ll = ll->next, i++)
751*4887Schin 			macro(lf, "SUBLANG", ll->language->name, tp->name);
752*4887Schin 		for (; i < territory_language_max; i++)
753*4887Schin 			fprintf(lf, "0,");
754*4887Schin 		fprintf(lf, "\n},\n");
755*4887Schin 	}
756*4887Schin 	fprintf(lf, "\t0\n};\n");
757*4887Schin 	fprintf(lf, "\nstatic const Lc_map_t map[] =\n{\n");
758*4887Schin 	for (mp = (Map_t*)state.map.root; mp; mp = (Map_t*)mp->link.next)
759*4887Schin 	{
760*4887Schin 		fprintf(lf, "{\"%s\",", mp->link.code);
761*4887Schin 		fprintf(lf, "&language[%d],", mp->language->link.index);
762*4887Schin 		fprintf(lf, "&territory[%d],", mp->territory->link.index);
763*4887Schin 		fprintf(lf, "&charset[%d],", mp->charset ? mp->charset->link.index : 0);
764*4887Schin 		if (mp->attribute)
765*4887Schin 			fprintf(lf, "&attribute_%s[%d]", mp->language->link.code, mp->attribute->link.index);
766*4887Schin 		else
767*4887Schin 			fprintf(lf, "0");
768*4887Schin 		fprintf(lf, "},\n");
769*4887Schin 	}
770*4887Schin 	fprintf(lf, "\t0\n};\n");
771*4887Schin 	fclose(lf);
772*4887Schin 	fprintf(hf, "\n#endif\n");
773*4887Schin 	fclose(hf);
774*4887Schin 	return 0;
775*4887Schin }
776