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