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
setrunelocale(encoding)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
setinvalidrune(ir)75 setinvalidrune(ir)
76 rune_t ir;
77 {
78 _INVALID_RUNE = ir;
79 }
80
81 static _RuneLocale *
_Read_RuneMagi(fp)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
___runetype(c)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_
___toupper(c)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_
___tolower(c)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
__istype(c,f)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_
toupper(c)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_
tolower(c)302 tolower(c)
303 _BSD_RUNE_T_ c;
304 {
305 return ((c & _CRMASK) ?
306 ___tolower(c) : _CurrentRuneLocale->maplower[c]);
307 }
308 #endif
309