xref: /freebsd/lib/libc/locale/rune.c (revision afe61c15161c324a7af299a9b8457aba5afc92db)
1 /*-
2  * Copyright (c) 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Paul Borman at Krystal Technologies.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #if defined(LIBC_SCCS) && !defined(lint)
38 static char sccsid[] = "@(#)rune.c	8.1 (Berkeley) 6/4/93";
39 #endif /* LIBC_SCCS and not lint */
40 
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 
44 #include <ctype.h>
45 #include <errno.h>
46 #include <limits.h>
47 #include <rune.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 
51 extern int		_none_init __P((_RuneLocale *));
52 extern int		_UTF2_init __P((_RuneLocale *));
53 extern int		_EUC_init __P((_RuneLocale *));
54 static _RuneLocale	*_Read_RuneMagi __P((FILE *));
55 
56 static char *PathLocale = 0;
57 
58 int
59 setrunelocale(encoding)
60 	char *encoding;
61 {
62 	FILE *fp;
63 	char name[PATH_MAX];
64 	_RuneLocale *rl;
65 
66 	if (!encoding)
67 	    return(EFAULT);
68 
69 	/*
70 	 * The "C" and "POSIX" locale are always here.
71 	 */
72 	if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) {
73 		_CurrentRuneLocale = &_DefaultRuneLocale;
74 		return(0);
75 	}
76 
77 	if (!PathLocale && !(PathLocale = getenv("PATH_LOCALE")))
78 		PathLocale = _PATH_LOCALE;
79 
80 	sprintf(name, "%s/%s/LC_CTYPE", PathLocale, encoding);
81 
82 	if ((fp = fopen(name, "r")) == NULL)
83 		return(ENOENT);
84 
85 	if ((rl = _Read_RuneMagi(fp)) == 0) {
86 		fclose(fp);
87 		return(EFTYPE);
88 	}
89 
90 	if (!rl->encoding[0] || !strcmp(rl->encoding, "UTF2")) {
91 		return(_UTF2_init(rl));
92 	} else if (!strcmp(rl->encoding, "NONE")) {
93 		return(_none_init(rl));
94 	} else if (!strcmp(rl->encoding, "EUC")) {
95 		return(_EUC_init(rl));
96 	} else
97 		return(EINVAL);
98 }
99 
100 void
101 setinvalidrune(ir)
102 	rune_t ir;
103 {
104 	_INVALID_RUNE = ir;
105 }
106 
107 static _RuneLocale *
108 _Read_RuneMagi(fp)
109 	FILE *fp;
110 {
111 	char *data;
112 	void *np;
113 	void *lastp;
114 	_RuneLocale *rl;
115 	_RuneEntry *rr;
116 	struct stat sb;
117 	int x;
118 
119 	if (fstat(fileno(fp), &sb) < 0)
120 		return(0);
121 
122 	if (sb.st_size < sizeof(_RuneLocale))
123 		return(0);
124 
125 	if ((data = malloc(sb.st_size)) == NULL)
126 		return(0);
127 
128 	rewind(fp); /* Someone might have read the magic number once already */
129 
130 	if (fread(data, sb.st_size, 1, fp) != 1) {
131 		free(data);
132 		return(0);
133 	}
134 
135 	rl = (_RuneLocale *)data;
136 	lastp = data + sb.st_size;
137 
138 	rl->variable = rl + 1;
139 
140 	if (memcmp(rl->magic, _RUNE_MAGIC_1, sizeof(rl->magic))) {
141 		free(data);
142 		return(0);
143 	}
144 
145 	rl->invalid_rune = ntohl(rl->invalid_rune);
146 	rl->variable_len = ntohl(rl->variable_len);
147 	rl->runetype_ext.nranges = ntohl(rl->runetype_ext.nranges);
148 	rl->maplower_ext.nranges = ntohl(rl->maplower_ext.nranges);
149 	rl->mapupper_ext.nranges = ntohl(rl->mapupper_ext.nranges);
150 
151 	for (x = 0; x < _CACHED_RUNES; ++x) {
152 		rl->runetype[x] = ntohl(rl->runetype[x]);
153 		rl->maplower[x] = ntohl(rl->maplower[x]);
154 		rl->mapupper[x] = ntohl(rl->mapupper[x]);
155 	}
156 
157 	rl->runetype_ext.ranges = (_RuneEntry *)rl->variable;
158 	rl->variable = rl->runetype_ext.ranges + rl->runetype_ext.nranges;
159 	if (rl->variable > lastp) {
160 		free(data);
161 		return(0);
162 	}
163 
164 	rl->maplower_ext.ranges = (_RuneEntry *)rl->variable;
165 	rl->variable = rl->maplower_ext.ranges + rl->maplower_ext.nranges;
166 	if (rl->variable > lastp) {
167 		free(data);
168 		return(0);
169 	}
170 
171 	rl->mapupper_ext.ranges = (_RuneEntry *)rl->variable;
172 	rl->variable = rl->mapupper_ext.ranges + rl->mapupper_ext.nranges;
173 	if (rl->variable > lastp) {
174 		free(data);
175 		return(0);
176 	}
177 
178 	for (x = 0; x < rl->runetype_ext.nranges; ++x) {
179 		rr = rl->runetype_ext.ranges;
180 
181 		rr[x].min = ntohl(rr[x].min);
182 		rr[x].max = ntohl(rr[x].max);
183 		if ((rr[x].map = ntohl(rr[x].map)) == 0) {
184 			int len = rr[x].max - rr[x].min + 1;
185 			rr[x].types = rl->variable;
186 			rl->variable = rr[x].types + len;
187 			if (rl->variable > lastp) {
188 				free(data);
189 				return(0);
190 			}
191 			while (len-- > 0)
192 				rr[x].types[len] = ntohl(rr[x].types[len]);
193 		} else
194 			rr[x].types = 0;
195 	}
196 
197 	for (x = 0; x < rl->maplower_ext.nranges; ++x) {
198 		rr = rl->maplower_ext.ranges;
199 
200 		rr[x].min = ntohl(rr[x].min);
201 		rr[x].max = ntohl(rr[x].max);
202 		rr[x].map = ntohl(rr[x].map);
203 	}
204 
205 	for (x = 0; x < rl->mapupper_ext.nranges; ++x) {
206 		rr = rl->mapupper_ext.ranges;
207 
208 		rr[x].min = ntohl(rr[x].min);
209 		rr[x].max = ntohl(rr[x].max);
210 		rr[x].map = ntohl(rr[x].map);
211 	}
212 	if (((char *)rl->variable) + rl->variable_len > (char *)lastp) {
213 		free(data);
214 		return(0);
215 	}
216 
217 	/*
218 	 * Go out and zero pointers that should be zero.
219 	 */
220 	if (!rl->variable_len)
221 		rl->variable = 0;
222 
223 	if (!rl->runetype_ext.nranges)
224 		rl->runetype_ext.ranges = 0;
225 
226 	if (!rl->maplower_ext.nranges)
227 		rl->maplower_ext.ranges = 0;
228 
229 	if (!rl->mapupper_ext.nranges)
230 		rl->mapupper_ext.ranges = 0;
231 
232 	return(rl);
233 }
234 
235 unsigned long
236 ___runetype(c)
237 	_BSD_RUNE_T_ c;
238 {
239 	int x;
240 	_RuneRange *rr = &_CurrentRuneLocale->runetype_ext;
241 	_RuneEntry *re = rr->ranges;
242 
243 	if (c == EOF)
244 		return(0);
245 	for (x = 0; x < rr->nranges; ++x, ++re) {
246 		if (c < re->min)
247 			return(0L);
248 		if (c <= re->max) {
249 			if (re->types)
250 			    return(re->types[c - re->min]);
251 			else
252 			    return(re->map);
253 		}
254 	}
255 	return(0L);
256 }
257 
258 _BSD_RUNE_T_
259 ___toupper(c)
260 	_BSD_RUNE_T_ c;
261 {
262 	int x;
263 	_RuneRange *rr = &_CurrentRuneLocale->mapupper_ext;
264 	_RuneEntry *re = rr->ranges;
265 
266 	if (c == EOF)
267 		return(EOF);
268 	for (x = 0; x < rr->nranges; ++x, ++re) {
269 		if (c < re->min)
270 			return(c);
271 		if (c <= re->max)
272 			return(re->map + c - re->min);
273 	}
274 	return(c);
275 }
276 
277 _BSD_RUNE_T_
278 ___tolower(c)
279 	_BSD_RUNE_T_ c;
280 {
281 	int x;
282 	_RuneRange *rr = &_CurrentRuneLocale->maplower_ext;
283 	_RuneEntry *re = rr->ranges;
284 
285 	if (c == EOF)
286 		return(EOF);
287 	for (x = 0; x < rr->nranges; ++x, ++re) {
288 		if (c < re->min)
289 			return(c);
290 		if (c <= re->max)
291 			return(re->map + c - re->min);
292 	}
293 	return(c);
294 }
295 
296 
297 #if !defined(_USE_CTYPE_INLINE_) && !defined(_USE_CTYPE_MACROS_)
298 /*
299  * See comments in <machine/ansi.h>
300  */
301 int
302 __istype(c, f)
303 	_BSD_RUNE_T_ c;
304 	unsigned long f;
305 {
306 	return ((((c & _CRMASK) ? ___runetype(c)
307            : _CurrentRuneLocale->runetype[c]) & f) ? 1 : 0);
308 }
309 
310 int
311 __isctype(_BSD_RUNE_T_ c, unsigned long f)
312 	_BSD_RUNE_T_ c;
313 	unsigned long f;
314 {
315 	return ((((c & _CRMASK) ? 0
316            : _DefaultRuneLocale.runetype[c]) & f) ? 1 : 0);
317 }
318 
319 _BSD_RUNE_T_
320 toupper(c)
321 	_BSD_RUNE_T_ c;
322 {
323 	return ((c & _CRMASK) ?
324 	    ___toupper(c) : _CurrentRuneLocale->mapupper[c]);
325 }
326 
327 _BSD_RUNE_T_
328 tolower(c)
329 	_BSD_RUNE_T_ c;
330 {
331 	return ((c & _CRMASK) ?
332 	    ___tolower(c) : _CurrentRuneLocale->maplower[c]);
333 }
334 #endif
335