/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1985-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* locale state implementation
*/
#include "lclib.h"
#include "lclang.h"
#include <ctype.h>
typedef struct Local_s
{
const char* name;
int size;
} Local_t;
{
"C",
"POSIX",
&lc_languages[0],
&lc_territories[0],
&lc_charsets[0],
0,
0,
{
{ &default_lc, 0, 0 },
{ &default_lc, 0, 0 },
{ &default_lc, 0, 0 },
{ &default_lc, 0, 0 },
{ &default_lc, 0, 0 },
{ &default_lc, 0, (void*)&default_numeric },
{ &default_lc, 0, 0 },
{ &default_lc, 0, 0 },
{ &default_lc, 0, 0 },
{ &default_lc, 0, 0 },
{ &default_lc, 0, 0 },
{ &default_lc, 0, 0 },
{ &default_lc, 0, 0 },
{ &default_lc, 0, 0 }
}
};
{
"debug",
"debug",
&lc_languages[1],
&lc_territories[1],
&lc_charsets[0],
0,
0,
{
{ &debug_lc, 0, 0 },
{ &debug_lc, 0, 0 },
{ &debug_lc, 0, 0 },
{ &debug_lc, 0, 0 },
{ &debug_lc, 0, 0 },
{ &debug_lc, 0, (void*)&debug_numeric },
{ &debug_lc, 0, 0 },
{ &debug_lc, 0, 0 },
{ &debug_lc, 0, 0 },
{ &debug_lc, 0, 0 },
{ &debug_lc, 0, 0 },
{ &debug_lc, 0, 0 },
{ &debug_lc, 0, 0 },
{ &debug_lc, 0, 0 }
},
};
{
};
/*
* return the internal category index for category
*/
int
{
switch (category)
{
case LC_ADDRESS: return AST_LC_ADDRESS;
case LC_COLLATE: return AST_LC_COLLATE;
case LC_CTYPE: return AST_LC_CTYPE;
case LC_IDENTIFICATION: return AST_LC_IDENTIFICATION;
case LC_LANG: return AST_LC_LANG;
case LC_MEASUREMENT: return AST_LC_MEASUREMENT;
case LC_MESSAGES: return AST_LC_MESSAGES;
case LC_MONETARY: return AST_LC_MONETARY;
case LC_NAME: return AST_LC_NAME;
case LC_NUMERIC: return AST_LC_NUMERIC;
case LC_PAPER: return AST_LC_PAPER;
case LC_TELEPHONE: return AST_LC_TELEPHONE;
case LC_TIME: return AST_LC_TIME;
case LC_XLITERATE: return AST_LC_XLITERATE;
}
return -1;
}
/*
* return the first category table entry
*/
lccategories(void)
{
return (Lc_category_t*)&lc_categories[0];
}
/*
* return the current info for category
*/
{
return 0;
}
/*
* return 1 if s matches the alternation pattern p
* if minimum!=0 then at least that many chars must match
* if standard!=0 and s[0] is a digit leading non-digits are ignored in p
*/
static int
{
register const char* t;
const char* x;
int w;
int z;
z = 0;
do
{
t = s;
if (standard)
{
if (isdigit(*t))
while (*p && !isdigit(*p))
p++;
else if (isdigit(*p))
while (*t && !isdigit(*t))
t++;
}
if (*p)
{
w = 0;
x = p;
while (*p && *p != '|')
{
if (!*t || *t == ',')
break;
else if (*t == *p)
/*ok*/;
else if (*t == '-')
{
{
t++;
continue;
}
while (*p && *p != '-')
p++;
if (!*p)
break;
}
else if (*p == '-')
{
{
p++;
continue;
}
w = 1;
while (*t && *t != '-')
t++;
if (!*t)
break;
}
else
break;
t++;
p++;
}
if ((!*t || *t == ',') && (!*p || *p == '|' || w))
return p - x;
z = p - x;
}
while (*p && *p != '|')
p++;
} while (*p++);
return z;
}
/*
* return 1 if s matches the charset names in cp
*/
static int
{
return match(s, cp->code, 0, 1) || match(s, cp->alternates, 3, 1) || cp->ms && match(s, cp->ms, 0, 1);
}
/*
* low level for lccanon
*/
static size_t
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)
{
register int c;
register int u;
register char* s;
register char* e;
register const char* t;
char* p;
char* r;
flags |= LC_abbreviated;
s = buf;
if (lp)
{
{
*s++ = 0;
return s - buf;
}
if (flags & LC_verbose)
{
u = 1;
while (s < e && (c = *t++))
{
if (u)
{
u = 0;
c = toupper(c);
}
else if (!isalnum(c))
u = 1;
*s++ = c;
}
}
else
}
if (s < e)
{
{
r = 0;
if (lp)
{
r = s;
*s++ = '_';
}
if (flags & LC_verbose)
{
u = 1;
while (s < e && (c = *t++) && c != '|')
{
if (u)
{
u = 0;
c = toupper(c);
}
else if (!isalnum(c))
u = 1;
*s++ = c;
}
}
else
if (r)
{
*s = 0;
{
{
*r = 0;
*r = '_';
}
setlocale(LC_MESSAGES, p);
free(p);
}
}
}
{
*s++ = '.';
for (; s < e && (c = *t++); s++)
*s = c;
else
{
if (islower(c))
c = toupper(c);
*s = c;
}
}
{
*s++ = c;
c = ',';
}
}
*s++ = 0;
return s - buf;
}
/*
* generate a canonical locale name in buf
*/
{
{
#if _WINIX
{
code[0] = 0;
else
}
#endif
buf[0] = '-';
buf[1] = 0;
return 0;
}
}
/*
* make an Lc_t from a locale name
*/
Lc_t*
{
register int c;
register char* s;
register char* e;
register const char* t;
const char* a;
char* w;
char* language_name;
char* territory_name;
char* charset_name;
char* attributes_name;
int i;
int n;
int z;
if (!(t = name) || !*t)
return &default_lc;
return lc;
{
al = 0;
goto mapped;
}
language_name = buf;
s = buf;
a = 0;
n = 0;
while (s < e && (c = *t++))
{
{
if (!c)
break;
if (isalnum(c) && !n)
*s++ = '-';
else
{
n = 0;
if (!a)
{
a = t - 1;
while (c && c != '_' && c != '.' && c != '@')
c = *t++;
if (!c)
break;
}
}
}
if (c == '_' && !territory_name)
{
*s++ = 0;
territory_name = s;
}
else if (c == '.' && !charset_name)
{
*s++ = 0;
charset_name = s;
}
else if (c == '@' && !attributes_name)
{
*s++ = 0;
attributes_name = s;
}
else
{
if (isupper(c))
c = tolower(c);
*s++ = c;
}
}
if ((t = a) && s < e)
{
if (attributes_name)
*s++ = ',';
else
{
*s++ = 0;
attributes_name = s;
}
while (s < e && (c = *t++))
{
{
if (!c)
break;
if (isalnum(c) && !n)
*s++ = '-';
else
n = 0;
}
if (c == '_' || c == '.' || c == '@')
break;
if (isupper(c))
c = tolower(c);
*s++ = c;
}
}
*s = 0;
#if AHA
sfprintf(sfstderr, "locale make %s language=%s territory=%s charset=%s attributes=%s\n", name, language_name, territory_name, charset_name, attributes_name);
#endif
tp = 0;
al = 0;
/*
* language
*/
n = strlen(s = language_name);
if (n == 2)
else if (n == 3)
{
{
c = s[2];
s[2] = 0;
s[2] = c;
n = 1;
}
}
lp = &lc_languages[0];
else
lp = 0;
{
{
if (!territory_name)
{
if (n == 2)
else
{
z = 0;
tpb = 0;
{
if ((z = i) == n)
break;
}
if (tpb)
}
}
{
/*
* name not in the tables so let
* handle the validity checks
*/
s = (char*)name;
z = strlen(s) + 1;
return 0;
tp = &lc_territories[0];
cp = &lc_charsets[0];
if (charset_name)
{
break;
}
al = 0;
goto override;
}
}
}
/*
* territory
*/
{
if (!(s = territory_name))
{
n = 0;
primary = 0;
{
{
n = 1;
break;
}
n++;
}
if (n == 1)
}
{
n = strlen(s);
if (n == 2)
{
{
if (lp != &lc_languages[0])
{
tp = 0;
}
break;
}
}
else
{
{
break;
}
}
tp = 0;
}
}
/*
* attributes -- done here to catch misplaced charset references
*/
if (s = attributes_name)
{
do
{
for (w = s; *s && *s != ','; s++);
c = *s;
*s = 0;
if (match_charset(w, cp))
{
break;
}
{
{
{
}
break;
}
if (i >= elementsof(lp->attributes) && (ap = newof(0, Lc_attribute_t, 1, sizeof(Lc_attribute_list_t) + s - w + 1)))
{
}
}
*s = c;
} while (*s++);
}
/*
* charset
*/
if (s = charset_name)
if (match_charset(s, cp))
break;
#if AHA
sfprintf(sfstderr, "locale make %s charset_name=%s cp=%s ppa=%s lp=%s\n", name, charset_name, cp ? cp->code : 0, ppa, lp->charset);
#endif
/*
* add to the list of possibly active locales
*/
i = -1;
for (c = 0; c < elementsof(local); ++c)
{
{
case '.':
case '_':
case 0:
i = c;
break;
}
break;
}
return 0;
if (i >= 0)
{
}
else
#if _WINIX
n = SUBLANG_DEFAULT;
if (tp)
{
break;
}
#endif
sfprintf(sfstderr, "locale make %17s %16s %16s %16s language=%s territory=%s charset=%s%s\n", "", lc->name, lc->code, "", lc->language->name, lc->territory->name, lc->charset->code, (lc->flags & LC_local) ? " local" : "");
return lc;
}
/*
* return an Lc_t* for each locale in the tables
* one Lc_t is allocated on the first call with lc==0
* this is freed when 0 returned
* the return value is not part of the lcmake() cache
*/
typedef struct Lc_scan_s
{
int territory;
int language;
int attribute;
} Lc_scan_t;
Lc_t*
{
{
return 0;
}
if (++ls->attribute >= elementsof(ls->lc.language->attributes) || !(ls->list.attribute = ls->lc.language->attributes[ls->attribute]))
{
if (++ls->language >= elementsof(ls->lc.territory->languages) || !(ls->lc.language = ls->lc.territory->languages[ls->language]))
{
{
return 0;
}
}
{
}
else
{
}
}
#if _WINIX
else
{
}
#endif
canonical(ls->lc.language, ls->lc.territory, ls->lc.charset, ls->lc.attributes, 0, ls->buf, sizeof(ls->buf));
}