xref: /onnv-gate/usr/src/lib/libast/common/port/lcgen.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin /*
234887Schin  * generate <lc.h> implementation tables from lc.tab
244887Schin  * this must make it through vanilla cc with no -last
254887Schin  *
264887Schin  *	# comment
274887Schin  *	:charset:
284887Schin  *		code	name	ms-codepage
294887Schin  *	:language:
304887Schin  *		code	name	alt1|alt2...	charset|... attr1|attr2|...
314887Schin  *		...
324887Schin  *	:territory:
334887Schin  *		code	name	lang1|lang2...
344887Schin  *	:abbreviation:
354887Schin  */
364887Schin 
374887Schin #include <stdio.h>
384887Schin #include <ctype.h>
394887Schin #ifdef __STDC__
404887Schin #include <stdlib.h>
414887Schin #include <string.h>
424887Schin #endif
434887Schin 
444887Schin typedef struct Link_s
454887Schin {
464887Schin 	struct Link_s*		next;
474887Schin 	char*			code;
484887Schin 	int			index;
494887Schin } Link_t;
504887Schin 
514887Schin typedef struct Table_s
524887Schin {
534887Schin 	Link_t*			root;
544887Schin 	int			count;
554887Schin } Table_t;
564887Schin 
574887Schin typedef struct Abbreviation_s
584887Schin {
594887Schin 	Link_t			link;
604887Schin 	char*			value;
614887Schin } Abbreviation_t;
624887Schin 
634887Schin typedef struct Attribute_s
644887Schin {
654887Schin 	Link_t			link;
664887Schin } Attribute_t;
674887Schin 
684887Schin typedef struct Attribute_list_s
694887Schin {
704887Schin 	struct Attribute_list_s*next;
714887Schin 	Attribute_t*		attribute;
724887Schin } Attribute_list_t;
734887Schin 
744887Schin typedef struct Charset_s
754887Schin {
764887Schin 	Link_t			link;
774887Schin 	char*			alternates;
784887Schin 	char*			ms;
794887Schin } Charset_t;
804887Schin 
814887Schin typedef struct Language_s
824887Schin {
834887Schin 	Link_t			link;
844887Schin 	char*			name;
854887Schin 	char*			alternates;
864887Schin 	Charset_t*		charset;
874887Schin 	Attribute_list_t*	attributes;
884887Schin } Language_t;
894887Schin 
904887Schin typedef struct Language_list_s
914887Schin {
924887Schin 	struct Language_list_s*	next;
934887Schin 	Language_t*		language;
944887Schin } Language_list_t;
954887Schin 
964887Schin typedef struct Territory_s
974887Schin {
984887Schin 	Link_t			link;
994887Schin 	char*			name;
1004887Schin 	Language_list_t*	languages;
1014887Schin 	int			primary;
1024887Schin 	int			index;
1034887Schin } Territory_t;
1044887Schin 
1054887Schin typedef struct Map_s
1064887Schin {
1074887Schin 	Link_t			link;
1084887Schin 	Language_t*		language;
1094887Schin 	Territory_t*		territory;
1104887Schin 	Charset_t*		charset;
1114887Schin 	Attribute_t*		attribute;
1124887Schin } Map_t;
1134887Schin 
1144887Schin static struct State_s
1154887Schin {
1164887Schin 	Table_t			attribute;
1174887Schin 	Table_t			charset;
1184887Schin 	Table_t			language;
1194887Schin 	Table_t			territory;
1204887Schin 	Table_t			map;
1214887Schin } state;
1224887Schin 
1234887Schin #define INIT		0
1244887Schin #define CHARSET		1
1254887Schin #define LANGUAGE	2
1264887Schin #define TERRITORY	3
1274887Schin #define MAP		4
1284887Schin 
1294887Schin #define elementsof(x)	(sizeof(x)/sizeof(x[0]))
1304887Schin #define newof(p,t,n,x)	((t*)malloc(sizeof(t)*(n)+(x)))
1314887Schin 
1324887Schin static Link_t*
1334887Schin #if defined(__STDC__) || defined(__cplusplus)
enter(register Table_t * tab,register Link_t * v)1344887Schin enter(register Table_t* tab, register Link_t* v)
1354887Schin #else
1364887Schin enter(tab, v)
1374887Schin register Table_t*	tab;
1384887Schin register Link_t*	v;
1394887Schin #endif
1404887Schin {
1414887Schin 	register Link_t*	x;
1424887Schin 	register Link_t*	p;
1434887Schin 
1444887Schin 	for (p = 0, x = tab->root; x; p = x, x = x->next)
1454887Schin 		if (!strcmp(x->code, v->code))
1464887Schin 			return x;
1474887Schin 	if (p)
1484887Schin 		p->next = v;
1494887Schin 	else
1504887Schin 		tab->root = v;
1514887Schin 	v->next = 0;
1524887Schin 	v->index = tab->count++;
1534887Schin 	return v;
1544887Schin }
1554887Schin 
1564887Schin static Link_t*
1574887Schin #if defined(__STDC__) || defined(__cplusplus)
lookup(register Table_t * tab,register char * s)1584887Schin lookup(register Table_t* tab, register char* s)
1594887Schin #else
1604887Schin lookup(tab, s)
1614887Schin register Table_t*	tab;
1624887Schin register char*		s;
1634887Schin #endif
1644887Schin {
1654887Schin 	register Link_t*	x;
1664887Schin 
1674887Schin 	for (x = tab->root; x; x = x->next)
1684887Schin 		if (!strcmp(x->code, s))
1694887Schin 			return x;
1704887Schin 	return 0;
1714887Schin }
1724887Schin 
1734887Schin static char*
1744887Schin #if defined(__STDC__) || defined(__cplusplus)
copy(char ** p,register char * f)1754887Schin copy(char** p, register char* f)
1764887Schin #else
1774887Schin copy(p, f)
1784887Schin char**		p;
1794887Schin register char*	f;
1804887Schin #endif
1814887Schin {
1824887Schin 	register char*	t;
1834887Schin 	char*		b;
1844887Schin 
1854887Schin 	if (!f)
1864887Schin 		return 0;
1874887Schin 	b = t = *p;
1884887Schin 	while (*t++ = *f++);
1894887Schin 	*p = t;
1904887Schin 	return b;
1914887Schin }
1924887Schin 
1934887Schin static void
1944887Schin #if defined(__STDC__) || defined(__cplusplus)
macro(FILE * f,char * p1,char * p2,char * p3)1954887Schin macro(FILE* f, char* p1, char* p2, char* p3)
1964887Schin #else
1974887Schin macro(f, p1, p2, p3)
1984887Schin FILE*		f;
1994887Schin char*		p1;
2004887Schin char*		p2;
2014887Schin char*		p3;
2024887Schin #endif
2034887Schin {
2044887Schin 	register int	c;
2054887Schin 	register char*	s;
2064887Schin 	register char*	b;
2074887Schin 	register char*	e;
2084887Schin 	int		i;
2094887Schin 	int		m;
2104887Schin 	int		n;
2114887Schin 	char*		part[4];
2124887Schin 	char		buf[128];
2134887Schin 
2144887Schin 	part[0] = p1;
2154887Schin 	part[1] = p2;
2164887Schin 	part[2] = p3;
2174887Schin 	part[3] = 0;
2184887Schin 	n = 0;
2194887Schin 	fprintf(f, "\n");
2204887Schin 	do
2214887Schin 	{
2224887Schin 		i = m = 0;
2234887Schin 		b = buf;
2244887Schin 		e = &buf[sizeof(buf)-1];
2254887Schin 		while (b < e)
2264887Schin 		{
2274887Schin 			if (!(s = part[i++]))
2284887Schin 				break;
2294887Schin 			if (i > 1)
2304887Schin 				*b++ = '_';
2314887Schin 			while ((c = *s++) && b < e)
2324887Schin 			{
2334887Schin 				if (c == '|')
2344887Schin 				{
2354887Schin 					part[i-1] = s;
2364887Schin 					m = 1;
2374887Schin 					break;
2384887Schin 				}
2394887Schin 				else if (islower(c))
2404887Schin 					c = toupper(c);
2414887Schin 				else if (!isalnum(c))
2424887Schin 					c = '_';
2434887Schin 				*b++ = c;
2444887Schin 			}
2454887Schin 		}
2464887Schin 		*b = 0;
2474887Schin 		fprintf(f, "#ifdef %s\n%s,\n#else\n", buf, buf);
2484887Schin 		n++;
2494887Schin 	} while (m);
2504887Schin 	fprintf(f, "0,\n");
2514887Schin 	while (n-- > 0)
2524887Schin 		fprintf(f, "#endif\n");
2534887Schin }
2544887Schin 
2554887Schin #if defined(__STDC__) || defined(__cplusplus)
2564887Schin int
main(int argc,char ** argv)2574887Schin main(int argc, char** argv)
2584887Schin #else
2594887Schin int
2604887Schin main(argc, argv)
2614887Schin int		argc;
2624887Schin char**		argv;
2634887Schin #endif
2644887Schin {
2654887Schin 	register char*		s;
2664887Schin 	register char**		vp;
2674887Schin 	register char**		ve;
2684887Schin 	Attribute_t*		ap;
2694887Schin 	Attribute_list_t*	al;
2704887Schin 	Attribute_list_t*	az;
2714887Schin 	Charset_t*		cp;
2724887Schin 	Territory_t*		tp;
2734887Schin 	Language_t*		lp;
2744887Schin 	Language_list_t*	ll;
2754887Schin 	Language_list_t*	lz;
2764887Schin 	Map_t*			mp;
2774887Schin 	char*			b;
2784887Schin 	char*			f;
2794887Schin 	char*			command;
2804887Schin 	char*			hdr;
2814887Schin 	char*			lib;
2824887Schin 	FILE*			hf;
2834887Schin 	FILE*			lf;
2844887Schin 	int			c;
2854887Schin 	int			i;
2864887Schin 	int			line;
2874887Schin 	int			type;
2884887Schin 	int			language_attribute_max;
2894887Schin 	int			territory_language_max;
2904887Schin 	char*			arg[5];
2914887Schin 	char			buf[1024];
2924887Schin 
2934887Schin 	command = *argv++;
2944887Schin 	line = 0;
2954887Schin 	if (!(hdr = *argv++) || !(lib = *argv++) || *argv)
2964887Schin 	{
2978462SApril.Chin@Sun.COM 		fprintf(stderr, "%s: { hdr lib tab } arguments expected\n", command);
2984887Schin 		return 1;
2994887Schin 	}
3004887Schin 	if (!(hf = fopen(hdr, "w")))
3014887Schin 	{
3024887Schin 		fprintf(stderr, "%s: %s: cannot write\n", command, hdr);
3034887Schin 		return 1;
3044887Schin 	}
3054887Schin 	if (!(lf = fopen(lib, "w")))
3064887Schin 	{
3074887Schin 		fprintf(stderr, "%s: %s: cannot write\n", command, lib);
3084887Schin 		return 1;
3094887Schin 	}
3104887Schin 	type = 0;
3114887Schin 	language_attribute_max = 0;
3124887Schin 	territory_language_max = 0;
3134887Schin 	state.language.count = 2;
3144887Schin 	state.territory.count = 2;
3154887Schin 	ve = &arg[elementsof(arg)];
3164887Schin 	fprintf(hf, "/* : : generated by %s : : */\n", command);
3174887Schin 	fprintf(hf, "#pragma prototyped\n");
3184887Schin 	fprintf(hf, "\n");
3194887Schin 	fprintf(hf, "#ifndef _LC_H\n");
3204887Schin 	fprintf(hf, "#define _LC_H\t\t\t1\n");
3214887Schin 	fprintf(hf, "\n");
3224887Schin 	fprintf(hf, "#include <ast.h>\n");
3234887Schin 	fprintf(hf, "\n");
3244887Schin 	fprintf(hf, "#define LC_abbreviated\t\t0x00001\n");
3254887Schin 	fprintf(hf, "#define LC_checked\t\t0x00002\n");
32610898Sroland.mainz@nrubsig.org 	fprintf(hf, "#define LC_debug\t\t0x00004\n");
32710898Sroland.mainz@nrubsig.org 	fprintf(hf, "#define LC_default\t\t0x00008\n");
32810898Sroland.mainz@nrubsig.org 	fprintf(hf, "#define LC_defined\t\t0x00010\n");
3294887Schin 	fprintf(hf, "#define LC_local\t\t0x00020\n");
3304887Schin 	fprintf(hf, "#define LC_primary\t\t0x00040\n");
3314887Schin 	fprintf(hf, "#define LC_qualified\t\t0x00080\n");
3324887Schin 	fprintf(hf, "#define LC_undefined\t\t0x00100\n");
33310898Sroland.mainz@nrubsig.org 	fprintf(hf, "#define LC_utf8\t\t\t0x00200\n");
33410898Sroland.mainz@nrubsig.org 	fprintf(hf, "#define LC_verbose\t\t0x00400\n");
335*12068SRoger.Faulkner@Oracle.COM 	fprintf(hf, "#define LC_setlocale\t\t\t0x10000\n");
336*12068SRoger.Faulkner@Oracle.COM 	fprintf(hf, "#define LC_setenv\t\t\t0x20000\n");
337*12068SRoger.Faulkner@Oracle.COM 	fprintf(hf, "#define LC_user\t\t\t0x40000\n");
3384887Schin 	fprintf(lf, "/* : : generated by %s : : */\n", command);
3398462SApril.Chin@Sun.COM 	fprintf(lf, "\n");
3408462SApril.Chin@Sun.COM 	fprintf(lf, "#include \"lclib.h\"\n");
3418462SApril.Chin@Sun.COM 	fprintf(lf, "#include \"lclang.h\"\n");
3428462SApril.Chin@Sun.COM 	fprintf(lf, "\n");
3434887Schin 	while (s = fgets(buf, sizeof(buf), stdin))
3444887Schin 	{
3454887Schin 		line++;
3464887Schin 		while (isspace(*s))
3474887Schin 			s++;
3484887Schin 		if (!*s || *s == '#')
3494887Schin 			continue;
3504887Schin 		b = s;
3514887Schin 		vp = arg;
3524887Schin 		for (;;)
3534887Schin 		{
3544887Schin 			for (*vp++ = s; *s && !isspace(*s); s++);
3554887Schin 			if (!*s)
3564887Schin 				break;
3574887Schin 			for (*s++ = 0; isspace(*s); s++);
3584887Schin 			if (!strcmp(*(vp - 1), "-"))
3594887Schin 				*(vp - 1) = 0;
3604887Schin 			if (!*s || vp >= ve)
3614887Schin 				break;
3624887Schin 		}
3634887Schin 		while (vp < ve)
3644887Schin 			*vp++ = 0;
3654887Schin 		if (*arg[0] == ':')
3664887Schin 		{
3674887Schin 			if (!strcmp(arg[0], ":map:"))
3684887Schin 			{
3694887Schin 				if (type != TERRITORY)
3704887Schin 				{
3714887Schin 					fprintf(stderr, "%s: %d: %s: must be specified after :territory:\n", command, line, arg[0]);
3724887Schin 					return 1;
3734887Schin 				}
3744887Schin 				type = MAP;
3754887Schin 				continue;
3764887Schin 			}
3774887Schin 			else if (!strcmp(arg[0], ":charset:"))
3784887Schin 			{
3794887Schin 				if (type != INIT)
3804887Schin 				{
3814887Schin 					fprintf(stderr, "%s: %d: %s must be specified first\n", command, line, arg[0]);
3824887Schin 					return 1;
3834887Schin 				}
3844887Schin 				type = CHARSET;
3854887Schin 				continue;
3864887Schin 			}
3874887Schin 			else if (!strcmp(arg[0], ":territory:"))
3884887Schin 			{
3894887Schin 				if (type != LANGUAGE)
3904887Schin 				{
3914887Schin 					fprintf(stderr, "%s: %d: %s: must be specified after :language:\n", command, line, arg[0]);
3924887Schin 					return 1;
3934887Schin 				}
3944887Schin 				type = TERRITORY;
3954887Schin 				continue;
3964887Schin 			}
3974887Schin 			else if (!strcmp(arg[0], ":language:"))
3984887Schin 			{
3994887Schin 				if (type != CHARSET)
4004887Schin 				{
4014887Schin 					fprintf(stderr, "%s: %d: %s must be specified after :charset:\n", command, line, arg[0]);
4024887Schin 					return 1;
4034887Schin 				}
4044887Schin 				type = LANGUAGE;
4054887Schin 				continue;
4064887Schin 			}
4074887Schin 			else
4084887Schin 			{
4094887Schin 				fprintf(stderr, "%s: %d: %s invalid\n", command, line, arg[0]);
4104887Schin 				return 1;
4114887Schin 			}
4124887Schin 		}
4134887Schin 		if (!arg[1])
4144887Schin 		{
4154887Schin 			fprintf(stderr, "%s: %d: at least two arguments expected\n", command, line);
4164887Schin 			return 1;
4174887Schin 		}
4184887Schin 		switch (type)
4194887Schin 		{
4204887Schin 		case CHARSET:
4214887Schin 			if (!(cp = newof(0, Charset_t, 1, s - b + 1)))
4224887Schin 			{
4234887Schin 				fprintf(stderr, "%s: %d: out of space\n", command, line);
4244887Schin 				return 1;
4254887Schin 			}
4264887Schin 			b = (char*)(cp + 1);
4274887Schin 			cp->link.code = copy(&b, arg[0]);
4284887Schin 			cp->alternates = copy(&b, arg[1]);
4294887Schin 			cp->ms = copy(&b, arg[2]);
4304887Schin 			if (cp != (Charset_t*)enter(&state.charset, (Link_t*)cp))
4314887Schin 			{
4324887Schin 				fprintf(stderr, "%s: %d: %s: duplicate charset\n", command, line, cp->link.code);
4334887Schin 				return 1;
4344887Schin 			}
4354887Schin 			break;
4364887Schin 		case TERRITORY:
4374887Schin 			if (!(tp = newof(0, Territory_t, 1, s - b + 1)))
4384887Schin 			{
4394887Schin 				fprintf(stderr, "%s: %d: out of space\n", command, line);
4404887Schin 				return 1;
4414887Schin 			}
4424887Schin 			b = (char*)(tp + 1);
4434887Schin 			tp->link.code = copy(&b, arg[0]);
4444887Schin 			tp->name = copy(&b, arg[1]);
4454887Schin 			tp->languages = 0;
4464887Schin 			if (s = copy(&b, arg[2]))
4474887Schin 			{
4484887Schin 				i = 0;
4494887Schin 				while (*(b = s))
4504887Schin 				{
4514887Schin 					for (; *s && *s != ':' && *s != '|'; s++);
4524887Schin 					if (c = *s)
4534887Schin 						*s++ = 0;
4544887Schin 					if (!(lp = (Language_t*)lookup(&state.language, b)))
4554887Schin 					{
4564887Schin 						fprintf(stderr, "%s: %d: %s: unknown language\n", command, line, b);
4574887Schin 						return 1;
4584887Schin 					}
4594887Schin 					if (!(ll = newof(0, Language_list_t, 1, 0)))
4604887Schin 					{
4614887Schin 						fprintf(stderr, "%s: %d: out of space\n", command, line);
4624887Schin 						return 1;
4634887Schin 					}
4644887Schin 					if (!tp->languages)
4654887Schin 						tp->languages = ll;
4664887Schin 					else
4674887Schin 						lz->next = ll;
4684887Schin 					lz = ll;
4694887Schin 					ll->language = lp;
4704887Schin 					ll->next = 0;
4714887Schin 					i++;
4724887Schin 					if (c == ':')
4734887Schin 					{
4744887Schin 						for (b = s; *s && *s != '|'; s++);
4754887Schin 						if (*s)
4764887Schin 							*s++ = 0;
4774887Schin 						if (!strcmp(b, "primary"))
4784887Schin 							tp->primary = 1;
4794887Schin 					}
4804887Schin 				}
4814887Schin 				if (territory_language_max < i)
4824887Schin 					territory_language_max = i;
4834887Schin 			}
4844887Schin 			if (tp != (Territory_t*)enter(&state.territory, (Link_t*)tp))
4854887Schin 			{
4864887Schin 				fprintf(stderr, "%s: %d: %s: duplicate territory\n", command, line, tp->link.code);
4874887Schin 				return 1;
4884887Schin 			}
4894887Schin 			break;
4904887Schin 		case LANGUAGE:
4914887Schin 			if (!(lp = newof(0, Language_t, 1, s - b + 1)))
4924887Schin 			{
4934887Schin 				fprintf(stderr, "%s: %d: out of space\n", command, line);
4944887Schin 				return 1;
4954887Schin 			}
4964887Schin 			b = (char*)(lp + 1);
4974887Schin 			lp->link.code = copy(&b, arg[0]);
4984887Schin 			lp->name = copy(&b, arg[1]);
4994887Schin 			lp->alternates = copy(&b, arg[2]);
5004887Schin 			if (!arg[3])
5014887Schin 				lp->charset = 0;
5024887Schin 			else if (!(lp->charset = (Charset_t*)lookup(&state.charset, arg[3])))
5034887Schin 			{
5044887Schin 				fprintf(stderr, "%s: %d: %s: unknown charset\n", command, line, arg[3]);
5054887Schin 				return 1;
5064887Schin 			}
5074887Schin 			lp->attributes = 0;
5084887Schin 			if (s = copy(&b, arg[4]))
5094887Schin 			{
5104887Schin 				i = 0;
5118462SApril.Chin@Sun.COM 				fprintf(lf, "\nconst Lc_attribute_t attribute_%s[] =\n{\n", lp->link.code);
5124887Schin 				while (*(b = s))
5134887Schin 				{
5144887Schin 					for (f = 0; *s && *s != '|'; s++)
5154887Schin 						if (*s == ':')
5164887Schin 						{
5174887Schin 							*s++ = 0;
5184887Schin 							f = s;
5194887Schin 						}
5204887Schin 					if (*s)
5214887Schin 						*s++ = 0;
5224887Schin 					fprintf(lf, "{\"%s\",", b);
5234887Schin 					if (f)
5244887Schin 						fprintf(lf, "LC_%s,", f);
5254887Schin 					else
5264887Schin 						fprintf(lf, "0,");
5274887Schin 					if (!(ap = newof(0, Attribute_t, 1, 0)))
5284887Schin 					{
5294887Schin 						fprintf(stderr, "%s: %d: out of space\n", command, line);
5304887Schin 						return 1;
5314887Schin 					}
5324887Schin 					ap->link.code = b;
5334887Schin 					ap->link.index = i++;
5344887Schin 					if (!(al = newof(0, Attribute_list_t, 1, 0)))
5354887Schin 					{
5364887Schin 						fprintf(stderr, "%s: %d: out of space\n", command, line);
5374887Schin 						return 1;
5384887Schin 					}
5394887Schin 					if (!lp->attributes)
5404887Schin 						lp->attributes = al;
5414887Schin 					else
5424887Schin 						az->next = al;
5434887Schin 					az = al;
5444887Schin 					al->attribute = ap;
5454887Schin 					al->next = 0;
5464887Schin 					macro(lf, "SUBLANG", lp->name, b);
5474887Schin 					fprintf(lf, "\n},\n");
5484887Schin 				}
5494887Schin 				if (language_attribute_max < i)
5504887Schin 					language_attribute_max = i;
5514887Schin 				fprintf(lf, "};\n");
5524887Schin 			}
5534887Schin 			if (lp != (Language_t*)enter(&state.language, (Link_t*)lp))
5544887Schin 			{
5554887Schin 				fprintf(stderr, "%s: %d: %s: duplicate language\n", command, line, lp->link.code);
5564887Schin 				return 1;
5574887Schin 			}
5584887Schin 			break;
5594887Schin 		case MAP:
5604887Schin 			if (!(mp = newof(0, Map_t, 1, s - b + 1)))
5614887Schin 			{
5624887Schin 				fprintf(stderr, "%s: %d: out of space\n", command, line);
5634887Schin 				return 1;
5644887Schin 			}
5654887Schin 			b = (char*)(mp + 1);
5664887Schin 			mp->link.code = copy(&b, arg[0]);
5674887Schin 			if (!arg[2])
5684887Schin 			{
5694887Schin 				fprintf(stderr, "%s: %d: territory code expected\n", command, line);
5704887Schin 				return 1;
5714887Schin 			}
5724887Schin 			if (!(mp->language = (Language_t*)lookup(&state.language, arg[1])))
5734887Schin 			{
5744887Schin 				fprintf(stderr, "%s: %d: %s: unknown language\n", command, line, arg[1]);
5754887Schin 				return 1;
5764887Schin 			}
5774887Schin 			if (!(mp->territory = (Territory_t*)lookup(&state.territory, arg[2])))
5784887Schin 			{
5794887Schin 				fprintf(stderr, "%s: %d: %s: unknown territory\n", command, line, arg[2]);
5804887Schin 				return 1;
5814887Schin 			}
5824887Schin 			if (!arg[3])
5834887Schin 				mp->charset = 0;
5844887Schin 			else if (!(mp->charset = (Charset_t*)lookup(&state.charset, arg[3])))
5854887Schin 			{
5864887Schin 				fprintf(stderr, "%s: %d: %s: unknown charset\n", command, line, arg[3]);
5874887Schin 				return 1;
5884887Schin 			}
5894887Schin 			mp->attribute = 0;
5904887Schin 			if (arg[4])
5914887Schin 			{
5924887Schin 				for (al = mp->language->attributes; al; al = al->next)
5934887Schin 					if (!strcmp(al->attribute->link.code, arg[4]))
5944887Schin 					{
5954887Schin 						mp->attribute = al->attribute;
5964887Schin 						break;
5974887Schin 					}
5984887Schin 				if (!mp->attribute)
5994887Schin 				{
6004887Schin 					fprintf(stderr, "%s: %d: %s: unknown attribute\n", command, line, arg[4]);
6014887Schin 					return 1;
6024887Schin 				}
6034887Schin 			}
6044887Schin 			if (mp != (Map_t*)enter(&state.map, (Link_t*)mp))
6054887Schin 			{
6064887Schin 				fprintf(stderr, "%s: %d: %s: duplicate map\n", command, line, mp->link.code);
6074887Schin 				return 1;
6084887Schin 			}
6094887Schin 			break;
6104887Schin 		}
6114887Schin 	}
6124887Schin 	fprintf(hf, "#define LC_language_attribute_max\t\t%d\n", language_attribute_max);
6134887Schin 	fprintf(hf, "#define LC_territory_language_max\t\t%d\n", territory_language_max);
6144887Schin 	fprintf(hf, "\nstruct Lc_s;\n");
6154887Schin 	fprintf(hf, "\ntypedef struct Lc_info_s\n{\n");
6164887Schin 	fprintf(hf, "\tconst struct Lc_s*\tlc;\n");
6174887Schin 	fprintf(hf, "\tunsigned long\t\tnumber;\n");
6184887Schin 	fprintf(hf, "\tvoid*\t\t\tdata;\n");
6194887Schin 	fprintf(hf, "} Lc_info_t;\n");
6204887Schin 	fprintf(hf, "\ntypedef struct Lc_attribute_s\n{\n");
6214887Schin 	fprintf(hf, "\tconst char*\t\tname;\n");
6224887Schin 	fprintf(hf, "\tunsigned long\t\tflags;\n");
6234887Schin 	fprintf(hf, "\tunsigned long\t\tindex;\n");
6244887Schin 	fprintf(hf, "} Lc_attribute_t;\n");
6254887Schin 	fprintf(hf, "\ntypedef struct Lc_charset_s\n{\n");
6264887Schin 	fprintf(hf, "\tconst char*\t\tcode;\n");
6274887Schin 	fprintf(hf, "\tconst char*\t\talternates;\n");
6284887Schin 	fprintf(hf, "\tconst char*\t\tms;\n");
6294887Schin 	fprintf(hf, "\tunsigned long\t\tindex;\n");
6304887Schin 	fprintf(hf, "} Lc_charset_t;\n");
6314887Schin 	fprintf(hf, "\ntypedef struct Lc_language_s\n{\n");
6324887Schin 	fprintf(hf, "\tconst char*\t\tcode;\n");
6334887Schin 	fprintf(hf, "\tconst char*\t\tname;\n");
6344887Schin 	fprintf(hf, "\tconst char*\t\talternates;\n");
6354887Schin 	fprintf(hf, "\tconst Lc_charset_t*\tcharset;\n");
6364887Schin 	fprintf(hf, "\tunsigned long\t\tflags;\n");
6374887Schin 	fprintf(hf, "\tunsigned long\t\tindex;\n");
6384887Schin 	fprintf(hf, "\tconst Lc_attribute_t*\tattributes[LC_language_attribute_max];\n");
6394887Schin 	fprintf(hf, "} Lc_language_t;\n");
6404887Schin 	fprintf(hf, "\ntypedef struct Lc_territory_s\n{\n");
6414887Schin 	fprintf(hf, "\tconst char*\t\tcode;\n");
6424887Schin 	fprintf(hf, "\tconst char*\t\tname;\n");
6434887Schin 	fprintf(hf, "\tunsigned long\t\tflags;\n");
6444887Schin 	fprintf(hf, "\tunsigned long\t\tindex;\n");
6454887Schin 	fprintf(hf, "\tconst Lc_language_t*\tlanguages[LC_territory_language_max];\n");
6464887Schin 	fprintf(hf, "#ifdef _LC_TERRITORY_PRIVATE_\n");
6474887Schin 	fprintf(hf, "\t_LC_TERRITORY_PRIVATE_\n");
6484887Schin 	fprintf(hf, "#endif\n");
6494887Schin 	fprintf(hf, "} Lc_territory_t;\n");
6504887Schin 	fprintf(hf, "\ntypedef struct Lc_map_s\n{\n");
6514887Schin 	fprintf(hf, "\tconst char*\t\tcode;\n");
6524887Schin 	fprintf(hf, "\tconst Lc_language_t*\tlanguage;\n");
6534887Schin 	fprintf(hf, "\tconst Lc_territory_t*\tterritory;\n");
6544887Schin 	fprintf(hf, "\tconst Lc_charset_t*\tcharset;\n");
6554887Schin 	fprintf(hf, "\tconst Lc_attribute_t*\tattribute;\n");
6564887Schin 	fprintf(hf, "} Lc_map_t;\n");
6574887Schin 	fprintf(hf, "\ntypedef struct Lc_attribute_list_s\n{\n");
6584887Schin 	fprintf(hf, "\tstruct Lc_attribute_list_s*\tnext;\n");
6594887Schin 	fprintf(hf, "\tconst Lc_attribute_t*\t\tattribute;\n");
6604887Schin 	fprintf(hf, "} Lc_attribute_list_t;\n");
6614887Schin 	fprintf(hf, "\ntypedef struct Lc_s\n{\n");
6624887Schin 	fprintf(hf, "\tconst char*\t\tname;\n");
6634887Schin 	fprintf(hf, "\tconst char*\t\tcode;\n");
6644887Schin 	fprintf(hf, "\tconst Lc_language_t*\tlanguage;\n");
6654887Schin 	fprintf(hf, "\tconst Lc_territory_t*\tterritory;\n");
6664887Schin 	fprintf(hf, "\tconst Lc_charset_t*\tcharset;\n");
6674887Schin 	fprintf(hf, "\tconst Lc_attribute_list_t*\tattributes;\n");
6684887Schin 	fprintf(hf, "\tunsigned long\t\tflags;\n");
6694887Schin 	fprintf(hf, "\tunsigned long\t\tindex;\n");
6704887Schin 	fprintf(hf, "#ifdef _LC_PRIVATE_\n");
6714887Schin 	fprintf(hf, "\t_LC_PRIVATE_\n");
6724887Schin 	fprintf(hf, "#endif\n");
6734887Schin 	fprintf(hf, "} Lc_t;\n");
6744887Schin 	fprintf(hf, "\nstruct Lc_category_s;\n");
6754887Schin 	fprintf(hf, "\ntypedef int (*Lc_category_set_f)(struct Lc_category_s*);\n");
6764887Schin 	fprintf(hf, "\ntypedef struct Lc_category_s\n{\n");
6774887Schin 	fprintf(hf, "\tconst char*\t\tname;\n");
6784887Schin 	fprintf(hf, "\tint\t\t\texternal;\n");
6794887Schin 	fprintf(hf, "\tint\t\t\tinternal;\n");
6804887Schin 	fprintf(hf, "\tLc_category_set_f\tsetf;\n");
6814887Schin 	fprintf(hf, "\tLc_t*\t\t\tprev;\n");
682*12068SRoger.Faulkner@Oracle.COM 	fprintf(hf, "\tunsigned int\t\tflags;\n");
6834887Schin 	fprintf(hf, "} Lc_category_t;\n");
6844887Schin 	fprintf(hf, "\n");
6854887Schin 	fprintf(hf, "#if _BLD_ast && defined(__EXPORT__)\n");
6864887Schin 	fprintf(hf, "#define extern\t\t__EXPORT__\n");
6874887Schin 	fprintf(hf, "#endif\n");
6884887Schin 	fprintf(hf, "\n");
6894887Schin 	fprintf(hf, "extern size_t\t\tlccanon(Lc_t*, unsigned long flags, char*, size_t);\n");
6904887Schin 	fprintf(hf, "extern Lc_category_t*\tlccategories(void);\n");
6914887Schin 	fprintf(hf, "extern int\t\tlcindex(int, int);\n");
6924887Schin 	fprintf(hf, "extern Lc_info_t*\tlcinfo(int);\n");
6934887Schin 	fprintf(hf, "extern Lc_t*\t\tlcmake(const char*);\n");
6944887Schin 	fprintf(hf, "extern Lc_t*\t\tlcscan(Lc_t*);\n");
6954887Schin 	fprintf(hf, "\n");
6964887Schin 	fprintf(hf, "#undef\textern\n");
6978462SApril.Chin@Sun.COM 	fprintf(lf, "\nconst Lc_charset_t lc_charsets[] =\n{\n");
6984887Schin 	for (cp = (Charset_t*)state.charset.root; cp; cp = (Charset_t*)cp->link.next)
6994887Schin 	{
7004887Schin 		fprintf(lf, "{\"%s\",", cp->link.code);
7014887Schin 		if (cp->alternates)
7024887Schin 			fprintf(lf, "\"%s\",", cp->alternates);
7034887Schin 		else
7044887Schin 			fprintf(lf, "0,");
7054887Schin 		if (cp->ms)
7064887Schin 			fprintf(lf, "\"%s\",", cp->ms);
7074887Schin 		else
7084887Schin 			fprintf(lf, "0");
7094887Schin 		fprintf(lf, "},\n");
7104887Schin 	}
7114887Schin 	fprintf(lf, "\t0\n};\n");
7128462SApril.Chin@Sun.COM 	fprintf(lf, "\nconst Lc_language_t lc_languages[] =\n{\n");
7138462SApril.Chin@Sun.COM 	fprintf(lf, "{\"C\",\"C\",\"POSIX\",&lc_charsets[0],LC_default,0,");
7144887Schin 	for (i = 0; i < language_attribute_max; i++)
7154887Schin 		fprintf(lf, "0,");
7164887Schin 	fprintf(lf, "},\n");
7178462SApril.Chin@Sun.COM 	fprintf(lf, "{\"debug\",\"debug\",0,&lc_charsets[0],LC_debug,0,");
7184887Schin 	for (i = 0; i < language_attribute_max; i++)
7194887Schin 		fprintf(lf, "0,");
7204887Schin 	fprintf(lf, "},\n");
7214887Schin 	for (lp = (Language_t*)state.language.root; lp; lp = (Language_t*)lp->link.next)
7224887Schin 	{
7234887Schin 		fprintf(lf, "{\"%s\",\"%s\",", lp->link.code, lp->name);
7244887Schin 		if (lp->alternates)
7254887Schin 			fprintf(lf, "\"%s\",", lp->alternates);
7264887Schin 		else
7274887Schin 			fprintf(lf, "0,");
7288462SApril.Chin@Sun.COM 		fprintf(lf, "&lc_charsets[%d],0,", lp->charset ? lp->charset->link.index : 0);
7294887Schin 		macro(lf, "LANG", lp->name, (char*)0);
7304887Schin 		for (i = 0, al = lp->attributes; al; al = al->next, i++)
7314887Schin 			fprintf(lf, "&attribute_%s[%d],", lp->link.code, al->attribute->link.index);
7324887Schin 		for (; i < language_attribute_max; i++)
7334887Schin 			fprintf(lf, "0,");
7344887Schin 		fprintf(lf, "\n},\n");
7354887Schin 	}
7364887Schin 	fprintf(lf, "\t0\n};\n");
7378462SApril.Chin@Sun.COM 	fprintf(lf, "\nconst Lc_territory_t lc_territories[] =\n{\n");
7388462SApril.Chin@Sun.COM 	fprintf(lf, "{\"C\",\"C\",LC_default,0,&lc_languages[0],");
7394887Schin 	for (i = 1; i < 2 * territory_language_max; i++)
7404887Schin 		fprintf(lf, "0,");
7414887Schin 	fprintf(lf, "},\n");
7428462SApril.Chin@Sun.COM 	fprintf(lf, "{\"debug\",\"debug\",LC_debug,0,&lc_languages[1],");
7434887Schin 	for (i = 1; i < 2 * territory_language_max; i++)
7444887Schin 		fprintf(lf, "0,");
7454887Schin 	fprintf(lf, "},\n");
7464887Schin 	for (tp = (Territory_t*)state.territory.root; tp; tp = (Territory_t*)tp->link.next)
7474887Schin 	{
7484887Schin 		fprintf(lf, "{\"%s\",\"%s\",", tp->link.code, tp->name);
7494887Schin 		if (tp->primary)
7504887Schin 			fprintf(lf, "LC_primary,");
7514887Schin 		else
7524887Schin 			fprintf(lf, "0,");
7534887Schin 		macro(lf, "CTRY", tp->name, (char*)0);
7544887Schin 		for (i = 0, ll = tp->languages; ll; ll = ll->next, i++)
7558462SApril.Chin@Sun.COM 			fprintf(lf, "&lc_languages[%d],", ll->language->link.index);
7564887Schin 		for (; i < territory_language_max; i++)
7574887Schin 			fprintf(lf, "0,");
7584887Schin 		for (i = 0, ll = tp->languages; ll; ll = ll->next, i++)
7594887Schin 			macro(lf, "SUBLANG", ll->language->name, tp->name);
7604887Schin 		for (; i < territory_language_max; i++)
7614887Schin 			fprintf(lf, "0,");
7624887Schin 		fprintf(lf, "\n},\n");
7634887Schin 	}
7644887Schin 	fprintf(lf, "\t0\n};\n");
7658462SApril.Chin@Sun.COM 	fprintf(lf, "\nconst Lc_map_t lc_maps[] =\n{\n");
7664887Schin 	for (mp = (Map_t*)state.map.root; mp; mp = (Map_t*)mp->link.next)
7674887Schin 	{
7684887Schin 		fprintf(lf, "{\"%s\",", mp->link.code);
7698462SApril.Chin@Sun.COM 		fprintf(lf, "&lc_languages[%d],", mp->language->link.index);
7708462SApril.Chin@Sun.COM 		fprintf(lf, "&lc_territories[%d],", mp->territory->link.index);
7718462SApril.Chin@Sun.COM 		fprintf(lf, "&lc_charsets[%d],", mp->charset ? mp->charset->link.index : 0);
7724887Schin 		if (mp->attribute)
7734887Schin 			fprintf(lf, "&attribute_%s[%d]", mp->language->link.code, mp->attribute->link.index);
7744887Schin 		else
7754887Schin 			fprintf(lf, "0");
7764887Schin 		fprintf(lf, "},\n");
7774887Schin 	}
7784887Schin 	fprintf(lf, "\t0\n};\n");
7794887Schin 	fclose(lf);
7804887Schin 	fprintf(hf, "\n#endif\n");
7814887Schin 	fclose(hf);
7824887Schin 	return 0;
7834887Schin }
784