Initial import of binutils 2.22 on the new vendor branch
[dragonfly.git] / lib / libc / locale / rune.c
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 09:18:37 swildner Exp $ */
3
4 /*-
5  * Copyright (c)1999 Citrus Project,
6  * All rights reserved.
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  *
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.
28  */
29
30 /*-
31  * Copyright (c) 1993
32  *      The Regents of the University of California.  All rights reserved.
33  *
34  * This code is derived from software contributed to Berkeley by
35  * Paul Borman at Krystal Technologies.
36  *
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.
48  *
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.
60  */
61
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>
70
71 #include <arpa/inet.h>
72
73 #include "../citrus/citrus_module.h"
74 #include "../citrus/citrus_ctype.h"
75 #include "rune.h"
76 #include "rune_local.h"
77
78 static int      readrange(_RuneLocale *, _RuneRange *, _FileRuneRange *,
79                           void *, FILE *);
80 static void     _freeentry(_RuneRange *);
81 static void     _wctype_init(_RuneLocale *rl);
82
83 static int
84 readrange(_RuneLocale *rl, _RuneRange *rr, _FileRuneRange *frr, void *lastp,
85           FILE *fp)
86 {
87         uint32_t i;
88         _RuneEntry *re;
89         _FileRuneEntry fre;
90
91         _DIAGASSERT(rl != NULL);
92         _DIAGASSERT(rr != NULL);
93         _DIAGASSERT(frr != NULL);
94         _DIAGASSERT(lastp != NULL);
95         _DIAGASSERT(fp != NULL);
96
97         re = (_RuneEntry *)rl->rl_variable;
98
99         rr->rr_nranges = ntohl(frr->frr_nranges);
100         if (rr->rr_nranges == 0) {
101                 rr->rr_rune_ranges = NULL;
102                 return(0);
103         }
104
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);
109
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++;
114
115                 if ((void *)re > lastp)
116                         return(-1);
117         }
118         rl->rl_variable = re;
119         return(0);
120 }
121
122 static int
123 readentry(_RuneRange *rr, FILE *fp)
124 {
125         _RuneEntry *re;
126         size_t l, i, j;
127         int error;
128
129         _DIAGASSERT(rr != NULL);
130         _DIAGASSERT(fp != NULL);
131
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;
137                 }
138
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;
144                 }
145                 memset(re[i].re_rune_types, 0, l * sizeof(_RuneType));
146
147                 if (fread(re[i].re_rune_types, sizeof(_RuneType), l, fp) != l)
148                         goto fail2;
149
150                 for (j = 0; j < l; j++)
151                         re[i].re_rune_types[j] = ntohl(re[i].re_rune_types[j]);
152         }
153         return(0);
154
155 fail:
156         for (j = 0; j < i; j++) {
157                 free(re[j].re_rune_types);
158                 re[j].re_rune_types = NULL;
159         }
160         return(error);
161
162 fail2:
163         for (j = 0; j <= i; j++) {
164                 free(re[j].re_rune_types);
165                 re[j].re_rune_types = NULL;
166         }
167         return(errno);
168 }
169
170 /* XXX: temporary implementation */
171 static void
172 find_codeset(_RuneLocale *rl)
173 {
174         char *top, *codeset, *tail, *ep;
175
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);
192         }
193 }
194
195 static void
196 _freeentry(_RuneRange *rr)
197 {
198         _RuneEntry *re;
199         uint32_t i;
200
201         _DIAGASSERT(rr != NULL);
202
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;
208         }
209 }
210
211 void
212 _wctype_init(_RuneLocale *rl)
213 {
214         memcpy(&rl->rl_wctype, &_DefaultRuneLocale.rl_wctype,
215                sizeof(rl->rl_wctype));
216 }
217
218
219 _RuneLocale *
220 _Read_RuneMagi(FILE *fp)
221 {
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;
231
232         _DIAGASSERT(fp != NULL);
233
234         if (fstat(fileno(fp), &sb) < 0)
235                 return(NULL);
236
237         if (sb.st_size < sizeof(_FileRuneLocale))
238                 return(NULL);
239         /* XXX more validation? */
240
241         /* Someone might have read the magic number once already */
242         rewind(fp);
243
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);
248
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);
253
254         if ((hostdata = malloc(hostdatalen)) == NULL)
255                 return(NULL);
256         memset(hostdata, 0, hostdatalen);
257         lastp = hostdata + hostdatalen;
258
259         rl = (_RuneLocale *)(void *)hostdata;
260         rl->rl_variable = rl + 1;
261
262         memcpy(rl->rl_magic, frl.frl_magic, sizeof(rl->rl_magic));
263         memcpy(rl->rl_encoding, frl.frl_encoding, sizeof(rl->rl_encoding));
264
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);
267
268         for (x = 0; x < _CACHED_RUNES; ++x) {
269                 rl->rl_runetype[x] = ntohl(frl.frl_runetype[x]);
270
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]);
274         }
275
276         if (readrange(rl, &rl->rl_runetype_ext, &frl.frl_runetype_ext,
277                       lastp, fp)) {
278                 free(hostdata);
279                 return(NULL);
280         }
281         if (readrange(rl, &rl->rl_maplower_ext, &frl.frl_maplower_ext,
282                       lastp, fp)) {
283                 free(hostdata);
284                 return(NULL);
285         }
286         if (readrange(rl, &rl->rl_mapupper_ext, &frl.frl_mapupper_ext,
287                       lastp, fp)) {
288                 free(hostdata);
289                 return(NULL);
290         }
291
292         if (readentry(&rl->rl_runetype_ext, fp) != 0) {
293                 free(hostdata);
294                 return(NULL);
295         }
296
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);
302         }
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);
309         }
310         find_codeset(rl);
311         _wctype_init(rl);
312
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);
318         }
319
320         return(rl);
321 }
322
323 void
324 _NukeRune(_RuneLocale *rl)
325 {
326         _DIAGASSERT(rl != NULL);
327
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);
335         }
336 }