rune.c revision 1574
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)
38static 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
51extern int		_none_init __P((_RuneLocale *));
52extern int		_UTF2_init __P((_RuneLocale *));
53extern int		_EUC_init __P((_RuneLocale *));
54static _RuneLocale	*_Read_RuneMagi __P((FILE *));
55
56static char *PathLocale = 0;
57
58int
59setrunelocale(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
100void
101setinvalidrune(ir)
102	rune_t ir;
103{
104	_INVALID_RUNE = ir;
105}
106
107static _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
235unsigned 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 */
301int
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
310int
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_
320toupper(c)
321	_BSD_RUNE_T_ c;
322{
323	return ((c & _CRMASK) ?
324	    ___toupper(c) : _CurrentRuneLocale->mapupper[c]);
325}
326
327_BSD_RUNE_T_
328tolower(c)
329	_BSD_RUNE_T_ c;
330{
331	return ((c & _CRMASK) ?
332	    ___tolower(c) : _CurrentRuneLocale->maplower[c]);
333}
334#endif
335