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