1*60474Sbostic /*- 2*60474Sbostic * Copyright (c) 1993 The Regents of the University of California. 3*60474Sbostic * All rights reserved. 4*60474Sbostic * 5*60474Sbostic * This code is derived from software contributed to Berkeley by 6*60474Sbostic * Paul Borman at Krystal Technologies. 7*60474Sbostic * 8*60474Sbostic * %sccs.include.redist.c% 9*60474Sbostic */ 10*60474Sbostic 11*60474Sbostic #if defined(LIBC_SCCS) && !defined(lint) 12*60474Sbostic static char sccsid[] = "@(#)rune.c 5.1 (Berkeley) 05/26/93"; 13*60474Sbostic #endif /* LIBC_SCCS and not lint */ 14*60474Sbostic 15*60474Sbostic #include <sys/types.h> 16*60474Sbostic #include <sys/stat.h> 17*60474Sbostic 18*60474Sbostic #include <ctype.h> 19*60474Sbostic #include <errno.h> 20*60474Sbostic #include <limits.h> 21*60474Sbostic #include <rune.h> 22*60474Sbostic #include <stdio.h> 23*60474Sbostic #include <stdlib.h> 24*60474Sbostic 25*60474Sbostic extern int _none_init __P((_RuneLocale *)); 26*60474Sbostic extern int _UTF2_init __P((_RuneLocale *)); 27*60474Sbostic extern int _EUC_init __P((_RuneLocale *)); 28*60474Sbostic static _RuneLocale *_Read_RuneMagi __P((FILE *)); 29*60474Sbostic 30*60474Sbostic static char *PathLocale = 0; 31*60474Sbostic 32*60474Sbostic int 33*60474Sbostic setrunelocale(encoding) 34*60474Sbostic char *encoding; 35*60474Sbostic { 36*60474Sbostic FILE *fp; 37*60474Sbostic char name[PATH_MAX]; 38*60474Sbostic _RuneLocale *rl; 39*60474Sbostic 40*60474Sbostic if (!encoding) 41*60474Sbostic return(EFAULT); 42*60474Sbostic 43*60474Sbostic /* 44*60474Sbostic * The "C" and "POSIX" locale are always here. 45*60474Sbostic */ 46*60474Sbostic if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) { 47*60474Sbostic _CurrentRuneLocale = &_DefaultRuneLocale; 48*60474Sbostic return(0); 49*60474Sbostic } 50*60474Sbostic 51*60474Sbostic if (!PathLocale && !(PathLocale = getenv("PATH_LOCALE"))) 52*60474Sbostic PathLocale = _PATH_LOCALE; 53*60474Sbostic 54*60474Sbostic sprintf(name, "%s/%s/LC_CTYPE", PathLocale, encoding); 55*60474Sbostic 56*60474Sbostic if ((fp = fopen(name, "r")) == NULL) 57*60474Sbostic return(ENOENT); 58*60474Sbostic 59*60474Sbostic if ((rl = _Read_RuneMagi(fp)) == 0) { 60*60474Sbostic fclose(fp); 61*60474Sbostic return(EFTYPE); 62*60474Sbostic } 63*60474Sbostic 64*60474Sbostic if (!rl->encoding[0] || !strcmp(rl->encoding, "UTF2")) { 65*60474Sbostic return(_UTF2_init(rl)); 66*60474Sbostic } else if (!strcmp(rl->encoding, "NONE")) { 67*60474Sbostic return(_none_init(rl)); 68*60474Sbostic } else if (!strcmp(rl->encoding, "EUC")) { 69*60474Sbostic return(_EUC_init(rl)); 70*60474Sbostic } else 71*60474Sbostic return(EINVAL); 72*60474Sbostic } 73*60474Sbostic 74*60474Sbostic void 75*60474Sbostic setinvalidrune(ir) 76*60474Sbostic rune_t ir; 77*60474Sbostic { 78*60474Sbostic _INVALID_RUNE = ir; 79*60474Sbostic } 80*60474Sbostic 81*60474Sbostic static _RuneLocale * 82*60474Sbostic _Read_RuneMagi(fp) 83*60474Sbostic FILE *fp; 84*60474Sbostic { 85*60474Sbostic char *data; 86*60474Sbostic void *np; 87*60474Sbostic void *lastp; 88*60474Sbostic _RuneLocale *rl; 89*60474Sbostic _RuneEntry *rr; 90*60474Sbostic struct stat sb; 91*60474Sbostic int x; 92*60474Sbostic 93*60474Sbostic if (fstat(fileno(fp), &sb) < 0) 94*60474Sbostic return(0); 95*60474Sbostic 96*60474Sbostic if (sb.st_size < sizeof(_RuneLocale)) 97*60474Sbostic return(0); 98*60474Sbostic 99*60474Sbostic if ((data = malloc(sb.st_size)) == NULL) 100*60474Sbostic return(0); 101*60474Sbostic 102*60474Sbostic rewind(fp); /* Someone might have read the magic number once already */ 103*60474Sbostic 104*60474Sbostic if (fread(data, sb.st_size, 1, fp) != 1) { 105*60474Sbostic free(data); 106*60474Sbostic return(0); 107*60474Sbostic } 108*60474Sbostic 109*60474Sbostic rl = (_RuneLocale *)data; 110*60474Sbostic lastp = data + sb.st_size; 111*60474Sbostic 112*60474Sbostic rl->variable = rl + 1; 113*60474Sbostic 114*60474Sbostic if (memcmp(rl->magic, _RUNE_MAGIC_1, sizeof(rl->magic))) { 115*60474Sbostic free(data); 116*60474Sbostic return(0); 117*60474Sbostic } 118*60474Sbostic 119*60474Sbostic rl->invalid_rune = ntohl(rl->invalid_rune); 120*60474Sbostic rl->variable_len = ntohl(rl->variable_len); 121*60474Sbostic rl->runetype_ext.nranges = ntohl(rl->runetype_ext.nranges); 122*60474Sbostic rl->maplower_ext.nranges = ntohl(rl->maplower_ext.nranges); 123*60474Sbostic rl->mapupper_ext.nranges = ntohl(rl->mapupper_ext.nranges); 124*60474Sbostic 125*60474Sbostic for (x = 0; x < _CACHED_RUNES; ++x) { 126*60474Sbostic rl->runetype[x] = ntohl(rl->runetype[x]); 127*60474Sbostic rl->maplower[x] = ntohl(rl->maplower[x]); 128*60474Sbostic rl->mapupper[x] = ntohl(rl->mapupper[x]); 129*60474Sbostic } 130*60474Sbostic 131*60474Sbostic rl->runetype_ext.ranges = (_RuneEntry *)rl->variable; 132*60474Sbostic rl->variable = rl->runetype_ext.ranges + rl->runetype_ext.nranges; 133*60474Sbostic if (rl->variable > lastp) { 134*60474Sbostic free(data); 135*60474Sbostic return(0); 136*60474Sbostic } 137*60474Sbostic 138*60474Sbostic rl->maplower_ext.ranges = (_RuneEntry *)rl->variable; 139*60474Sbostic rl->variable = rl->maplower_ext.ranges + rl->maplower_ext.nranges; 140*60474Sbostic if (rl->variable > lastp) { 141*60474Sbostic free(data); 142*60474Sbostic return(0); 143*60474Sbostic } 144*60474Sbostic 145*60474Sbostic rl->mapupper_ext.ranges = (_RuneEntry *)rl->variable; 146*60474Sbostic rl->variable = rl->mapupper_ext.ranges + rl->mapupper_ext.nranges; 147*60474Sbostic if (rl->variable > lastp) { 148*60474Sbostic free(data); 149*60474Sbostic return(0); 150*60474Sbostic } 151*60474Sbostic 152*60474Sbostic for (x = 0; x < rl->runetype_ext.nranges; ++x) { 153*60474Sbostic rr = rl->runetype_ext.ranges; 154*60474Sbostic 155*60474Sbostic rr[x].min = ntohl(rr[x].min); 156*60474Sbostic rr[x].max = ntohl(rr[x].max); 157*60474Sbostic if ((rr[x].map = ntohl(rr[x].map)) == 0) { 158*60474Sbostic int len = rr[x].max - rr[x].min + 1; 159*60474Sbostic rr[x].types = rl->variable; 160*60474Sbostic rl->variable = rr[x].types + len; 161*60474Sbostic if (rl->variable > lastp) { 162*60474Sbostic free(data); 163*60474Sbostic return(0); 164*60474Sbostic } 165*60474Sbostic while (len-- > 0) 166*60474Sbostic rr[x].types[len] = ntohl(rr[x].types[len]); 167*60474Sbostic } else 168*60474Sbostic rr[x].types = 0; 169*60474Sbostic } 170*60474Sbostic 171*60474Sbostic for (x = 0; x < rl->maplower_ext.nranges; ++x) { 172*60474Sbostic rr = rl->maplower_ext.ranges; 173*60474Sbostic 174*60474Sbostic rr[x].min = ntohl(rr[x].min); 175*60474Sbostic rr[x].max = ntohl(rr[x].max); 176*60474Sbostic rr[x].map = ntohl(rr[x].map); 177*60474Sbostic } 178*60474Sbostic 179*60474Sbostic for (x = 0; x < rl->mapupper_ext.nranges; ++x) { 180*60474Sbostic rr = rl->mapupper_ext.ranges; 181*60474Sbostic 182*60474Sbostic rr[x].min = ntohl(rr[x].min); 183*60474Sbostic rr[x].max = ntohl(rr[x].max); 184*60474Sbostic rr[x].map = ntohl(rr[x].map); 185*60474Sbostic } 186*60474Sbostic if (((char *)rl->variable) + rl->variable_len > (char *)lastp) { 187*60474Sbostic free(data); 188*60474Sbostic return(0); 189*60474Sbostic } 190*60474Sbostic 191*60474Sbostic /* 192*60474Sbostic * Go out and zero pointers that should be zero. 193*60474Sbostic */ 194*60474Sbostic if (!rl->variable_len) 195*60474Sbostic rl->variable = 0; 196*60474Sbostic 197*60474Sbostic if (!rl->runetype_ext.nranges) 198*60474Sbostic rl->runetype_ext.ranges = 0; 199*60474Sbostic 200*60474Sbostic if (!rl->maplower_ext.nranges) 201*60474Sbostic rl->maplower_ext.ranges = 0; 202*60474Sbostic 203*60474Sbostic if (!rl->mapupper_ext.nranges) 204*60474Sbostic rl->mapupper_ext.ranges = 0; 205*60474Sbostic 206*60474Sbostic return(rl); 207*60474Sbostic } 208*60474Sbostic 209*60474Sbostic unsigned long 210*60474Sbostic ___runetype(c) 211*60474Sbostic _BSD_RUNE_T_ c; 212*60474Sbostic { 213*60474Sbostic int x; 214*60474Sbostic _RuneRange *rr = &_CurrentRuneLocale->runetype_ext; 215*60474Sbostic _RuneEntry *re = rr->ranges; 216*60474Sbostic 217*60474Sbostic if (c == EOF) 218*60474Sbostic return(0); 219*60474Sbostic for (x = 0; x < rr->nranges; ++x, ++re) { 220*60474Sbostic if (c < re->min) 221*60474Sbostic return(0L); 222*60474Sbostic if (c <= re->max) { 223*60474Sbostic if (re->types) 224*60474Sbostic return(re->types[c - re->min]); 225*60474Sbostic else 226*60474Sbostic return(re->map); 227*60474Sbostic } 228*60474Sbostic } 229*60474Sbostic return(0L); 230*60474Sbostic } 231*60474Sbostic 232*60474Sbostic _BSD_RUNE_T_ 233*60474Sbostic ___toupper(c) 234*60474Sbostic _BSD_RUNE_T_ c; 235*60474Sbostic { 236*60474Sbostic int x; 237*60474Sbostic _RuneRange *rr = &_CurrentRuneLocale->mapupper_ext; 238*60474Sbostic _RuneEntry *re = rr->ranges; 239*60474Sbostic 240*60474Sbostic if (c == EOF) 241*60474Sbostic return(EOF); 242*60474Sbostic for (x = 0; x < rr->nranges; ++x, ++re) { 243*60474Sbostic if (c < re->min) 244*60474Sbostic return(c); 245*60474Sbostic if (c <= re->max) 246*60474Sbostic return(re->map + c - re->min); 247*60474Sbostic } 248*60474Sbostic return(c); 249*60474Sbostic } 250*60474Sbostic 251*60474Sbostic _BSD_RUNE_T_ 252*60474Sbostic ___tolower(c) 253*60474Sbostic _BSD_RUNE_T_ c; 254*60474Sbostic { 255*60474Sbostic int x; 256*60474Sbostic _RuneRange *rr = &_CurrentRuneLocale->maplower_ext; 257*60474Sbostic _RuneEntry *re = rr->ranges; 258*60474Sbostic 259*60474Sbostic if (c == EOF) 260*60474Sbostic return(EOF); 261*60474Sbostic for (x = 0; x < rr->nranges; ++x, ++re) { 262*60474Sbostic if (c < re->min) 263*60474Sbostic return(c); 264*60474Sbostic if (c <= re->max) 265*60474Sbostic return(re->map + c - re->min); 266*60474Sbostic } 267*60474Sbostic return(c); 268*60474Sbostic } 269*60474Sbostic 270*60474Sbostic 271*60474Sbostic #if !defined(_USE_CTYPE_INLINE_) && !defined(_USE_CTYPE_MACROS_) 272*60474Sbostic /* 273*60474Sbostic * See comments in <machine/ansi.h> 274*60474Sbostic */ 275*60474Sbostic int 276*60474Sbostic __istype(c, f) 277*60474Sbostic _BSD_RUNE_T_ c; 278*60474Sbostic unsigned long f; 279*60474Sbostic { 280*60474Sbostic return ((((c & _CRMASK) ? ___runetype(c) 281*60474Sbostic : _CurrentRuneLocale->runetype[c]) & f) ? 1 : 0); 282*60474Sbostic } 283*60474Sbostic 284*60474Sbostic int 285*60474Sbostic __isctype(_BSD_RUNE_T_ c, unsigned long f) 286*60474Sbostic _BSD_RUNE_T_ c; 287*60474Sbostic unsigned long f; 288*60474Sbostic { 289*60474Sbostic return ((((c & _CRMASK) ? 0 290*60474Sbostic : _DefaultRuneLocale.runetype[c]) & f) ? 1 : 0); 291*60474Sbostic } 292*60474Sbostic 293*60474Sbostic _BSD_RUNE_T_ 294*60474Sbostic toupper(c) 295*60474Sbostic _BSD_RUNE_T_ c; 296*60474Sbostic { 297*60474Sbostic return ((c & _CRMASK) ? 298*60474Sbostic ___toupper(c) : _CurrentRuneLocale->mapupper[c]); 299*60474Sbostic } 300*60474Sbostic 301*60474Sbostic _BSD_RUNE_T_ 302*60474Sbostic tolower(c) 303*60474Sbostic _BSD_RUNE_T_ c; 304*60474Sbostic { 305*60474Sbostic return ((c & _CRMASK) ? 306*60474Sbostic ___tolower(c) : _CurrentRuneLocale->maplower[c]); 307*60474Sbostic } 308*60474Sbostic #endif 309