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 * 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 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#ifndef RUNEOFF32 38#if defined(LIBC_SCCS) && !defined(lint) 39static char sccsid[] = "@(#)rune.c 8.1 (Berkeley) 6/4/93"; 40#endif /* LIBC_SCCS and not lint */ 41#include <sys/cdefs.h> 42__FBSDID("$FreeBSD: src/lib/libc/locale/rune.c,v 1.12 2004/07/29 06:16:19 tjr Exp $"); 43 44#include "xlocale_private.h" 45 46#include "namespace.h" 47#include <arpa/inet.h> 48#include <errno.h> 49#include <runetype.h> 50#else 51#include "runetype.h" 52#endif /* !RUNEOFF32 */ 53#include <stdio.h> 54#ifndef RUNEOFF32 55#include <string.h> 56#include <stdlib.h> 57#include <sys/types.h> 58#include <sys/stat.h> 59#include "un-namespace.h" 60#endif /* !RUNEOFF32 */ 61 62#if defined(__LP64__) || defined(RUNEOFF32) 63/* 64 * Because the LC_CTYPE files were created with a 32-bit program, we need 65 * to adjust for the larger pointers in LP64 (the longs have already been 66 * replaced by 32-bit equivalents). Also, natural alignment will pad 67 * 64-bit types to 8-byte boundaries, and make structures containing 68 * 64-bit types sized to 8-byte boundaries. 69 */ 70#include <stddef.h> 71#ifndef RUNEOFF32 72#include "rune32.h" 73#define BYTES32BITS 4 74#define BYTES64BITS 8 75/* whether to skip over a pointer or not (one-to-one with off64) */ 76int skip[] = { 77 1, 78 1, 79 0, 80 1, 81 0, 82 1, 83 0, 84 1, 85 1, 86 1, 87 0 88}; 89#endif /* !RUNEOFF32 */ 90int off64[] = { 91 offsetof(_RuneLocale, __sgetrune), 92 offsetof(_RuneLocale, __sputrune), 93 offsetof(_RuneLocale, __runetype_ext), 94 offsetof(_RuneLocale, __runetype_ext) + offsetof(_RuneRange, __ranges), 95 offsetof(_RuneLocale, __maplower_ext), 96 offsetof(_RuneLocale, __maplower_ext) + offsetof(_RuneRange, __ranges), 97 offsetof(_RuneLocale, __mapupper_ext), 98 offsetof(_RuneLocale, __mapupper_ext) + offsetof(_RuneRange, __ranges), 99 offsetof(_RuneLocale, __variable), 100 offsetof(_RuneLocale, __charclasses), 101 sizeof(_RuneLocale) 102}; 103#define NOFF (sizeof(off64) / sizeof(int)) 104#ifdef RUNEOFF32 105/* 106 * This program generates a header file (on stdout) that containes the 32-bit 107 * offsets, plus some 32-bit sizes 108 */ 109main() 110{ 111 int i; 112 printf("#define SIZEOF32_RUNEENTRY %d\n", sizeof(_RuneEntry)); 113 printf("#define SIZEOF32_RUNELOCALE %d\n", sizeof(_RuneLocale)); 114 printf("int off32[] = {\n"); 115 for(i = 0; i < NOFF; i++) 116 printf("\t%d,\n", off64[i]); 117 printf("};\n"); 118 return 0; 119} 120#endif /* RUNEOFF32 */ 121#else /* !__LP64__ && !RUNEOFF32 */ 122#define SIZEOF32_RUNELOCALE sizeof(_RuneLocale) 123#endif /* __LP64__ || RUNEOFF32 */ 124 125#ifndef RUNEOFF32 126struct __xlocale_st_runelocale * 127_Read_RuneMagi(fp) 128 FILE *fp; 129{ 130 struct __xlocale_st_runelocale *data; 131 void *lastp; 132 _RuneLocale *rl; 133 _RuneEntry *rr; 134 struct stat sb; 135 int x, saverr; 136 137 if (_fstat(fileno(fp), &sb) < 0) 138 return (NULL); 139 140 if (sb.st_size < SIZEOF32_RUNELOCALE) { 141 errno = EFTYPE; 142 return (NULL); 143 } 144 145#ifdef __LP64__ 146 /* will adjust later */ 147 if ((data = (struct __xlocale_st_runelocale *)malloc(sizeof(struct __xlocale_st_runelocale))) == NULL) 148#else /* !__LP64__ */ 149 if ((data = (struct __xlocale_st_runelocale *)malloc(sizeof(struct __xlocale_st_runelocale) - sizeof(_RuneLocale) + sb.st_size)) == NULL) 150#endif /* __LP64__ */ 151 return (NULL); 152 data->__refcount = 1; 153 data->__free_extra = NULL; 154 155 errno = 0; 156 rewind(fp); /* Someone might have read the magic number once already */ 157 if (errno) { 158 saverr = errno; 159 free(data); 160 errno = saverr; 161 return (NULL); 162 } 163 164 rl = &data->_CurrentRuneLocale; 165 166#ifdef __LP64__ 167 if (fread(rl, SIZEOF32_RUNELOCALE, 1, fp) != 1) 168#else /* !__LP64__ */ 169 if (fread(rl, sb.st_size, 1, fp) != 1) 170#endif /* __LP64__ */ 171 { 172 saverr = errno; 173 free(data); 174 errno = saverr; 175 return (NULL); 176 } 177 178#ifndef __LP64__ 179 lastp = (char *)rl + sb.st_size; 180 181 rl->__variable = rl + 1; 182#endif /* __LP64__ */ 183 184 if (memcmp(rl->__magic, _RUNE_MAGIC_A, sizeof(rl->__magic))) { 185 free(data); 186 errno = EFTYPE; 187 return (NULL); 188 } 189 190#ifdef __LP64__ 191 /* shift things into the right position */ 192 for (x = NOFF - 2; x >= 0; x--) 193 memmove((char *)rl + off64[x] + (skip[x] ? BYTES64BITS : 0), 194 (char *)rl + off32[x] + (skip[x] ? BYTES32BITS : 0), 195 off32[x + 1] - off32[x] - (skip[x] ? BYTES32BITS : 0)); 196#endif /* __LP64__ */ 197#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN 198 rl->__invalid_rune = ntohl(rl->__invalid_rune); 199 rl->__variable_len = ntohl(rl->__variable_len); 200 rl->__ncharclasses = ntohl(rl->__ncharclasses); 201 rl->__runetype_ext.__nranges = ntohl(rl->__runetype_ext.__nranges); 202 rl->__maplower_ext.__nranges = ntohl(rl->__maplower_ext.__nranges); 203 rl->__mapupper_ext.__nranges = ntohl(rl->__mapupper_ext.__nranges); 204 205 for (x = 0; x < _CACHED_RUNES; ++x) { 206 rl->__runetype[x] = ntohl(rl->__runetype[x]); 207 rl->__maplower[x] = ntohl(rl->__maplower[x]); 208 rl->__mapupper[x] = ntohl(rl->__mapupper[x]); 209 } 210#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */ 211 212#ifdef __LP64__ 213 { 214 int count = rl->__runetype_ext.__nranges + rl->__maplower_ext.__nranges 215 + rl->__mapupper_ext.__nranges; 216 int extra = sb.st_size - SIZEOF32_RUNELOCALE - count * SIZEOF32_RUNEENTRY - rl->__ncharclasses * sizeof(_RuneCharClass); 217 _RuneEntry *rp; 218 219 if (extra < 0) { 220 saverr = errno; 221 free(data); 222 errno = saverr; 223 return (NULL); 224 } 225 if ((data = (struct __xlocale_st_runelocale *)reallocf(data, sizeof(struct __xlocale_st_runelocale) 226 + count * sizeof(_RuneEntry) 227 + rl->__ncharclasses * sizeof(_RuneCharClass) 228 + extra)) == NULL) 229 return (NULL); 230 rl = &data->_CurrentRuneLocale; 231 rl->__variable = rl + 1; 232 rp = (_RuneEntry *)rl->__variable; 233 for (x = 0; x < count; x++, rp++) 234 if (fread(rp, SIZEOF32_RUNEENTRY, 1, fp) != 1) { 235 saverr = errno; 236 free(data); 237 errno = saverr; 238 return (NULL); 239 } 240 if (rl->__ncharclasses > 0) { 241 if (fread(rp, sizeof(_RuneCharClass), rl->__ncharclasses, fp) != rl->__ncharclasses) { 242 saverr = errno; 243 free(data); 244 errno = saverr; 245 return (NULL); 246 } 247 rp = (_RuneEntry *)((char *)rp + rl->__ncharclasses * sizeof(_RuneCharClass)); 248 } 249 if (extra > 0 && fread(rp, extra, 1, fp) != 1) { 250 saverr = errno; 251 free(data); 252 errno = saverr; 253 return (NULL); 254 } 255 lastp = (char *)rp + extra; 256 } 257#endif /* __LP64__ */ 258 rl->__runetype_ext.__ranges = (_RuneEntry *)rl->__variable; 259 rl->__variable = rl->__runetype_ext.__ranges + 260 rl->__runetype_ext.__nranges; 261 if (rl->__variable > lastp) { 262 free(data); 263 errno = EFTYPE; 264 return (NULL); 265 } 266 267 rl->__maplower_ext.__ranges = (_RuneEntry *)rl->__variable; 268 rl->__variable = rl->__maplower_ext.__ranges + 269 rl->__maplower_ext.__nranges; 270 if (rl->__variable > lastp) { 271 free(data); 272 errno = EFTYPE; 273 return (NULL); 274 } 275 276 rl->__mapupper_ext.__ranges = (_RuneEntry *)rl->__variable; 277 rl->__variable = rl->__mapupper_ext.__ranges + 278 rl->__mapupper_ext.__nranges; 279 if (rl->__variable > lastp) { 280 free(data); 281 errno = EFTYPE; 282 return (NULL); 283 } 284 285 for (x = 0; x < rl->__runetype_ext.__nranges; ++x) { 286 rr = rl->__runetype_ext.__ranges; 287 288#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN 289 rr[x].__min = ntohl(rr[x].__min); 290 rr[x].__max = ntohl(rr[x].__max); 291#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */ 292 if ((rr[x].__map = ntohl(rr[x].__map)) == 0) { 293 int len = rr[x].__max - rr[x].__min + 1; 294 rr[x].__types = rl->__variable; 295 rl->__variable = rr[x].__types + len; 296 if (rl->__variable > lastp) { 297 free(data); 298 errno = EFTYPE; 299 return (NULL); 300 } 301#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN 302 while (len-- > 0) 303 rr[x].__types[len] = ntohl(rr[x].__types[len]); 304#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */ 305 } else 306 rr[x].__types = 0; 307 } 308 309#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN 310 for (x = 0; x < rl->__maplower_ext.__nranges; ++x) { 311 rr = rl->__maplower_ext.__ranges; 312 313 rr[x].__min = ntohl(rr[x].__min); 314 rr[x].__max = ntohl(rr[x].__max); 315 rr[x].__map = ntohl(rr[x].__map); 316 } 317 318 for (x = 0; x < rl->__mapupper_ext.__nranges; ++x) { 319 rr = rl->__mapupper_ext.__ranges; 320 321 rr[x].__min = ntohl(rr[x].__min); 322 rr[x].__max = ntohl(rr[x].__max); 323 rr[x].__map = ntohl(rr[x].__map); 324 } 325#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */ 326 327 if (rl->__ncharclasses > 0) { 328 rl->__charclasses = (_RuneCharClass *)rl->__variable; 329 rl->__variable = (void *)(rl->__charclasses + rl->__ncharclasses); 330 if (rl->__variable > lastp) { 331 free(data); 332 errno = EFTYPE; 333 return (NULL); 334 } 335#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN 336 for (x = 0; x < rl->__ncharclasses; ++x) 337 rl->__charclasses[x].__mask = ntohl(rl->__charclasses[x].__mask); 338#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */ 339 } 340 341 if (((char *)rl->__variable) + rl->__variable_len > (char *)lastp) { 342 free(data); 343 errno = EFTYPE; 344 return (NULL); 345 } 346 347 /* 348 * Go out and zero pointers that should be zero. 349 */ 350 if (!rl->__variable_len) 351 rl->__variable = 0; 352 353 if (!rl->__runetype_ext.__nranges) 354 rl->__runetype_ext.__ranges = 0; 355 356 if (!rl->__maplower_ext.__nranges) 357 rl->__maplower_ext.__ranges = 0; 358 359 if (!rl->__mapupper_ext.__nranges) 360 rl->__mapupper_ext.__ranges = 0; 361 362 data->__datasize = lastp - (void *)data; 363 return (data); 364} 365#endif /* !RUNEOFF32 */ 366