xref: /csrg-svn/lib/libc/locale/rune.c (revision 60474)
1*60474Sbostic /*-
2*60474Sbostic  * Copyright (c) 1993 The Regents of the University of California.
3*60474Sbostic  * All rights reserved.
4*60474Sbostic  *
5*60474Sbostic  * This code is derived from software contributed to Berkeley by
6*60474Sbostic  * Paul Borman at Krystal Technologies.
7*60474Sbostic  *
8*60474Sbostic  * %sccs.include.redist.c%
9*60474Sbostic  */
10*60474Sbostic 
11*60474Sbostic #if defined(LIBC_SCCS) && !defined(lint)
12*60474Sbostic static char sccsid[] = "@(#)rune.c	5.1 (Berkeley) 05/26/93";
13*60474Sbostic #endif /* LIBC_SCCS and not lint */
14*60474Sbostic 
15*60474Sbostic #include <sys/types.h>
16*60474Sbostic #include <sys/stat.h>
17*60474Sbostic 
18*60474Sbostic #include <ctype.h>
19*60474Sbostic #include <errno.h>
20*60474Sbostic #include <limits.h>
21*60474Sbostic #include <rune.h>
22*60474Sbostic #include <stdio.h>
23*60474Sbostic #include <stdlib.h>
24*60474Sbostic 
25*60474Sbostic extern int		_none_init __P((_RuneLocale *));
26*60474Sbostic extern int		_UTF2_init __P((_RuneLocale *));
27*60474Sbostic extern int		_EUC_init __P((_RuneLocale *));
28*60474Sbostic static _RuneLocale	*_Read_RuneMagi __P((FILE *));
29*60474Sbostic 
30*60474Sbostic static char *PathLocale = 0;
31*60474Sbostic 
32*60474Sbostic int
33*60474Sbostic setrunelocale(encoding)
34*60474Sbostic 	char *encoding;
35*60474Sbostic {
36*60474Sbostic 	FILE *fp;
37*60474Sbostic 	char name[PATH_MAX];
38*60474Sbostic 	_RuneLocale *rl;
39*60474Sbostic 
40*60474Sbostic 	if (!encoding)
41*60474Sbostic 	    return(EFAULT);
42*60474Sbostic 
43*60474Sbostic 	/*
44*60474Sbostic 	 * The "C" and "POSIX" locale are always here.
45*60474Sbostic 	 */
46*60474Sbostic 	if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) {
47*60474Sbostic 		_CurrentRuneLocale = &_DefaultRuneLocale;
48*60474Sbostic 		return(0);
49*60474Sbostic 	}
50*60474Sbostic 
51*60474Sbostic 	if (!PathLocale && !(PathLocale = getenv("PATH_LOCALE")))
52*60474Sbostic 		PathLocale = _PATH_LOCALE;
53*60474Sbostic 
54*60474Sbostic 	sprintf(name, "%s/%s/LC_CTYPE", PathLocale, encoding);
55*60474Sbostic 
56*60474Sbostic 	if ((fp = fopen(name, "r")) == NULL)
57*60474Sbostic 		return(ENOENT);
58*60474Sbostic 
59*60474Sbostic 	if ((rl = _Read_RuneMagi(fp)) == 0) {
60*60474Sbostic 		fclose(fp);
61*60474Sbostic 		return(EFTYPE);
62*60474Sbostic 	}
63*60474Sbostic 
64*60474Sbostic 	if (!rl->encoding[0] || !strcmp(rl->encoding, "UTF2")) {
65*60474Sbostic 		return(_UTF2_init(rl));
66*60474Sbostic 	} else if (!strcmp(rl->encoding, "NONE")) {
67*60474Sbostic 		return(_none_init(rl));
68*60474Sbostic 	} else if (!strcmp(rl->encoding, "EUC")) {
69*60474Sbostic 		return(_EUC_init(rl));
70*60474Sbostic 	} else
71*60474Sbostic 		return(EINVAL);
72*60474Sbostic }
73*60474Sbostic 
74*60474Sbostic void
75*60474Sbostic setinvalidrune(ir)
76*60474Sbostic 	rune_t ir;
77*60474Sbostic {
78*60474Sbostic 	_INVALID_RUNE = ir;
79*60474Sbostic }
80*60474Sbostic 
81*60474Sbostic static _RuneLocale *
82*60474Sbostic _Read_RuneMagi(fp)
83*60474Sbostic 	FILE *fp;
84*60474Sbostic {
85*60474Sbostic 	char *data;
86*60474Sbostic 	void *np;
87*60474Sbostic 	void *lastp;
88*60474Sbostic 	_RuneLocale *rl;
89*60474Sbostic 	_RuneEntry *rr;
90*60474Sbostic 	struct stat sb;
91*60474Sbostic 	int x;
92*60474Sbostic 
93*60474Sbostic 	if (fstat(fileno(fp), &sb) < 0)
94*60474Sbostic 		return(0);
95*60474Sbostic 
96*60474Sbostic 	if (sb.st_size < sizeof(_RuneLocale))
97*60474Sbostic 		return(0);
98*60474Sbostic 
99*60474Sbostic 	if ((data = malloc(sb.st_size)) == NULL)
100*60474Sbostic 		return(0);
101*60474Sbostic 
102*60474Sbostic 	rewind(fp); /* Someone might have read the magic number once already */
103*60474Sbostic 
104*60474Sbostic 	if (fread(data, sb.st_size, 1, fp) != 1) {
105*60474Sbostic 		free(data);
106*60474Sbostic 		return(0);
107*60474Sbostic 	}
108*60474Sbostic 
109*60474Sbostic 	rl = (_RuneLocale *)data;
110*60474Sbostic 	lastp = data + sb.st_size;
111*60474Sbostic 
112*60474Sbostic 	rl->variable = rl + 1;
113*60474Sbostic 
114*60474Sbostic 	if (memcmp(rl->magic, _RUNE_MAGIC_1, sizeof(rl->magic))) {
115*60474Sbostic 		free(data);
116*60474Sbostic 		return(0);
117*60474Sbostic 	}
118*60474Sbostic 
119*60474Sbostic 	rl->invalid_rune = ntohl(rl->invalid_rune);
120*60474Sbostic 	rl->variable_len = ntohl(rl->variable_len);
121*60474Sbostic 	rl->runetype_ext.nranges = ntohl(rl->runetype_ext.nranges);
122*60474Sbostic 	rl->maplower_ext.nranges = ntohl(rl->maplower_ext.nranges);
123*60474Sbostic 	rl->mapupper_ext.nranges = ntohl(rl->mapupper_ext.nranges);
124*60474Sbostic 
125*60474Sbostic 	for (x = 0; x < _CACHED_RUNES; ++x) {
126*60474Sbostic 		rl->runetype[x] = ntohl(rl->runetype[x]);
127*60474Sbostic 		rl->maplower[x] = ntohl(rl->maplower[x]);
128*60474Sbostic 		rl->mapupper[x] = ntohl(rl->mapupper[x]);
129*60474Sbostic 	}
130*60474Sbostic 
131*60474Sbostic 	rl->runetype_ext.ranges = (_RuneEntry *)rl->variable;
132*60474Sbostic 	rl->variable = rl->runetype_ext.ranges + rl->runetype_ext.nranges;
133*60474Sbostic 	if (rl->variable > lastp) {
134*60474Sbostic 		free(data);
135*60474Sbostic 		return(0);
136*60474Sbostic 	}
137*60474Sbostic 
138*60474Sbostic 	rl->maplower_ext.ranges = (_RuneEntry *)rl->variable;
139*60474Sbostic 	rl->variable = rl->maplower_ext.ranges + rl->maplower_ext.nranges;
140*60474Sbostic 	if (rl->variable > lastp) {
141*60474Sbostic 		free(data);
142*60474Sbostic 		return(0);
143*60474Sbostic 	}
144*60474Sbostic 
145*60474Sbostic 	rl->mapupper_ext.ranges = (_RuneEntry *)rl->variable;
146*60474Sbostic 	rl->variable = rl->mapupper_ext.ranges + rl->mapupper_ext.nranges;
147*60474Sbostic 	if (rl->variable > lastp) {
148*60474Sbostic 		free(data);
149*60474Sbostic 		return(0);
150*60474Sbostic 	}
151*60474Sbostic 
152*60474Sbostic 	for (x = 0; x < rl->runetype_ext.nranges; ++x) {
153*60474Sbostic 		rr = rl->runetype_ext.ranges;
154*60474Sbostic 
155*60474Sbostic 		rr[x].min = ntohl(rr[x].min);
156*60474Sbostic 		rr[x].max = ntohl(rr[x].max);
157*60474Sbostic 		if ((rr[x].map = ntohl(rr[x].map)) == 0) {
158*60474Sbostic 			int len = rr[x].max - rr[x].min + 1;
159*60474Sbostic 			rr[x].types = rl->variable;
160*60474Sbostic 			rl->variable = rr[x].types + len;
161*60474Sbostic 			if (rl->variable > lastp) {
162*60474Sbostic 				free(data);
163*60474Sbostic 				return(0);
164*60474Sbostic 			}
165*60474Sbostic 			while (len-- > 0)
166*60474Sbostic 				rr[x].types[len] = ntohl(rr[x].types[len]);
167*60474Sbostic 		} else
168*60474Sbostic 			rr[x].types = 0;
169*60474Sbostic 	}
170*60474Sbostic 
171*60474Sbostic 	for (x = 0; x < rl->maplower_ext.nranges; ++x) {
172*60474Sbostic 		rr = rl->maplower_ext.ranges;
173*60474Sbostic 
174*60474Sbostic 		rr[x].min = ntohl(rr[x].min);
175*60474Sbostic 		rr[x].max = ntohl(rr[x].max);
176*60474Sbostic 		rr[x].map = ntohl(rr[x].map);
177*60474Sbostic 	}
178*60474Sbostic 
179*60474Sbostic 	for (x = 0; x < rl->mapupper_ext.nranges; ++x) {
180*60474Sbostic 		rr = rl->mapupper_ext.ranges;
181*60474Sbostic 
182*60474Sbostic 		rr[x].min = ntohl(rr[x].min);
183*60474Sbostic 		rr[x].max = ntohl(rr[x].max);
184*60474Sbostic 		rr[x].map = ntohl(rr[x].map);
185*60474Sbostic 	}
186*60474Sbostic 	if (((char *)rl->variable) + rl->variable_len > (char *)lastp) {
187*60474Sbostic 		free(data);
188*60474Sbostic 		return(0);
189*60474Sbostic 	}
190*60474Sbostic 
191*60474Sbostic 	/*
192*60474Sbostic 	 * Go out and zero pointers that should be zero.
193*60474Sbostic 	 */
194*60474Sbostic 	if (!rl->variable_len)
195*60474Sbostic 		rl->variable = 0;
196*60474Sbostic 
197*60474Sbostic 	if (!rl->runetype_ext.nranges)
198*60474Sbostic 		rl->runetype_ext.ranges = 0;
199*60474Sbostic 
200*60474Sbostic 	if (!rl->maplower_ext.nranges)
201*60474Sbostic 		rl->maplower_ext.ranges = 0;
202*60474Sbostic 
203*60474Sbostic 	if (!rl->mapupper_ext.nranges)
204*60474Sbostic 		rl->mapupper_ext.ranges = 0;
205*60474Sbostic 
206*60474Sbostic 	return(rl);
207*60474Sbostic }
208*60474Sbostic 
209*60474Sbostic unsigned long
210*60474Sbostic ___runetype(c)
211*60474Sbostic 	_BSD_RUNE_T_ c;
212*60474Sbostic {
213*60474Sbostic 	int x;
214*60474Sbostic 	_RuneRange *rr = &_CurrentRuneLocale->runetype_ext;
215*60474Sbostic 	_RuneEntry *re = rr->ranges;
216*60474Sbostic 
217*60474Sbostic 	if (c == EOF)
218*60474Sbostic 		return(0);
219*60474Sbostic 	for (x = 0; x < rr->nranges; ++x, ++re) {
220*60474Sbostic 		if (c < re->min)
221*60474Sbostic 			return(0L);
222*60474Sbostic 		if (c <= re->max) {
223*60474Sbostic 			if (re->types)
224*60474Sbostic 			    return(re->types[c - re->min]);
225*60474Sbostic 			else
226*60474Sbostic 			    return(re->map);
227*60474Sbostic 		}
228*60474Sbostic 	}
229*60474Sbostic 	return(0L);
230*60474Sbostic }
231*60474Sbostic 
232*60474Sbostic _BSD_RUNE_T_
233*60474Sbostic ___toupper(c)
234*60474Sbostic 	_BSD_RUNE_T_ c;
235*60474Sbostic {
236*60474Sbostic 	int x;
237*60474Sbostic 	_RuneRange *rr = &_CurrentRuneLocale->mapupper_ext;
238*60474Sbostic 	_RuneEntry *re = rr->ranges;
239*60474Sbostic 
240*60474Sbostic 	if (c == EOF)
241*60474Sbostic 		return(EOF);
242*60474Sbostic 	for (x = 0; x < rr->nranges; ++x, ++re) {
243*60474Sbostic 		if (c < re->min)
244*60474Sbostic 			return(c);
245*60474Sbostic 		if (c <= re->max)
246*60474Sbostic 			return(re->map + c - re->min);
247*60474Sbostic 	}
248*60474Sbostic 	return(c);
249*60474Sbostic }
250*60474Sbostic 
251*60474Sbostic _BSD_RUNE_T_
252*60474Sbostic ___tolower(c)
253*60474Sbostic 	_BSD_RUNE_T_ c;
254*60474Sbostic {
255*60474Sbostic 	int x;
256*60474Sbostic 	_RuneRange *rr = &_CurrentRuneLocale->maplower_ext;
257*60474Sbostic 	_RuneEntry *re = rr->ranges;
258*60474Sbostic 
259*60474Sbostic 	if (c == EOF)
260*60474Sbostic 		return(EOF);
261*60474Sbostic 	for (x = 0; x < rr->nranges; ++x, ++re) {
262*60474Sbostic 		if (c < re->min)
263*60474Sbostic 			return(c);
264*60474Sbostic 		if (c <= re->max)
265*60474Sbostic 			return(re->map + c - re->min);
266*60474Sbostic 	}
267*60474Sbostic 	return(c);
268*60474Sbostic }
269*60474Sbostic 
270*60474Sbostic 
271*60474Sbostic #if !defined(_USE_CTYPE_INLINE_) && !defined(_USE_CTYPE_MACROS_)
272*60474Sbostic /*
273*60474Sbostic  * See comments in <machine/ansi.h>
274*60474Sbostic  */
275*60474Sbostic int
276*60474Sbostic __istype(c, f)
277*60474Sbostic 	_BSD_RUNE_T_ c;
278*60474Sbostic 	unsigned long f;
279*60474Sbostic {
280*60474Sbostic 	return ((((c & _CRMASK) ? ___runetype(c)
281*60474Sbostic            : _CurrentRuneLocale->runetype[c]) & f) ? 1 : 0);
282*60474Sbostic }
283*60474Sbostic 
284*60474Sbostic int
285*60474Sbostic __isctype(_BSD_RUNE_T_ c, unsigned long f)
286*60474Sbostic 	_BSD_RUNE_T_ c;
287*60474Sbostic 	unsigned long f;
288*60474Sbostic {
289*60474Sbostic 	return ((((c & _CRMASK) ? 0
290*60474Sbostic            : _DefaultRuneLocale.runetype[c]) & f) ? 1 : 0);
291*60474Sbostic }
292*60474Sbostic 
293*60474Sbostic _BSD_RUNE_T_
294*60474Sbostic toupper(c)
295*60474Sbostic 	_BSD_RUNE_T_ c;
296*60474Sbostic {
297*60474Sbostic 	return ((c & _CRMASK) ?
298*60474Sbostic 	    ___toupper(c) : _CurrentRuneLocale->mapupper[c]);
299*60474Sbostic }
300*60474Sbostic 
301*60474Sbostic _BSD_RUNE_T_
302*60474Sbostic tolower(c)
303*60474Sbostic 	_BSD_RUNE_T_ c;
304*60474Sbostic {
305*60474Sbostic 	return ((c & _CRMASK) ?
306*60474Sbostic 	    ___tolower(c) : _CurrentRuneLocale->maplower[c]);
307*60474Sbostic }
308*60474Sbostic #endif
309