xref: /csrg-svn/lib/libc/locale/rune.c (revision 61136)
160474Sbostic /*-
2*61136Sbostic  * Copyright (c) 1993
3*61136Sbostic  *	The Regents of the University of California.  All rights reserved.
460474Sbostic  *
560474Sbostic  * This code is derived from software contributed to Berkeley by
660474Sbostic  * Paul Borman at Krystal Technologies.
760474Sbostic  *
860474Sbostic  * %sccs.include.redist.c%
960474Sbostic  */
1060474Sbostic 
1160474Sbostic #if defined(LIBC_SCCS) && !defined(lint)
12*61136Sbostic static char sccsid[] = "@(#)rune.c	8.1 (Berkeley) 06/04/93";
1360474Sbostic #endif /* LIBC_SCCS and not lint */
1460474Sbostic 
1560474Sbostic #include <sys/types.h>
1660474Sbostic #include <sys/stat.h>
1760474Sbostic 
1860474Sbostic #include <ctype.h>
1960474Sbostic #include <errno.h>
2060474Sbostic #include <limits.h>
2160474Sbostic #include <rune.h>
2260474Sbostic #include <stdio.h>
2360474Sbostic #include <stdlib.h>
2460474Sbostic 
2560474Sbostic extern int		_none_init __P((_RuneLocale *));
2660474Sbostic extern int		_UTF2_init __P((_RuneLocale *));
2760474Sbostic extern int		_EUC_init __P((_RuneLocale *));
2860474Sbostic static _RuneLocale	*_Read_RuneMagi __P((FILE *));
2960474Sbostic 
3060474Sbostic static char *PathLocale = 0;
3160474Sbostic 
3260474Sbostic int
setrunelocale(encoding)3360474Sbostic setrunelocale(encoding)
3460474Sbostic 	char *encoding;
3560474Sbostic {
3660474Sbostic 	FILE *fp;
3760474Sbostic 	char name[PATH_MAX];
3860474Sbostic 	_RuneLocale *rl;
3960474Sbostic 
4060474Sbostic 	if (!encoding)
4160474Sbostic 	    return(EFAULT);
4260474Sbostic 
4360474Sbostic 	/*
4460474Sbostic 	 * The "C" and "POSIX" locale are always here.
4560474Sbostic 	 */
4660474Sbostic 	if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) {
4760474Sbostic 		_CurrentRuneLocale = &_DefaultRuneLocale;
4860474Sbostic 		return(0);
4960474Sbostic 	}
5060474Sbostic 
5160474Sbostic 	if (!PathLocale && !(PathLocale = getenv("PATH_LOCALE")))
5260474Sbostic 		PathLocale = _PATH_LOCALE;
5360474Sbostic 
5460474Sbostic 	sprintf(name, "%s/%s/LC_CTYPE", PathLocale, encoding);
5560474Sbostic 
5660474Sbostic 	if ((fp = fopen(name, "r")) == NULL)
5760474Sbostic 		return(ENOENT);
5860474Sbostic 
5960474Sbostic 	if ((rl = _Read_RuneMagi(fp)) == 0) {
6060474Sbostic 		fclose(fp);
6160474Sbostic 		return(EFTYPE);
6260474Sbostic 	}
6360474Sbostic 
6460474Sbostic 	if (!rl->encoding[0] || !strcmp(rl->encoding, "UTF2")) {
6560474Sbostic 		return(_UTF2_init(rl));
6660474Sbostic 	} else if (!strcmp(rl->encoding, "NONE")) {
6760474Sbostic 		return(_none_init(rl));
6860474Sbostic 	} else if (!strcmp(rl->encoding, "EUC")) {
6960474Sbostic 		return(_EUC_init(rl));
7060474Sbostic 	} else
7160474Sbostic 		return(EINVAL);
7260474Sbostic }
7360474Sbostic 
7460474Sbostic void
setinvalidrune(ir)7560474Sbostic setinvalidrune(ir)
7660474Sbostic 	rune_t ir;
7760474Sbostic {
7860474Sbostic 	_INVALID_RUNE = ir;
7960474Sbostic }
8060474Sbostic 
8160474Sbostic static _RuneLocale *
_Read_RuneMagi(fp)8260474Sbostic _Read_RuneMagi(fp)
8360474Sbostic 	FILE *fp;
8460474Sbostic {
8560474Sbostic 	char *data;
8660474Sbostic 	void *np;
8760474Sbostic 	void *lastp;
8860474Sbostic 	_RuneLocale *rl;
8960474Sbostic 	_RuneEntry *rr;
9060474Sbostic 	struct stat sb;
9160474Sbostic 	int x;
9260474Sbostic 
9360474Sbostic 	if (fstat(fileno(fp), &sb) < 0)
9460474Sbostic 		return(0);
9560474Sbostic 
9660474Sbostic 	if (sb.st_size < sizeof(_RuneLocale))
9760474Sbostic 		return(0);
9860474Sbostic 
9960474Sbostic 	if ((data = malloc(sb.st_size)) == NULL)
10060474Sbostic 		return(0);
10160474Sbostic 
10260474Sbostic 	rewind(fp); /* Someone might have read the magic number once already */
10360474Sbostic 
10460474Sbostic 	if (fread(data, sb.st_size, 1, fp) != 1) {
10560474Sbostic 		free(data);
10660474Sbostic 		return(0);
10760474Sbostic 	}
10860474Sbostic 
10960474Sbostic 	rl = (_RuneLocale *)data;
11060474Sbostic 	lastp = data + sb.st_size;
11160474Sbostic 
11260474Sbostic 	rl->variable = rl + 1;
11360474Sbostic 
11460474Sbostic 	if (memcmp(rl->magic, _RUNE_MAGIC_1, sizeof(rl->magic))) {
11560474Sbostic 		free(data);
11660474Sbostic 		return(0);
11760474Sbostic 	}
11860474Sbostic 
11960474Sbostic 	rl->invalid_rune = ntohl(rl->invalid_rune);
12060474Sbostic 	rl->variable_len = ntohl(rl->variable_len);
12160474Sbostic 	rl->runetype_ext.nranges = ntohl(rl->runetype_ext.nranges);
12260474Sbostic 	rl->maplower_ext.nranges = ntohl(rl->maplower_ext.nranges);
12360474Sbostic 	rl->mapupper_ext.nranges = ntohl(rl->mapupper_ext.nranges);
12460474Sbostic 
12560474Sbostic 	for (x = 0; x < _CACHED_RUNES; ++x) {
12660474Sbostic 		rl->runetype[x] = ntohl(rl->runetype[x]);
12760474Sbostic 		rl->maplower[x] = ntohl(rl->maplower[x]);
12860474Sbostic 		rl->mapupper[x] = ntohl(rl->mapupper[x]);
12960474Sbostic 	}
13060474Sbostic 
13160474Sbostic 	rl->runetype_ext.ranges = (_RuneEntry *)rl->variable;
13260474Sbostic 	rl->variable = rl->runetype_ext.ranges + rl->runetype_ext.nranges;
13360474Sbostic 	if (rl->variable > lastp) {
13460474Sbostic 		free(data);
13560474Sbostic 		return(0);
13660474Sbostic 	}
13760474Sbostic 
13860474Sbostic 	rl->maplower_ext.ranges = (_RuneEntry *)rl->variable;
13960474Sbostic 	rl->variable = rl->maplower_ext.ranges + rl->maplower_ext.nranges;
14060474Sbostic 	if (rl->variable > lastp) {
14160474Sbostic 		free(data);
14260474Sbostic 		return(0);
14360474Sbostic 	}
14460474Sbostic 
14560474Sbostic 	rl->mapupper_ext.ranges = (_RuneEntry *)rl->variable;
14660474Sbostic 	rl->variable = rl->mapupper_ext.ranges + rl->mapupper_ext.nranges;
14760474Sbostic 	if (rl->variable > lastp) {
14860474Sbostic 		free(data);
14960474Sbostic 		return(0);
15060474Sbostic 	}
15160474Sbostic 
15260474Sbostic 	for (x = 0; x < rl->runetype_ext.nranges; ++x) {
15360474Sbostic 		rr = rl->runetype_ext.ranges;
15460474Sbostic 
15560474Sbostic 		rr[x].min = ntohl(rr[x].min);
15660474Sbostic 		rr[x].max = ntohl(rr[x].max);
15760474Sbostic 		if ((rr[x].map = ntohl(rr[x].map)) == 0) {
15860474Sbostic 			int len = rr[x].max - rr[x].min + 1;
15960474Sbostic 			rr[x].types = rl->variable;
16060474Sbostic 			rl->variable = rr[x].types + len;
16160474Sbostic 			if (rl->variable > lastp) {
16260474Sbostic 				free(data);
16360474Sbostic 				return(0);
16460474Sbostic 			}
16560474Sbostic 			while (len-- > 0)
16660474Sbostic 				rr[x].types[len] = ntohl(rr[x].types[len]);
16760474Sbostic 		} else
16860474Sbostic 			rr[x].types = 0;
16960474Sbostic 	}
17060474Sbostic 
17160474Sbostic 	for (x = 0; x < rl->maplower_ext.nranges; ++x) {
17260474Sbostic 		rr = rl->maplower_ext.ranges;
17360474Sbostic 
17460474Sbostic 		rr[x].min = ntohl(rr[x].min);
17560474Sbostic 		rr[x].max = ntohl(rr[x].max);
17660474Sbostic 		rr[x].map = ntohl(rr[x].map);
17760474Sbostic 	}
17860474Sbostic 
17960474Sbostic 	for (x = 0; x < rl->mapupper_ext.nranges; ++x) {
18060474Sbostic 		rr = rl->mapupper_ext.ranges;
18160474Sbostic 
18260474Sbostic 		rr[x].min = ntohl(rr[x].min);
18360474Sbostic 		rr[x].max = ntohl(rr[x].max);
18460474Sbostic 		rr[x].map = ntohl(rr[x].map);
18560474Sbostic 	}
18660474Sbostic 	if (((char *)rl->variable) + rl->variable_len > (char *)lastp) {
18760474Sbostic 		free(data);
18860474Sbostic 		return(0);
18960474Sbostic 	}
19060474Sbostic 
19160474Sbostic 	/*
19260474Sbostic 	 * Go out and zero pointers that should be zero.
19360474Sbostic 	 */
19460474Sbostic 	if (!rl->variable_len)
19560474Sbostic 		rl->variable = 0;
19660474Sbostic 
19760474Sbostic 	if (!rl->runetype_ext.nranges)
19860474Sbostic 		rl->runetype_ext.ranges = 0;
19960474Sbostic 
20060474Sbostic 	if (!rl->maplower_ext.nranges)
20160474Sbostic 		rl->maplower_ext.ranges = 0;
20260474Sbostic 
20360474Sbostic 	if (!rl->mapupper_ext.nranges)
20460474Sbostic 		rl->mapupper_ext.ranges = 0;
20560474Sbostic 
20660474Sbostic 	return(rl);
20760474Sbostic }
20860474Sbostic 
20960474Sbostic unsigned long
___runetype(c)21060474Sbostic ___runetype(c)
21160474Sbostic 	_BSD_RUNE_T_ c;
21260474Sbostic {
21360474Sbostic 	int x;
21460474Sbostic 	_RuneRange *rr = &_CurrentRuneLocale->runetype_ext;
21560474Sbostic 	_RuneEntry *re = rr->ranges;
21660474Sbostic 
21760474Sbostic 	if (c == EOF)
21860474Sbostic 		return(0);
21960474Sbostic 	for (x = 0; x < rr->nranges; ++x, ++re) {
22060474Sbostic 		if (c < re->min)
22160474Sbostic 			return(0L);
22260474Sbostic 		if (c <= re->max) {
22360474Sbostic 			if (re->types)
22460474Sbostic 			    return(re->types[c - re->min]);
22560474Sbostic 			else
22660474Sbostic 			    return(re->map);
22760474Sbostic 		}
22860474Sbostic 	}
22960474Sbostic 	return(0L);
23060474Sbostic }
23160474Sbostic 
23260474Sbostic _BSD_RUNE_T_
___toupper(c)23360474Sbostic ___toupper(c)
23460474Sbostic 	_BSD_RUNE_T_ c;
23560474Sbostic {
23660474Sbostic 	int x;
23760474Sbostic 	_RuneRange *rr = &_CurrentRuneLocale->mapupper_ext;
23860474Sbostic 	_RuneEntry *re = rr->ranges;
23960474Sbostic 
24060474Sbostic 	if (c == EOF)
24160474Sbostic 		return(EOF);
24260474Sbostic 	for (x = 0; x < rr->nranges; ++x, ++re) {
24360474Sbostic 		if (c < re->min)
24460474Sbostic 			return(c);
24560474Sbostic 		if (c <= re->max)
24660474Sbostic 			return(re->map + c - re->min);
24760474Sbostic 	}
24860474Sbostic 	return(c);
24960474Sbostic }
25060474Sbostic 
25160474Sbostic _BSD_RUNE_T_
___tolower(c)25260474Sbostic ___tolower(c)
25360474Sbostic 	_BSD_RUNE_T_ c;
25460474Sbostic {
25560474Sbostic 	int x;
25660474Sbostic 	_RuneRange *rr = &_CurrentRuneLocale->maplower_ext;
25760474Sbostic 	_RuneEntry *re = rr->ranges;
25860474Sbostic 
25960474Sbostic 	if (c == EOF)
26060474Sbostic 		return(EOF);
26160474Sbostic 	for (x = 0; x < rr->nranges; ++x, ++re) {
26260474Sbostic 		if (c < re->min)
26360474Sbostic 			return(c);
26460474Sbostic 		if (c <= re->max)
26560474Sbostic 			return(re->map + c - re->min);
26660474Sbostic 	}
26760474Sbostic 	return(c);
26860474Sbostic }
26960474Sbostic 
27060474Sbostic 
27160474Sbostic #if !defined(_USE_CTYPE_INLINE_) && !defined(_USE_CTYPE_MACROS_)
27260474Sbostic /*
27360474Sbostic  * See comments in <machine/ansi.h>
27460474Sbostic  */
27560474Sbostic int
__istype(c,f)27660474Sbostic __istype(c, f)
27760474Sbostic 	_BSD_RUNE_T_ c;
27860474Sbostic 	unsigned long f;
27960474Sbostic {
28060474Sbostic 	return ((((c & _CRMASK) ? ___runetype(c)
28160474Sbostic            : _CurrentRuneLocale->runetype[c]) & f) ? 1 : 0);
28260474Sbostic }
28360474Sbostic 
28460474Sbostic int
28560474Sbostic __isctype(_BSD_RUNE_T_ c, unsigned long f)
28660474Sbostic 	_BSD_RUNE_T_ c;
28760474Sbostic 	unsigned long f;
28860474Sbostic {
28960474Sbostic 	return ((((c & _CRMASK) ? 0
29060474Sbostic            : _DefaultRuneLocale.runetype[c]) & f) ? 1 : 0);
29160474Sbostic }
29260474Sbostic 
29360474Sbostic _BSD_RUNE_T_
toupper(c)29460474Sbostic toupper(c)
29560474Sbostic 	_BSD_RUNE_T_ c;
29660474Sbostic {
29760474Sbostic 	return ((c & _CRMASK) ?
29860474Sbostic 	    ___toupper(c) : _CurrentRuneLocale->mapupper[c]);
29960474Sbostic }
30060474Sbostic 
30160474Sbostic _BSD_RUNE_T_
tolower(c)30260474Sbostic tolower(c)
30360474Sbostic 	_BSD_RUNE_T_ c;
30460474Sbostic {
30560474Sbostic 	return ((c & _CRMASK) ?
30660474Sbostic 	    ___tolower(c) : _CurrentRuneLocale->maplower[c]);
30760474Sbostic }
30860474Sbostic #endif
309