xref: /freebsd/lib/libc/locale/rune.c (revision 228f8c4f8b8728dbd5ba4621e74fa8576d64e869)
158f0484fSRodney W. Grimes /*-
258f0484fSRodney W. Grimes  * Copyright (c) 1993
358f0484fSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
458f0484fSRodney W. Grimes  *
558f0484fSRodney W. Grimes  * This code is derived from software contributed to Berkeley by
658f0484fSRodney W. Grimes  * Paul Borman at Krystal Technologies.
758f0484fSRodney W. Grimes  *
858f0484fSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
958f0484fSRodney W. Grimes  * modification, are permitted provided that the following conditions
1058f0484fSRodney W. Grimes  * are met:
1158f0484fSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
1258f0484fSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
1358f0484fSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
1458f0484fSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
1558f0484fSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
1658f0484fSRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
1758f0484fSRodney W. Grimes  *    must display the following acknowledgement:
1858f0484fSRodney W. Grimes  *	This product includes software developed by the University of
1958f0484fSRodney W. Grimes  *	California, Berkeley and its contributors.
2058f0484fSRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
2158f0484fSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
2258f0484fSRodney W. Grimes  *    without specific prior written permission.
2358f0484fSRodney W. Grimes  *
2458f0484fSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2558f0484fSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2658f0484fSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2758f0484fSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2858f0484fSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2958f0484fSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3058f0484fSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3158f0484fSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3258f0484fSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3358f0484fSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3458f0484fSRodney W. Grimes  * SUCH DAMAGE.
3558f0484fSRodney W. Grimes  */
3658f0484fSRodney W. Grimes 
3758f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint)
3858f0484fSRodney W. Grimes static char sccsid[] = "@(#)rune.c	8.1 (Berkeley) 6/4/93";
3958f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */
40333fc21eSDavid E. O'Brien #include <sys/cdefs.h>
41333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$");
4258f0484fSRodney W. Grimes 
43d201fe46SDaniel Eischen #include "namespace.h"
44fd8e4ebcSMike Barcroft #include <arpa/inet.h>
4576692b80SAndrey A. Chernov #include <errno.h>
46a0998ce6STim J. Robbins #include <runetype.h>
4758f0484fSRodney W. Grimes #include <stdio.h>
48350a3d3eSAndrey A. Chernov #include <string.h>
4958f0484fSRodney W. Grimes #include <stdlib.h>
50350a3d3eSAndrey A. Chernov #include <sys/types.h>
51350a3d3eSAndrey A. Chernov #include <sys/stat.h>
52d201fe46SDaniel Eischen #include "un-namespace.h"
5358f0484fSRodney W. Grimes 
54228f8c4fSRuslan Ermilov #include "runefile.h"
55228f8c4fSRuslan Ermilov 
563fb3a430SRuslan Ermilov _RuneLocale *_Read_RuneMagi(FILE *);
573fb3a430SRuslan Ermilov 
58350a3d3eSAndrey A. Chernov _RuneLocale *
593fb3a430SRuslan Ermilov _Read_RuneMagi(FILE *fp)
60350a3d3eSAndrey A. Chernov {
613fb3a430SRuslan Ermilov 	char *fdata, *data;
62350a3d3eSAndrey A. Chernov 	void *lastp;
633fb3a430SRuslan Ermilov 	_FileRuneLocale *frl;
64350a3d3eSAndrey A. Chernov 	_RuneLocale *rl;
653fb3a430SRuslan Ermilov 	_FileRuneEntry *frr;
66350a3d3eSAndrey A. Chernov 	_RuneEntry *rr;
67350a3d3eSAndrey A. Chernov 	struct stat sb;
6876692b80SAndrey A. Chernov 	int x, saverr;
693fb3a430SRuslan Ermilov 	void *variable;
703fb3a430SRuslan Ermilov 	_FileRuneEntry *runetype_ext_ranges;
713fb3a430SRuslan Ermilov 	_FileRuneEntry *maplower_ext_ranges;
723fb3a430SRuslan Ermilov 	_FileRuneEntry *mapupper_ext_ranges;
733fb3a430SRuslan Ermilov 	int runetype_ext_len = 0;
74350a3d3eSAndrey A. Chernov 
75d201fe46SDaniel Eischen 	if (_fstat(fileno(fp), &sb) < 0)
7676692b80SAndrey A. Chernov 		return (NULL);
77350a3d3eSAndrey A. Chernov 
783fb3a430SRuslan Ermilov 	if ((size_t)sb.st_size < sizeof(_FileRuneLocale)) {
7976692b80SAndrey A. Chernov 		errno = EFTYPE;
8076692b80SAndrey A. Chernov 		return (NULL);
8176692b80SAndrey A. Chernov 	}
82350a3d3eSAndrey A. Chernov 
833fb3a430SRuslan Ermilov 	if ((fdata = malloc(sb.st_size)) == NULL)
8476692b80SAndrey A. Chernov 		return (NULL);
85350a3d3eSAndrey A. Chernov 
8676692b80SAndrey A. Chernov 	errno = 0;
87350a3d3eSAndrey A. Chernov 	rewind(fp); /* Someone might have read the magic number once already */
8876692b80SAndrey A. Chernov 	if (errno) {
8976692b80SAndrey A. Chernov 		saverr = errno;
903fb3a430SRuslan Ermilov 		free(fdata);
9176692b80SAndrey A. Chernov 		errno = saverr;
9276692b80SAndrey A. Chernov 		return (NULL);
9376692b80SAndrey A. Chernov 	}
94350a3d3eSAndrey A. Chernov 
953fb3a430SRuslan Ermilov 	if (fread(fdata, sb.st_size, 1, fp) != 1) {
9676692b80SAndrey A. Chernov 		saverr = errno;
973fb3a430SRuslan Ermilov 		free(fdata);
9876692b80SAndrey A. Chernov 		errno = saverr;
9976692b80SAndrey A. Chernov 		return (NULL);
100350a3d3eSAndrey A. Chernov 	}
101350a3d3eSAndrey A. Chernov 
1023fb3a430SRuslan Ermilov 	frl = (_FileRuneLocale *)fdata;
1033fb3a430SRuslan Ermilov 	lastp = fdata + sb.st_size;
104350a3d3eSAndrey A. Chernov 
1053fb3a430SRuslan Ermilov 	variable = frl + 1;
106350a3d3eSAndrey A. Chernov 
1073fb3a430SRuslan Ermilov 	if (memcmp(frl->magic, _FILE_RUNE_MAGIC_1, sizeof(frl->magic))) {
1083fb3a430SRuslan Ermilov 		free(fdata);
10976692b80SAndrey A. Chernov 		errno = EFTYPE;
11076692b80SAndrey A. Chernov 		return (NULL);
111350a3d3eSAndrey A. Chernov 	}
112350a3d3eSAndrey A. Chernov 
1133fb3a430SRuslan Ermilov 	frl->variable_len = ntohl(frl->variable_len);
1143fb3a430SRuslan Ermilov 	frl->runetype_ext_nranges = ntohl(frl->runetype_ext_nranges);
1153fb3a430SRuslan Ermilov 	frl->maplower_ext_nranges = ntohl(frl->maplower_ext_nranges);
1163fb3a430SRuslan Ermilov 	frl->mapupper_ext_nranges = ntohl(frl->mapupper_ext_nranges);
117350a3d3eSAndrey A. Chernov 
118350a3d3eSAndrey A. Chernov 	for (x = 0; x < _CACHED_RUNES; ++x) {
1193fb3a430SRuslan Ermilov 		frl->runetype[x] = ntohl(frl->runetype[x]);
1203fb3a430SRuslan Ermilov 		frl->maplower[x] = ntohl(frl->maplower[x]);
1213fb3a430SRuslan Ermilov 		frl->mapupper[x] = ntohl(frl->mapupper[x]);
122350a3d3eSAndrey A. Chernov 	}
123350a3d3eSAndrey A. Chernov 
1243fb3a430SRuslan Ermilov 	runetype_ext_ranges = (_FileRuneEntry *)variable;
1253fb3a430SRuslan Ermilov 	variable = runetype_ext_ranges + frl->runetype_ext_nranges;
1263fb3a430SRuslan Ermilov 	if (variable > lastp) {
1273fb3a430SRuslan Ermilov 		free(fdata);
12876692b80SAndrey A. Chernov 		errno = EFTYPE;
12976692b80SAndrey A. Chernov 		return (NULL);
130350a3d3eSAndrey A. Chernov 	}
131350a3d3eSAndrey A. Chernov 
1323fb3a430SRuslan Ermilov 	maplower_ext_ranges = (_FileRuneEntry *)variable;
1333fb3a430SRuslan Ermilov 	variable = maplower_ext_ranges + frl->maplower_ext_nranges;
1343fb3a430SRuslan Ermilov 	if (variable > lastp) {
1353fb3a430SRuslan Ermilov 		free(fdata);
13676692b80SAndrey A. Chernov 		errno = EFTYPE;
13776692b80SAndrey A. Chernov 		return (NULL);
138350a3d3eSAndrey A. Chernov 	}
139350a3d3eSAndrey A. Chernov 
1403fb3a430SRuslan Ermilov 	mapupper_ext_ranges = (_FileRuneEntry *)variable;
1413fb3a430SRuslan Ermilov 	variable = mapupper_ext_ranges + frl->mapupper_ext_nranges;
1423fb3a430SRuslan Ermilov 	if (variable > lastp) {
1433fb3a430SRuslan Ermilov 		free(fdata);
14476692b80SAndrey A. Chernov 		errno = EFTYPE;
14576692b80SAndrey A. Chernov 		return (NULL);
146350a3d3eSAndrey A. Chernov 	}
147350a3d3eSAndrey A. Chernov 
1483fb3a430SRuslan Ermilov 	frr = runetype_ext_ranges;
1493fb3a430SRuslan Ermilov 	for (x = 0; x < frl->runetype_ext_nranges; ++x) {
1503fb3a430SRuslan Ermilov 		uint32_t *types;
151350a3d3eSAndrey A. Chernov 
1523fb3a430SRuslan Ermilov 		frr[x].min = ntohl(frr[x].min);
1533fb3a430SRuslan Ermilov 		frr[x].max = ntohl(frr[x].max);
1543fb3a430SRuslan Ermilov 		frr[x].map = ntohl(frr[x].map);
1553fb3a430SRuslan Ermilov 		if (frr[x].map == 0) {
1563fb3a430SRuslan Ermilov 			int len = frr[x].max - frr[x].min + 1;
1573fb3a430SRuslan Ermilov 			types = variable;
1583fb3a430SRuslan Ermilov 			variable = types + len;
1593fb3a430SRuslan Ermilov 			runetype_ext_len += len;
1603fb3a430SRuslan Ermilov 			if (variable > lastp) {
1613fb3a430SRuslan Ermilov 				free(fdata);
16276692b80SAndrey A. Chernov 				errno = EFTYPE;
16376692b80SAndrey A. Chernov 				return (NULL);
164350a3d3eSAndrey A. Chernov 			}
165350a3d3eSAndrey A. Chernov 			while (len-- > 0)
1663fb3a430SRuslan Ermilov 				types[len] = ntohl(types[len]);
1673fb3a430SRuslan Ermilov 		}
168350a3d3eSAndrey A. Chernov 	}
169350a3d3eSAndrey A. Chernov 
1703fb3a430SRuslan Ermilov 	frr = maplower_ext_ranges;
1713fb3a430SRuslan Ermilov 	for (x = 0; x < frl->maplower_ext_nranges; ++x) {
1723fb3a430SRuslan Ermilov 		frr[x].min = ntohl(frr[x].min);
1733fb3a430SRuslan Ermilov 		frr[x].max = ntohl(frr[x].max);
1743fb3a430SRuslan Ermilov 		frr[x].map = ntohl(frr[x].map);
175350a3d3eSAndrey A. Chernov 	}
176350a3d3eSAndrey A. Chernov 
1773fb3a430SRuslan Ermilov 	frr = mapupper_ext_ranges;
1783fb3a430SRuslan Ermilov 	for (x = 0; x < frl->mapupper_ext_nranges; ++x) {
1793fb3a430SRuslan Ermilov 		frr[x].min = ntohl(frr[x].min);
1803fb3a430SRuslan Ermilov 		frr[x].max = ntohl(frr[x].max);
1813fb3a430SRuslan Ermilov 		frr[x].map = ntohl(frr[x].map);
182350a3d3eSAndrey A. Chernov 	}
1833fb3a430SRuslan Ermilov 	if ((char *)variable + frl->variable_len > (char *)lastp) {
1843fb3a430SRuslan Ermilov 		free(fdata);
18576692b80SAndrey A. Chernov 		errno = EFTYPE;
18676692b80SAndrey A. Chernov 		return (NULL);
187350a3d3eSAndrey A. Chernov 	}
188350a3d3eSAndrey A. Chernov 
189350a3d3eSAndrey A. Chernov 	/*
1903fb3a430SRuslan Ermilov 	 * Convert from disk format to host format.
1913fb3a430SRuslan Ermilov 	 */
1923fb3a430SRuslan Ermilov 	data = malloc(sizeof(_RuneLocale) +
1933fb3a430SRuslan Ermilov 	    (frl->runetype_ext_nranges + frl->maplower_ext_nranges +
1943fb3a430SRuslan Ermilov 	    frl->mapupper_ext_nranges) * sizeof(_RuneEntry) +
1953fb3a430SRuslan Ermilov 	    runetype_ext_len * sizeof(*rr->__types) +
1963fb3a430SRuslan Ermilov 	    frl->variable_len);
1973fb3a430SRuslan Ermilov 	if (data == NULL) {
1983fb3a430SRuslan Ermilov 		saverr = errno;
1993fb3a430SRuslan Ermilov 		free(fdata);
2003fb3a430SRuslan Ermilov 		errno = saverr;
2013fb3a430SRuslan Ermilov 		return (NULL);
2023fb3a430SRuslan Ermilov 	}
2033fb3a430SRuslan Ermilov 
2043fb3a430SRuslan Ermilov 	rl = (_RuneLocale *)data;
2053fb3a430SRuslan Ermilov 	rl->__variable = rl + 1;
2063fb3a430SRuslan Ermilov 
2073fb3a430SRuslan Ermilov 	memcpy(rl->__magic, _RUNE_MAGIC_1, sizeof(rl->__magic));
2083fb3a430SRuslan Ermilov 	memcpy(rl->__encoding, frl->encoding, sizeof(rl->__encoding));
2093fb3a430SRuslan Ermilov 	rl->__invalid_rune = 0;
2103fb3a430SRuslan Ermilov 
2113fb3a430SRuslan Ermilov 	rl->__variable_len = frl->variable_len;
2123fb3a430SRuslan Ermilov 	rl->__runetype_ext.__nranges = frl->runetype_ext_nranges;
2133fb3a430SRuslan Ermilov 	rl->__maplower_ext.__nranges = frl->maplower_ext_nranges;
2143fb3a430SRuslan Ermilov 	rl->__mapupper_ext.__nranges = frl->mapupper_ext_nranges;
2153fb3a430SRuslan Ermilov 
2163fb3a430SRuslan Ermilov 	for (x = 0; x < _CACHED_RUNES; ++x) {
2173fb3a430SRuslan Ermilov 		rl->__runetype[x] = frl->runetype[x];
2183fb3a430SRuslan Ermilov 		rl->__maplower[x] = frl->maplower[x];
2193fb3a430SRuslan Ermilov 		rl->__mapupper[x] = frl->mapupper[x];
2203fb3a430SRuslan Ermilov 	}
2213fb3a430SRuslan Ermilov 
2223fb3a430SRuslan Ermilov 	rl->__runetype_ext.__ranges = (_RuneEntry *)rl->__variable;
2233fb3a430SRuslan Ermilov 	rl->__variable = rl->__runetype_ext.__ranges +
2243fb3a430SRuslan Ermilov 	    rl->__runetype_ext.__nranges;
2253fb3a430SRuslan Ermilov 
2263fb3a430SRuslan Ermilov 	rl->__maplower_ext.__ranges = (_RuneEntry *)rl->__variable;
2273fb3a430SRuslan Ermilov 	rl->__variable = rl->__maplower_ext.__ranges +
2283fb3a430SRuslan Ermilov 	    rl->__maplower_ext.__nranges;
2293fb3a430SRuslan Ermilov 
2303fb3a430SRuslan Ermilov 	rl->__mapupper_ext.__ranges = (_RuneEntry *)rl->__variable;
2313fb3a430SRuslan Ermilov 	rl->__variable = rl->__mapupper_ext.__ranges +
2323fb3a430SRuslan Ermilov 	    rl->__mapupper_ext.__nranges;
2333fb3a430SRuslan Ermilov 
2343fb3a430SRuslan Ermilov 	variable = mapupper_ext_ranges + frl->mapupper_ext_nranges;
2353fb3a430SRuslan Ermilov 	frr = runetype_ext_ranges;
2363fb3a430SRuslan Ermilov 	rr = rl->__runetype_ext.__ranges;
2373fb3a430SRuslan Ermilov 	for (x = 0; x < rl->__runetype_ext.__nranges; ++x) {
2383fb3a430SRuslan Ermilov 		uint32_t *types;
2393fb3a430SRuslan Ermilov 
2403fb3a430SRuslan Ermilov 		rr[x].__min = frr[x].min;
2413fb3a430SRuslan Ermilov 		rr[x].__max = frr[x].max;
2423fb3a430SRuslan Ermilov 		rr[x].__map = frr[x].map;
2433fb3a430SRuslan Ermilov 		if (rr[x].__map == 0) {
2443fb3a430SRuslan Ermilov 			int len = rr[x].__max - rr[x].__min + 1;
2453fb3a430SRuslan Ermilov 			types = variable;
2463fb3a430SRuslan Ermilov 			variable = types + len;
2473fb3a430SRuslan Ermilov 			rr[x].__types = rl->__variable;
2483fb3a430SRuslan Ermilov 			rl->__variable = rr[x].__types + len;
2493fb3a430SRuslan Ermilov 			while (len-- > 0)
2503fb3a430SRuslan Ermilov 				rr[x].__types[len] = types[len];
2513fb3a430SRuslan Ermilov 		} else
2523fb3a430SRuslan Ermilov 			rr[x].__types = NULL;
2533fb3a430SRuslan Ermilov 	}
2543fb3a430SRuslan Ermilov 
2553fb3a430SRuslan Ermilov 	frr = maplower_ext_ranges;
2563fb3a430SRuslan Ermilov 	rr = rl->__maplower_ext.__ranges;
2573fb3a430SRuslan Ermilov 	for (x = 0; x < rl->__maplower_ext.__nranges; ++x) {
2583fb3a430SRuslan Ermilov 		rr[x].__min = frr[x].min;
2593fb3a430SRuslan Ermilov 		rr[x].__max = frr[x].max;
2603fb3a430SRuslan Ermilov 		rr[x].__map = frr[x].map;
2613fb3a430SRuslan Ermilov 	}
2623fb3a430SRuslan Ermilov 
2633fb3a430SRuslan Ermilov 	frr = mapupper_ext_ranges;
2643fb3a430SRuslan Ermilov 	rr = rl->__mapupper_ext.__ranges;
2653fb3a430SRuslan Ermilov 	for (x = 0; x < rl->__mapupper_ext.__nranges; ++x) {
2663fb3a430SRuslan Ermilov 		rr[x].__min = frr[x].min;
2673fb3a430SRuslan Ermilov 		rr[x].__max = frr[x].max;
2683fb3a430SRuslan Ermilov 		rr[x].__map = frr[x].map;
2693fb3a430SRuslan Ermilov 	}
2703fb3a430SRuslan Ermilov 
2713fb3a430SRuslan Ermilov 	memcpy(rl->__variable, variable, rl->__variable_len);
2723fb3a430SRuslan Ermilov 	free(fdata);
2733fb3a430SRuslan Ermilov 
2743fb3a430SRuslan Ermilov 	/*
275350a3d3eSAndrey A. Chernov 	 * Go out and zero pointers that should be zero.
276350a3d3eSAndrey A. Chernov 	 */
277ddc1ededSTim J. Robbins 	if (!rl->__variable_len)
2783fb3a430SRuslan Ermilov 		rl->__variable = NULL;
279350a3d3eSAndrey A. Chernov 
280ddc1ededSTim J. Robbins 	if (!rl->__runetype_ext.__nranges)
2813fb3a430SRuslan Ermilov 		rl->__runetype_ext.__ranges = NULL;
282350a3d3eSAndrey A. Chernov 
283ddc1ededSTim J. Robbins 	if (!rl->__maplower_ext.__nranges)
2843fb3a430SRuslan Ermilov 		rl->__maplower_ext.__ranges = NULL;
285350a3d3eSAndrey A. Chernov 
286ddc1ededSTim J. Robbins 	if (!rl->__mapupper_ext.__nranges)
2873fb3a430SRuslan Ermilov 		rl->__mapupper_ext.__ranges = NULL;
288350a3d3eSAndrey A. Chernov 
289350a3d3eSAndrey A. Chernov 	return (rl);
290350a3d3eSAndrey A. Chernov }
291