14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1985-2009 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #pragma prototyped 234887Schin 244887Schin /* 254887Schin * locale state implementation 264887Schin */ 274887Schin 284887Schin #include "lclib.h" 298462SApril.Chin@Sun.COM #include "lclang.h" 304887Schin 314887Schin #include <ctype.h> 324887Schin 334887Schin static Lc_numeric_t default_numeric = { '.', -1 }; 344887Schin 354887Schin static Lc_t default_lc = 364887Schin { 374887Schin "C", 384887Schin "POSIX", 398462SApril.Chin@Sun.COM &lc_languages[0], 408462SApril.Chin@Sun.COM &lc_territories[0], 418462SApril.Chin@Sun.COM &lc_charsets[0], 424887Schin 0, 434887Schin LC_default|LC_checked|LC_local, 444887Schin 0, 454887Schin { 464887Schin { &default_lc, 0, 0 }, 474887Schin { &default_lc, 0, 0 }, 484887Schin { &default_lc, 0, 0 }, 494887Schin { &default_lc, 0, 0 }, 504887Schin { &default_lc, 0, 0 }, 514887Schin { &default_lc, 0, (void*)&default_numeric }, 524887Schin { &default_lc, 0, 0 }, 534887Schin { &default_lc, 0, 0 }, 544887Schin { &default_lc, 0, 0 }, 554887Schin { &default_lc, 0, 0 }, 564887Schin { &default_lc, 0, 0 }, 574887Schin { &default_lc, 0, 0 }, 584887Schin { &default_lc, 0, 0 }, 594887Schin { &default_lc, 0, 0 } 604887Schin } 614887Schin }; 624887Schin 634887Schin static Lc_numeric_t debug_numeric = { ',', '.' }; 644887Schin 654887Schin static Lc_t debug_lc = 664887Schin { 674887Schin "debug", 684887Schin "debug", 698462SApril.Chin@Sun.COM &lc_languages[1], 708462SApril.Chin@Sun.COM &lc_territories[1], 718462SApril.Chin@Sun.COM &lc_charsets[0], 724887Schin 0, 734887Schin LC_debug|LC_checked|LC_local, 744887Schin 0, 754887Schin { 764887Schin { &debug_lc, 0, 0 }, 774887Schin { &debug_lc, 0, 0 }, 784887Schin { &debug_lc, 0, 0 }, 794887Schin { &debug_lc, 0, 0 }, 804887Schin { &debug_lc, 0, 0 }, 814887Schin { &debug_lc, 0, (void*)&debug_numeric }, 824887Schin { &debug_lc, 0, 0 }, 834887Schin { &debug_lc, 0, 0 }, 844887Schin { &debug_lc, 0, 0 }, 854887Schin { &debug_lc, 0, 0 }, 864887Schin { &debug_lc, 0, 0 }, 874887Schin { &debug_lc, 0, 0 }, 884887Schin { &debug_lc, 0, 0 }, 894887Schin { &debug_lc, 0, 0 } 904887Schin }, 914887Schin &default_lc 924887Schin }; 934887Schin 944887Schin static Lc_t* lcs = &debug_lc; 954887Schin 964887Schin Lc_t* locales[] = 974887Schin { 984887Schin &default_lc, 994887Schin &default_lc, 1004887Schin &default_lc, 1014887Schin &default_lc, 1024887Schin &default_lc, 1034887Schin &default_lc, 1044887Schin &default_lc, 1054887Schin &default_lc, 1064887Schin &default_lc, 1074887Schin &default_lc, 1084887Schin &default_lc, 1094887Schin &default_lc, 1104887Schin &default_lc, 1114887Schin &default_lc 1124887Schin }; 1134887Schin 1144887Schin /* 1154887Schin * return the internal category index for category 1164887Schin */ 1174887Schin 1184887Schin int 1194887Schin lcindex(int category, int min) 1204887Schin { 1214887Schin switch (category) 1224887Schin { 1234887Schin case LC_ALL: return min ? -1 : AST_LC_ALL; 1244887Schin case LC_ADDRESS: return AST_LC_ADDRESS; 1254887Schin case LC_COLLATE: return AST_LC_COLLATE; 1264887Schin case LC_CTYPE: return AST_LC_CTYPE; 1274887Schin case LC_IDENTIFICATION: return AST_LC_IDENTIFICATION; 128*10898Sroland.mainz@nrubsig.org case LC_LANG: return AST_LC_LANG; 1294887Schin case LC_MEASUREMENT: return AST_LC_MEASUREMENT; 1304887Schin case LC_MESSAGES: return AST_LC_MESSAGES; 1314887Schin case LC_MONETARY: return AST_LC_MONETARY; 1324887Schin case LC_NAME: return AST_LC_NAME; 1334887Schin case LC_NUMERIC: return AST_LC_NUMERIC; 1344887Schin case LC_PAPER: return AST_LC_PAPER; 1354887Schin case LC_TELEPHONE: return AST_LC_TELEPHONE; 1364887Schin case LC_TIME: return AST_LC_TIME; 1374887Schin case LC_XLITERATE: return AST_LC_XLITERATE; 1384887Schin } 1394887Schin return -1; 1404887Schin } 1414887Schin 1424887Schin /* 1434887Schin * return the first category table entry 1444887Schin */ 1454887Schin 1464887Schin Lc_category_t* 1474887Schin lccategories(void) 1484887Schin { 1498462SApril.Chin@Sun.COM return (Lc_category_t*)&lc_categories[0]; 1504887Schin } 1514887Schin 1524887Schin /* 1534887Schin * return the current info for category 1544887Schin */ 1554887Schin 1564887Schin Lc_info_t* 1574887Schin lcinfo(register int category) 1584887Schin { 1594887Schin if ((category = lcindex(category, 0)) < 0) 1604887Schin return 0; 1614887Schin return LCINFO(category); 1624887Schin } 1634887Schin 1644887Schin /* 1654887Schin * return 1 if s matches the alternation pattern p 1664887Schin * if minimum!=0 then at least that many chars must match 1674887Schin * if standard!=0 and s[0] is a digit leading non-digits are ignored in p 1684887Schin */ 1694887Schin 1704887Schin static int 1714887Schin match(const char* s, register const char* p, int minimum, int standard) 1724887Schin { 1734887Schin register const char* t; 1744887Schin const char* x; 1754887Schin int w; 1764887Schin int z; 1774887Schin 1784887Schin z = 0; 1794887Schin do 1804887Schin { 1814887Schin t = s; 1824887Schin if (standard) 1834887Schin { 1844887Schin if (isdigit(*t)) 1854887Schin while (*p && !isdigit(*p)) 1864887Schin p++; 1874887Schin else if (isdigit(*p)) 1884887Schin while (*t && !isdigit(*t)) 1894887Schin t++; 1904887Schin } 1914887Schin if (*p) 1924887Schin { 1934887Schin w = 0; 1944887Schin x = p; 1954887Schin while (*p && *p != '|') 1964887Schin { 1974887Schin if (!*t || *t == ',') 1984887Schin break; 1994887Schin else if (*t == *p) 2004887Schin /*ok*/; 2014887Schin else if (*t == '-') 2024887Schin { 2034887Schin if (standard && isdigit(*p)) 2044887Schin { 2054887Schin t++; 2064887Schin continue; 2074887Schin } 2084887Schin while (*p && *p != '-') 2094887Schin p++; 2104887Schin if (!*p) 2114887Schin break; 2124887Schin } 2134887Schin else if (*p == '-') 2144887Schin { 2154887Schin if (standard && isdigit(*t)) 2164887Schin { 2174887Schin p++; 2184887Schin continue; 2194887Schin } 2204887Schin w = 1; 2214887Schin while (*t && *t != '-') 2224887Schin t++; 2234887Schin if (!*t) 2244887Schin break; 2254887Schin } 2264887Schin else 2274887Schin break; 2284887Schin t++; 2294887Schin p++; 2304887Schin } 2314887Schin if ((!*t || *t == ',') && (!*p || *p == '|' || w)) 2324887Schin return p - x; 2334887Schin if (minimum && z < (p - x) && (p - x) >= minimum) 2344887Schin z = p - x; 2354887Schin } 2364887Schin while (*p && *p != '|') 2374887Schin p++; 2384887Schin } while (*p++); 2394887Schin return z; 2404887Schin } 2414887Schin 2424887Schin /* 2434887Schin * return 1 if s matches the charset names in cp 2444887Schin */ 2454887Schin 2464887Schin static int 2474887Schin match_charset(register const char* s, register const Lc_charset_t* cp) 2484887Schin { 2494887Schin return match(s, cp->code, 0, 1) || match(s, cp->alternates, 3, 1) || cp->ms && match(s, cp->ms, 0, 1); 2504887Schin } 2514887Schin 2524887Schin /* 2534887Schin * low level for lccanon 2544887Schin */ 2554887Schin 2564887Schin static size_t 2574887Schin canonical(const Lc_language_t* lp, const Lc_territory_t* tp, const Lc_charset_t* cp, const Lc_attribute_list_t* ap, unsigned long flags, char* buf, size_t siz) 2584887Schin { 2594887Schin register int c; 2604887Schin register int u; 2614887Schin register char* s; 2624887Schin register char* e; 2634887Schin register const char* t; 2644887Schin 2654887Schin if (!(flags & (LC_abbreviated|LC_default|LC_local|LC_qualified|LC_verbose))) 2664887Schin flags |= LC_abbreviated; 2674887Schin s = buf; 2684887Schin e = &buf[siz - 3]; 2694887Schin if (lp) 2704887Schin { 2714887Schin if (lp->flags & (LC_debug|LC_default)) 2724887Schin { 2734887Schin for (t = lp->code; s < e && (*s = *t++); s++); 2744887Schin *s++ = 0; 2754887Schin return s - buf; 2764887Schin } 2774887Schin if (flags & LC_verbose) 2784887Schin { 2794887Schin u = 1; 2804887Schin t = lp->name; 2814887Schin while (s < e && (c = *t++)) 2824887Schin { 2834887Schin if (u) 2844887Schin { 2854887Schin u = 0; 2864887Schin c = toupper(c); 2874887Schin } 2884887Schin else if (!isalnum(c)) 2894887Schin u = 1; 2904887Schin *s++ = c; 2914887Schin } 2924887Schin } 2934887Schin else 2944887Schin for (t = lp->code; s < e && (*s = *t++); s++); 2954887Schin } 2964887Schin if (s < e) 2974887Schin { 2988462SApril.Chin@Sun.COM if (tp && tp != &lc_territories[0] && (!(flags & (LC_abbreviated|LC_default)) || !lp || !streq(lp->code, tp->code))) 2994887Schin { 3004887Schin if (lp) 3014887Schin *s++ = '_'; 3024887Schin if (flags & LC_verbose) 3034887Schin { 3044887Schin u = 1; 3054887Schin t = tp->name; 3064887Schin while (s < e && (c = *t++) && c != '|') 3074887Schin { 3084887Schin if (u) 3094887Schin { 3104887Schin u = 0; 3114887Schin c = toupper(c); 3124887Schin } 3134887Schin else if (!isalnum(c)) 3144887Schin u = 1; 3154887Schin *s++ = c; 3164887Schin } 3174887Schin } 3184887Schin else 3194887Schin for (t = tp->code; s < e && (*s = toupper(*t++)); s++); 3204887Schin } 3214887Schin if (lp && (!(flags & (LC_abbreviated|LC_default)) || cp != lp->charset) && s < e) 3224887Schin { 3234887Schin *s++ = '.'; 3244887Schin for (t = cp->code; s < e && (c = *t++); s++) 3254887Schin { 3264887Schin if (islower(c)) 3274887Schin c = toupper(c); 3284887Schin *s = c; 3294887Schin } 3304887Schin } 3314887Schin for (c = '@'; ap && s < e; ap = ap->next) 3324887Schin if (!(flags & (LC_abbreviated|LC_default|LC_verbose)) || !(ap->attribute->flags & LC_default)) 3334887Schin { 3344887Schin *s++ = c; 3354887Schin c = ','; 3364887Schin for (t = ap->attribute->name; s < e && (*s = *t++); s++); 3374887Schin } 3384887Schin } 3394887Schin *s++ = 0; 3404887Schin return s - buf; 3414887Schin } 3424887Schin 3434887Schin /* 3444887Schin * generate a canonical locale name in buf 3454887Schin */ 3464887Schin 3474887Schin size_t 3484887Schin lccanon(Lc_t* lc, unsigned long flags, char* buf, size_t siz) 3494887Schin { 3504887Schin if ((flags & LC_local) && (!lc->language || !(lc->language->flags & (LC_debug|LC_default)))) 3514887Schin { 3524887Schin #if _WINIX 3534887Schin char lang[64]; 3544887Schin char code[64]; 3554887Schin char ctry[64]; 3564887Schin 3574887Schin if (lc->index && 3584887Schin GetLocaleInfo(lc->index, LOCALE_SENGLANGUAGE, lang, sizeof(lang)) && 3594887Schin GetLocaleInfo(lc->index, LOCALE_SENGCOUNTRY, ctry, sizeof(ctry))) 3604887Schin { 3614887Schin if (!GetLocaleInfo(lc->index, LOCALE_IDEFAULTANSICODEPAGE, code, sizeof(code))) 3624887Schin code[0] = 0; 3634887Schin if (!lc->charset || !lc->charset->ms) 3644887Schin return sfsprintf(buf, siz, "%s_%s", lang, ctry); 3654887Schin else if (streq(lc->charset->ms, code)) 3664887Schin return sfsprintf(buf, siz, "%s_%s.%s", lang, ctry, code); 3674887Schin else 3684887Schin return sfsprintf(buf, siz, "%s_%s.%s,%s", lang, ctry, code, lc->charset->ms); 3694887Schin } 3704887Schin #endif 3714887Schin buf[0] = '-'; 3724887Schin buf[1] = 0; 3734887Schin return 0; 3744887Schin } 3754887Schin return canonical(lc->language, lc->territory, lc->charset, lc->attributes, flags, buf, siz); 3764887Schin } 3774887Schin 3784887Schin /* 3794887Schin * make an Lc_t from a locale name 3804887Schin */ 3814887Schin 3824887Schin Lc_t* 3834887Schin lcmake(const char* name) 3844887Schin { 3854887Schin register int c; 3864887Schin register char* s; 3874887Schin register char* e; 3884887Schin register const char* t; 3894887Schin const char* a; 3904887Schin char* w; 3914887Schin char* language_name; 3924887Schin char* territory_name; 3934887Schin char* charset_name; 3944887Schin char* attributes_name; 3954887Schin Lc_t* lc; 3964887Schin const Lc_map_t* mp; 3974887Schin const Lc_language_t* lp; 3984887Schin const Lc_territory_t* tp; 3994887Schin const Lc_territory_t* tpb; 4004887Schin const Lc_territory_t* primary; 4014887Schin const Lc_charset_t* cp; 4024887Schin const Lc_charset_t* ppa; 4034887Schin const Lc_attribute_t* ap; 4044887Schin Lc_attribute_list_t* ai; 4054887Schin Lc_attribute_list_t* al; 4064887Schin int i; 4074887Schin int n; 4084887Schin int z; 4094887Schin char buf[PATH_MAX / 2]; 4104887Schin char tmp[PATH_MAX / 2]; 4114887Schin 4124887Schin if (!(t = name) || !*t) 4134887Schin return &default_lc; 4144887Schin for (lc = lcs; lc; lc = lc->next) 4154887Schin if (!strcasecmp(t, lc->code) || !strcasecmp(t, lc->name)) 4164887Schin return lc; 4178462SApril.Chin@Sun.COM for (mp = lc_maps; mp->code; mp++) 4184887Schin if (streq(t, mp->code)) 4194887Schin { 4204887Schin lp = mp->language; 4214887Schin tp = mp->territory; 4224887Schin cp = mp->charset; 4234887Schin if (!mp->attribute) 4244887Schin al = 0; 4254887Schin else if (al = newof(0, Lc_attribute_list_t, 1, 0)) 4264887Schin al->attribute = mp->attribute; 4274887Schin goto mapped; 4284887Schin } 4294887Schin language_name = buf; 4304887Schin territory_name = charset_name = attributes_name = 0; 4314887Schin s = buf; 4324887Schin e = &buf[sizeof(buf)-2]; 4334887Schin a = 0; 4344887Schin n = 0; 4354887Schin while (s < e && (c = *t++)) 4364887Schin { 4374887Schin if (isspace(c) || (c == '(' || c == '-' && *t == '-') && ++n) 4384887Schin { 4394887Schin while ((c = *t++) && (isspace(c) || (c == '-' || c == '(' || c == ')') && ++n)) 4404887Schin if (!c) 4414887Schin break; 4424887Schin if (isalnum(c) && !n) 4434887Schin *s++ = '-'; 4444887Schin else 4454887Schin { 4464887Schin n = 0; 4474887Schin if (!a) 4484887Schin { 4494887Schin a = t - 1; 4504887Schin while (c && c != '_' && c != '.' && c != '@') 4514887Schin c = *t++; 4524887Schin if (!c) 4534887Schin break; 4544887Schin } 4554887Schin } 4564887Schin } 4574887Schin if (c == '_' && !territory_name) 4584887Schin { 4594887Schin *s++ = 0; 4604887Schin territory_name = s; 4614887Schin } 4624887Schin else if (c == '.' && !charset_name) 4634887Schin { 4644887Schin *s++ = 0; 4654887Schin charset_name = s; 4664887Schin } 4674887Schin else if (c == '@' && !attributes_name) 4684887Schin { 4694887Schin *s++ = 0; 4704887Schin attributes_name = s; 4714887Schin } 4724887Schin else 4734887Schin { 4744887Schin if (isupper(c)) 4754887Schin c = tolower(c); 4764887Schin *s++ = c; 4774887Schin } 4784887Schin } 4794887Schin if ((t = a) && s < e) 4804887Schin { 4814887Schin if (attributes_name) 4824887Schin *s++ = ','; 4834887Schin else 4844887Schin { 4854887Schin *s++ = 0; 4864887Schin attributes_name = s; 4874887Schin } 4884887Schin while (s < e && (c = *t++)) 4894887Schin { 4904887Schin if (isspace(c) || (c == '(' || c == ')' || c == '-' && *t == '-') && ++n) 4914887Schin { 4924887Schin while ((c = *t++) && (isspace(c) || (c == '-' || c == '(' || c == ')') && ++n)) 4934887Schin if (!c) 4944887Schin break; 4954887Schin if (isalnum(c) && !n) 4964887Schin *s++ = '-'; 4974887Schin else 4984887Schin n = 0; 4994887Schin } 5004887Schin if (c == '_' || c == '.' || c == '@') 5014887Schin break; 5024887Schin if (isupper(c)) 5034887Schin c = tolower(c); 5044887Schin *s++ = c; 5054887Schin } 5064887Schin } 5074887Schin *s = 0; 5084887Schin tp = 0; 5094887Schin cp = ppa = 0; 5104887Schin al = 0; 5114887Schin 5124887Schin /* 5134887Schin * language 5144887Schin */ 5154887Schin 5164887Schin n = strlen(s = language_name); 5174887Schin if (n == 2) 5188462SApril.Chin@Sun.COM for (lp = lc_languages; lp->code && !streq(s, lp->code); lp++); 5194887Schin else if (n == 3) 5204887Schin { 5218462SApril.Chin@Sun.COM for (lp = lc_languages; lp->code && (!lp->alternates || !match(s, lp->alternates, n, 0)); lp++); 5224887Schin if (!lp->code) 5234887Schin { 5244887Schin c = s[2]; 5254887Schin s[2] = 0; 5268462SApril.Chin@Sun.COM for (lp = lc_languages; lp->code && !streq(s, lp->code); lp++); 5274887Schin s[2] = c; 5284887Schin if (lp->code) 5294887Schin n = 1; 5304887Schin } 5314887Schin } 5324887Schin else 5334887Schin lp = 0; 5344887Schin if (!lp || !lp->code) 5354887Schin { 5368462SApril.Chin@Sun.COM for (lp = lc_languages; lp->code && !match(s, lp->name, 0, 0); lp++); 5374887Schin if (!lp || !lp->code) 5384887Schin { 5394887Schin if (!territory_name) 5404887Schin { 5414887Schin if (n == 2) 5428462SApril.Chin@Sun.COM for (tp = lc_territories; tp->code && !streq(s, tp->code); tp++); 5434887Schin else 5444887Schin { 5454887Schin z = 0; 5464887Schin tpb = 0; 5478462SApril.Chin@Sun.COM for (tp = lc_territories; tp->name; tp++) 5484887Schin if ((i = match(s, tp->name, 3, 0)) > z) 5494887Schin { 5504887Schin tpb = tp; 5514887Schin if ((z = i) == n) 5524887Schin break; 5534887Schin } 5544887Schin if (tpb) 5554887Schin tp = tpb; 5564887Schin } 5574887Schin if (tp->code) 5584887Schin lp = tp->languages[0]; 5594887Schin } 5604887Schin if (!lp || !lp->code) 5614887Schin { 5624887Schin /* 5634887Schin * name not in the tables so let 5644887Schin * _ast_setlocale() and/or setlocale() 5654887Schin * handle the validity checks 5664887Schin */ 5674887Schin 5684887Schin s = (char*)name; 5694887Schin z = strlen(s) + 1; 5704887Schin if (!(lp = newof(0, Lc_language_t, 1, z))) 5714887Schin return 0; 5724887Schin name = ((Lc_language_t*)lp)->code = ((Lc_language_t*)lp)->name = (const char*)(lp + 1); 5734887Schin memcpy((char*)lp->code, s, z - 1); 5748462SApril.Chin@Sun.COM tp = &lc_territories[0]; 5758462SApril.Chin@Sun.COM cp = ((Lc_language_t*)lp)->charset = &lc_charsets[0]; 5764887Schin al = 0; 5774887Schin goto override; 5784887Schin } 5794887Schin } 5804887Schin } 5814887Schin 5824887Schin /* 5834887Schin * territory 5844887Schin */ 5854887Schin 5864887Schin if (!tp || !tp->code) 5874887Schin { 5884887Schin if (!(s = territory_name)) 5894887Schin { 5904887Schin n = 0; 5914887Schin primary = 0; 5928462SApril.Chin@Sun.COM for (tp = lc_territories; tp->code; tp++) 5934887Schin if (tp->languages[0] == lp) 5944887Schin { 5954887Schin if (tp->flags & LC_primary) 5964887Schin { 5974887Schin n = 1; 5984887Schin primary = tp; 5994887Schin break; 6004887Schin } 6014887Schin n++; 6024887Schin primary = tp; 6034887Schin } 6044887Schin if (n == 1) 6054887Schin tp = primary; 6064887Schin s = (char*)lp->code; 6074887Schin } 6084887Schin if (!tp || !tp->code) 6094887Schin { 6104887Schin n = strlen(s); 6114887Schin if (n == 2) 6124887Schin { 6138462SApril.Chin@Sun.COM for (tp = lc_territories; tp->code; tp++) 6144887Schin if (streq(s, tp->code)) 6154887Schin { 6164887Schin for (i = 0; i < elementsof(tp->languages) && lp != tp->languages[i]; i++); 6174887Schin if (i >= elementsof(tp->languages)) 6184887Schin tp = 0; 6194887Schin break; 6204887Schin } 6214887Schin } 6224887Schin else 6234887Schin { 6248462SApril.Chin@Sun.COM for (tp = lc_territories; tp->code; tp++) 6254887Schin if (match(s, tp->name, 3, 0)) 6264887Schin { 6274887Schin for (i = 0; i < elementsof(tp->languages) && lp != tp->languages[i]; i++); 6284887Schin if (i < elementsof(tp->languages)) 6294887Schin break; 6304887Schin } 6314887Schin } 6324887Schin if (tp && !tp->code) 6334887Schin tp = 0; 6344887Schin } 6354887Schin } 6364887Schin 6374887Schin /* 6384887Schin * attributes -- done here to catch misplaced charset references 6394887Schin */ 6404887Schin 6414887Schin if (s = attributes_name) 6424887Schin { 6434887Schin do 6444887Schin { 6454887Schin for (w = s; *s && *s != ','; s++); 6464887Schin c = *s; 6474887Schin *s = 0; 6484887Schin if (!(cp = lp->charset) || !match_charset(w, cp)) 6498462SApril.Chin@Sun.COM for (cp = lc_charsets; cp->code; cp++) 6504887Schin if (match_charset(w, cp)) 6514887Schin { 6524887Schin ppa = cp; 6534887Schin break; 6544887Schin } 6554887Schin if (!cp->code) 6564887Schin { 6574887Schin for (i = 0; i < elementsof(lp->attributes) && (ap = lp->attributes[i]); i++) 6584887Schin if (match(w, ap->name, 5, 0)) 6594887Schin { 6604887Schin if (ai = newof(0, Lc_attribute_list_t, 1, 0)) 6614887Schin { 6624887Schin ai->attribute = ap; 6634887Schin ai->next = al; 6644887Schin al = ai; 6654887Schin } 6664887Schin break; 6674887Schin } 6684887Schin if (i >= elementsof(lp->attributes) && (ap = newof(0, Lc_attribute_t, 1, sizeof(Lc_attribute_list_t) + s - w + 1))) 6694887Schin { 6704887Schin ai = (Lc_attribute_list_t*)(ap + 1); 6714887Schin strcpy((char*)(((Lc_attribute_t*)ap)->name = (const char*)(ai + 1)), w); 6724887Schin ai->attribute = ap; 6734887Schin ai->next = al; 6744887Schin al = ai; 6754887Schin } 6764887Schin } 6774887Schin *s = c; 6784887Schin } while (*s++); 6794887Schin } 6804887Schin 6814887Schin /* 6824887Schin * charset 6834887Schin */ 6844887Schin 6854887Schin if (s = charset_name) 6868462SApril.Chin@Sun.COM for (cp = lc_charsets; cp->code; cp++) 6874887Schin if (match_charset(s, cp)) 6884887Schin break; 6894887Schin if (!cp || !cp->code) 6904887Schin cp = ppa ? ppa : lp->charset; 6914887Schin mapped: 6924887Schin z = canonical(lp, tp, cp, al, 0, s = tmp, sizeof(tmp)); 6934887Schin 6944887Schin /* 6954887Schin * add to the list of possibly active locales 6964887Schin */ 6974887Schin 6984887Schin override: 6994887Schin n = strlen(name) + 1; 7004887Schin if (!(lc = newof(0, Lc_t, 1, n + z))) 7014887Schin return 0; 7024887Schin strcpy((char*)(lc->name = (const char*)(lc + 1)), name); 7034887Schin strcpy((char*)(lc->code = lc->name + n), s); 7048462SApril.Chin@Sun.COM lc->language = lp ? lp : &lc_languages[0]; 7058462SApril.Chin@Sun.COM lc->territory = tp ? tp : &lc_territories[0]; 7068462SApril.Chin@Sun.COM lc->charset = cp ? cp : &lc_charsets[0]; 707*10898Sroland.mainz@nrubsig.org if (!strcmp(lc->charset->code, "utf8")) 708*10898Sroland.mainz@nrubsig.org lc->flags |= LC_utf8; 7094887Schin lc->attributes = al; 7104887Schin for (i = 0; i < elementsof(lc->info); i++) 7114887Schin lc->info[i].lc = lc; 7124887Schin #if _WINIX 7134887Schin n = SUBLANG_DEFAULT; 7144887Schin if (tp) 7154887Schin for (i = 0; i < elementsof(tp->languages); i++) 7164887Schin if (lp == tp->languages[i]) 7174887Schin { 7184887Schin n = tp->indices[i]; 7194887Schin break; 7204887Schin } 7214887Schin lc->index = MAKELCID(MAKELANGID(lp->index, n), SORT_DEFAULT); 7224887Schin #endif 7234887Schin lc->next = lcs; 7244887Schin lcs = lc; 7254887Schin return lc; 7264887Schin } 7274887Schin 7284887Schin /* 7294887Schin * return an Lc_t* for each locale in the tables 7304887Schin * one Lc_t is allocated on the first call with lc==0 7314887Schin * this is freed when 0 returned 7324887Schin * the return value is not part of the lcmake() cache 7334887Schin */ 7344887Schin 7354887Schin typedef struct Lc_scan_s 7364887Schin { 7374887Schin Lc_t lc; 7384887Schin Lc_attribute_list_t list; 7394887Schin int territory; 7404887Schin int language; 7414887Schin int attribute; 7424887Schin char buf[256]; 7434887Schin } Lc_scan_t; 7444887Schin 7454887Schin Lc_t* 7464887Schin lcscan(Lc_t* lc) 7474887Schin { 7484887Schin register Lc_scan_t* ls; 7494887Schin 7504887Schin if (!(ls = (Lc_scan_t*)lc)) 7514887Schin { 7524887Schin if (!(ls = newof(0, Lc_scan_t, 1, 0))) 7534887Schin return 0; 7544887Schin ls->lc.code = ls->lc.name = ls->buf; 7554887Schin ls->territory = -1; 7564887Schin ls->language = elementsof(ls->lc.territory->languages); 7574887Schin ls->attribute = elementsof(ls->lc.language->attributes); 7584887Schin } 7594887Schin if (++ls->attribute >= elementsof(ls->lc.language->attributes) || !(ls->list.attribute = ls->lc.language->attributes[ls->attribute])) 7604887Schin { 7614887Schin if (++ls->language >= elementsof(ls->lc.territory->languages) || !(ls->lc.language = ls->lc.territory->languages[ls->language])) 7624887Schin { 7638462SApril.Chin@Sun.COM if (!lc_territories[++ls->territory].code) 7644887Schin { 7654887Schin free(ls); 7664887Schin return 0; 7674887Schin } 7688462SApril.Chin@Sun.COM ls->lc.territory = &lc_territories[ls->territory]; 7694887Schin ls->lc.language = ls->lc.territory->languages[ls->language = 0]; 7704887Schin } 7714887Schin if (ls->lc.language) 7724887Schin { 7738462SApril.Chin@Sun.COM ls->lc.charset = ls->lc.language->charset ? ls->lc.language->charset : &lc_charsets[0]; 7744887Schin ls->list.attribute = ls->lc.language->attributes[ls->attribute = 0]; 7754887Schin } 7764887Schin else 7774887Schin { 7788462SApril.Chin@Sun.COM ls->lc.charset = &lc_charsets[0]; 7794887Schin ls->list.attribute = 0; 7804887Schin } 7814887Schin } 7824887Schin ls->lc.attributes = ls->list.attribute ? &ls->list : (Lc_attribute_list_t*)0; 7834887Schin #if _WINIX 7844887Schin if (!ls->lc.language || !ls->lc.language->index) 7854887Schin ls->lc.index = 0; 7864887Schin else 7874887Schin { 7884887Schin if ((!ls->list.attribute || !(ls->lc.index = ls->list.attribute->index)) && 7894887Schin (!ls->lc.territory || !(ls->lc.index = ls->lc.territory->indices[ls->language]))) 7904887Schin ls->lc.index = SUBLANG_DEFAULT; 7914887Schin ls->lc.index = MAKELCID(MAKELANGID(ls->lc.language->index, ls->lc.index), SORT_DEFAULT); 7924887Schin } 7934887Schin #endif 7944887Schin canonical(ls->lc.language, ls->lc.territory, ls->lc.charset, ls->lc.attributes, 0, ls->buf, sizeof(ls->buf)); 7954887Schin return (Lc_t*)ls; 7964887Schin } 797