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