Add a manual page explaining the format of /etc/manpath.config.
[dragonfly/vkernel-mp.git] / lib / libc / locale / rune.c
blob43967bb967b3f4a76119b58e7f7cb1a2a982baf2
1 /* $NetBSD: src/lib/libc/locale/rune.c,v 1.26 2004/05/09 11:26:33 kleink Exp $ */
2 /* $DragonFly: src/lib/libc/locale/rune.c,v 1.6 2005/11/20 10:18:37 swildner Exp $ */
4 /*-
5 * Copyright (c)1999 Citrus Project,
6 * All rights reserved.
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.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
30 /*-
31 * Copyright (c) 1993
32 * The Regents of the University of California. All rights reserved.
34 * This code is derived from software contributed to Berkeley by
35 * Paul Borman at Krystal Technologies.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
62 #include <sys/types.h>
63 #include <sys/stat.h>
64 #include <assert.h>
65 #include <errno.h>
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <wchar.h>
71 #include <arpa/inet.h>
73 #include "../citrus/citrus_module.h"
74 #include "../citrus/citrus_ctype.h"
75 #include "rune.h"
76 #include "rune_local.h"
78 static int readrange(_RuneLocale *, _RuneRange *, _FileRuneRange *,
79 void *, FILE *);
80 static void _freeentry(_RuneRange *);
81 static void _wctype_init(_RuneLocale *rl);
83 static int
84 readrange(_RuneLocale *rl, _RuneRange *rr, _FileRuneRange *frr, void *lastp,
85 FILE *fp)
87 uint32_t i;
88 _RuneEntry *re;
89 _FileRuneEntry fre;
91 _DIAGASSERT(rl != NULL);
92 _DIAGASSERT(rr != NULL);
93 _DIAGASSERT(frr != NULL);
94 _DIAGASSERT(lastp != NULL);
95 _DIAGASSERT(fp != NULL);
97 re = (_RuneEntry *)rl->rl_variable;
99 rr->rr_nranges = ntohl(frr->frr_nranges);
100 if (rr->rr_nranges == 0) {
101 rr->rr_rune_ranges = NULL;
102 return(0);
105 rr->rr_rune_ranges = re;
106 for (i = 0; i < rr->rr_nranges; i++) {
107 if (fread(&fre, sizeof(fre), 1, fp) != 1)
108 return(-1);
110 re->re_min = ntohl((uint32_t)fre.fre_min);
111 re->re_max = ntohl((uint32_t)fre.fre_max);
112 re->re_map = ntohl((uint32_t)fre.fre_map);
113 re++;
115 if ((void *)re > lastp)
116 return(-1);
118 rl->rl_variable = re;
119 return(0);
122 static int
123 readentry(_RuneRange *rr, FILE *fp)
125 _RuneEntry *re;
126 size_t l, i, j;
127 int error;
129 _DIAGASSERT(rr != NULL);
130 _DIAGASSERT(fp != NULL);
132 re = rr->rr_rune_ranges;
133 for (i = 0; i < rr->rr_nranges; i++) {
134 if (re[i].re_map != 0) {
135 re[i].re_rune_types = NULL;
136 continue;
139 l = re[i].re_max - re[i].re_min + 1;
140 re[i].re_rune_types = malloc(l * sizeof(_RuneType));
141 if (!re[i].re_rune_types) {
142 error = ENOMEM;
143 goto fail;
145 memset(re[i].re_rune_types, 0, l * sizeof(_RuneType));
147 if (fread(re[i].re_rune_types, sizeof(_RuneType), l, fp) != l)
148 goto fail2;
150 for (j = 0; j < l; j++)
151 re[i].re_rune_types[j] = ntohl(re[i].re_rune_types[j]);
153 return(0);
155 fail:
156 for (j = 0; j < i; j++) {
157 free(re[j].re_rune_types);
158 re[j].re_rune_types = NULL;
160 return(error);
162 fail2:
163 for (j = 0; j <= i; j++) {
164 free(re[j].re_rune_types);
165 re[j].re_rune_types = NULL;
167 return(errno);
170 /* XXX: temporary implementation */
171 static void
172 find_codeset(_RuneLocale *rl)
174 char *top, *codeset, *tail, *ep;
176 /* end of rl_variable region */
177 ep = (char *)rl->rl_variable;
178 ep += rl->rl_variable_len;
179 rl->rl_codeset = NULL;
180 if (!(top = strstr(rl->rl_variable, _RUNE_CODESET)))
181 return;
182 tail = strpbrk(top, " \t");
183 codeset = top + sizeof(_RUNE_CODESET) - 1;
184 if (tail) {
185 *top = *tail;
186 *tail = '\0';
187 rl->rl_codeset = strdup(codeset);
188 strlcpy(top + 1, tail + 1, (unsigned)(ep - (top + 1)));
189 } else {
190 *top = '\0';
191 rl->rl_codeset = strdup(codeset);
195 static void
196 _freeentry(_RuneRange *rr)
198 _RuneEntry *re;
199 uint32_t i;
201 _DIAGASSERT(rr != NULL);
203 re = rr->rr_rune_ranges;
204 for (i = 0; i < rr->rr_nranges; i++) {
205 if (re[i].re_rune_types)
206 free(re[i].re_rune_types);
207 re[i].re_rune_types = NULL;
211 void
212 _wctype_init(_RuneLocale *rl)
214 memcpy(&rl->rl_wctype, &_DefaultRuneLocale.rl_wctype,
215 sizeof(rl->rl_wctype));
219 _RuneLocale *
220 _Read_RuneMagi(FILE *fp)
222 /* file */
223 _FileRuneLocale frl;
224 /* host data */
225 char *hostdata;
226 size_t hostdatalen;
227 void *lastp;
228 _RuneLocale *rl;
229 struct stat sb;
230 int x;
232 _DIAGASSERT(fp != NULL);
234 if (fstat(fileno(fp), &sb) < 0)
235 return(NULL);
237 if (sb.st_size < sizeof(_FileRuneLocale))
238 return(NULL);
239 /* XXX more validation? */
241 /* Someone might have read the magic number once already */
242 rewind(fp);
244 if (fread(&frl, sizeof(frl), 1, fp) != 1)
245 return(NULL);
246 if (memcmp(frl.frl_magic, _RUNE_MAGIC_1, sizeof(frl.frl_magic)))
247 return(NULL);
249 hostdatalen = sizeof(*rl) + ntohl((u_int32_t)frl.frl_variable_len) +
250 ntohl(frl.frl_runetype_ext.frr_nranges) * sizeof(_RuneEntry) +
251 ntohl(frl.frl_maplower_ext.frr_nranges) * sizeof(_RuneEntry) +
252 ntohl(frl.frl_mapupper_ext.frr_nranges) * sizeof(_RuneEntry);
254 if ((hostdata = malloc(hostdatalen)) == NULL)
255 return(NULL);
256 memset(hostdata, 0, hostdatalen);
257 lastp = hostdata + hostdatalen;
259 rl = (_RuneLocale *)(void *)hostdata;
260 rl->rl_variable = rl + 1;
262 memcpy(rl->rl_magic, frl.frl_magic, sizeof(rl->rl_magic));
263 memcpy(rl->rl_encoding, frl.frl_encoding, sizeof(rl->rl_encoding));
265 rl->rl_invalid_rune = ntohl((u_int32_t)frl.frl_invalid_rune);
266 rl->rl_variable_len = ntohl((u_int32_t)frl.frl_variable_len);
268 for (x = 0; x < _CACHED_RUNES; ++x) {
269 rl->rl_runetype[x] = ntohl(frl.frl_runetype[x]);
271 /* XXX assumes rune_t = u_int32_t */
272 rl->rl_maplower[x] = ntohl((uint32_t)frl.frl_maplower[x]);
273 rl->rl_mapupper[x] = ntohl((uint32_t)frl.frl_mapupper[x]);
276 if (readrange(rl, &rl->rl_runetype_ext, &frl.frl_runetype_ext,
277 lastp, fp)) {
278 free(hostdata);
279 return(NULL);
281 if (readrange(rl, &rl->rl_maplower_ext, &frl.frl_maplower_ext,
282 lastp, fp)) {
283 free(hostdata);
284 return(NULL);
286 if (readrange(rl, &rl->rl_mapupper_ext, &frl.frl_mapupper_ext,
287 lastp, fp)) {
288 free(hostdata);
289 return(NULL);
292 if (readentry(&rl->rl_runetype_ext, fp) != 0) {
293 free(hostdata);
294 return(NULL);
297 if ((uint8_t *)rl->rl_variable + rl->rl_variable_len >
298 (uint8_t *)lastp) {
299 _freeentry(&rl->rl_runetype_ext);
300 free(hostdata);
301 return(NULL);
303 if (rl->rl_variable_len == 0)
304 rl->rl_variable = NULL;
305 else if (fread(rl->rl_variable, rl->rl_variable_len, 1, fp) != 1) {
306 _freeentry(&rl->rl_runetype_ext);
307 free(hostdata);
308 return(NULL);
310 find_codeset(rl);
311 _wctype_init(rl);
313 /* error if we have junk at the tail */
314 if (ftell(fp) != sb.st_size) {
315 _freeentry(&rl->rl_runetype_ext);
316 free(hostdata);
317 return(NULL);
320 return(rl);
323 void
324 _NukeRune(_RuneLocale *rl)
326 _DIAGASSERT(rl != NULL);
328 if (rl != &_DefaultRuneLocale) {
329 _freeentry(&rl->rl_runetype_ext);
330 if (rl->rl_codeset != NULL)
331 free(rl->rl_codeset);
332 if (rl->rl_citrus_ctype)
333 _citrus_ctype_close(rl->rl_citrus_ctype);
334 free(rl);