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