summaryrefslogtreecommitdiff
path: root/libc/misc/locale/locale.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc/misc/locale/locale.c')
-rw-r--r--libc/misc/locale/locale.c177
1 files changed, 77 insertions, 100 deletions
diff --git a/libc/misc/locale/locale.c b/libc/misc/locale/locale.c
index 858a02c33..68e54413e 100644
--- a/libc/misc/locale/locale.c
+++ b/libc/misc/locale/locale.c
@@ -11,8 +11,8 @@
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
*/
/* Nov. 1, 2002
@@ -58,20 +58,6 @@
#include <ctype.h>
#include <stdio.h>
-/* Experimentally off - libc_hidden_proto(memcpy) */
-/* Experimentally off - libc_hidden_proto(memset) */
-/* Experimentally off - libc_hidden_proto(strtok_r) */
-/* Experimentally off - libc_hidden_proto(strlen) */
-/* Experimentally off - libc_hidden_proto(strcmp) */
-/* Experimentally off - libc_hidden_proto(strcpy) */
-/* Experimentally off - libc_hidden_proto(strncmp) */
-/* Experimentally off - libc_hidden_proto(strchr) */
-libc_hidden_proto(getenv)
-#ifdef __UCLIBC_HAS_CTYPE_TABLES__
-libc_hidden_proto(__C_ctype_toupper)
-#endif
-/*libc_hidden_proto(fflush)*/
-
#ifdef __UCLIBC_MJN3_ONLY__
#ifdef L_setlocale
#warning TODO: Make the link_warning()s a config option?
@@ -99,19 +85,17 @@ libc_hidden_proto(__C_ctype_toupper)
#endif
#endif
-/* Need to include this before locale.h and xlocale.h! */
+/* Need to include this before locale.h! */
#include <bits/uClibc_locale.h>
#undef CODESET_LIST
#define CODESET_LIST (__locale_mmap->codeset_list)
#ifdef __UCLIBC_HAS_XLOCALE__
-#include <xlocale.h>
#include <locale.h>
-#else /* __UCLIBC_HAS_XLOCALE__ */
+#else /* __UCLIBC_HAS_XLOCALE__ */
/* We need this internally... */
#define __UCLIBC_HAS_XLOCALE__ 1
-#include <xlocale.h>
#include <locale.h>
#undef __UCLIBC_HAS_XLOCALE__
#endif /* __UCLIBC_HAS_XLOCALE__ */
@@ -120,14 +104,14 @@ libc_hidden_proto(__C_ctype_toupper)
#define LOCALE_NAMES (__locale_mmap->locale_names5)
#define LOCALES (__locale_mmap->locales)
-#define LOCALE_AT_MODIFIERS (__locale_mmap->locale_at_modifiers)
+#define LOCALE_AT_MODIFIERS (__locale_mmap->locale_at_modifiers)
#define CATEGORY_NAMES (__locale_mmap->lc_names)
#ifdef __UCLIBC_MJN3_ONLY__
#warning REMINDER: redo the MAX_LOCALE_STR stuff...
#endif
-#define MAX_LOCALE_STR 256 /* TODO: Only sufficient for current case. */
-#define MAX_LOCALE_CATEGORY_STR 32 /* TODO: Only sufficient for current case. */
+#define MAX_LOCALE_STR 256 /* TODO: Only sufficient for current case. */
+#define MAX_LOCALE_CATEGORY_STR 32 /* TODO: Only sufficient for current case. */
/* Note: Best if MAX_LOCALE_CATEGORY_STR is a power of 2. */
extern int _locale_set_l(const unsigned char *p, __locale_t base) attribute_hidden;
@@ -169,7 +153,7 @@ char *setlocale(int category, register const char *locale)
: NULL;
}
-#else /* ---------------------------------------------- __LOCALE_C_ONLY */
+#else /* ---------------------------------------------- __LOCALE_C_ONLY */
#ifdef __UCLIBC_HAS_THREADS__
link_warning(setlocale,"REMINDER: The 'setlocale' function is _not_ threadsafe except for simple queries.")
@@ -193,8 +177,6 @@ static const char utf8[] = "UTF-8";
*/
static char hr_locale[(MAX_LOCALE_CATEGORY_STR * LC_ALL) + MAX_LOCALE_STR];
-/* Experimentally off - libc_hidden_proto(stpcpy) */
-libc_hidden_proto(newlocale)
static void update_hr_locale(const unsigned char *spec)
{
@@ -230,7 +212,8 @@ static void update_hr_locale(const unsigned char *spec)
+ __LOCALE_DATA_WIDTH_LOCALES * ((((int)(*s & 0x7f)) << 7)
+ (s[1] & 0x7f));
if (category == LC_ALL) {
- n = stpcpy(n, CATEGORY_NAMES + (int) CATEGORY_NAMES[i]);
+ /* CATEGORY_NAMES is unsigned char* */
+ n = stpcpy(n, (char*) CATEGORY_NAMES + (int) CATEGORY_NAMES[i]);
*n++ = '=';
}
if (*loc == 0) {
@@ -248,12 +231,12 @@ static void update_hr_locale(const unsigned char *spec)
if (loc[2] == 2) {
n = stpcpy(n, utf8);
} else if (loc[2] >= 3) {
- n = stpcpy(n, CODESET_LIST + (int)(CODESET_LIST[loc[2] - 3]));
+ n = stpcpy(n, (char*) CODESET_LIST + (int)(CODESET_LIST[loc[2] - 3]));
}
if (at) {
const char *q;
*n++ = '@';
- q = LOCALE_AT_MODIFIERS;
+ q = (char*) LOCALE_AT_MODIFIERS;
do {
if (q[1] == at) {
n = stpcpy(n, q+2);
@@ -267,7 +250,7 @@ static void update_hr_locale(const unsigned char *spec)
}
s += 2;
} while (++i < category);
- *--n = 0; /* Remove trailing ';' and nul-terminate. */
+ *--n = 0; /* Remove trailing ';' and nul-terminate. */
++category;
} while (!done);
@@ -303,7 +286,6 @@ char *setlocale(int category, const char *locale)
* placement of the fields in the struct. If necessary, we could ensure
* this usings an array of offsets but at some size cost. */
-libc_hidden_proto(localeconv)
#ifdef __LOCALE_C_ONLY
@@ -332,14 +314,14 @@ struct lconv *localeconv(void)
return &the_lconv;
}
-#else /* __LOCALE_C_ONLY */
+#else /* __LOCALE_C_ONLY */
static struct lconv the_lconv;
struct lconv *localeconv(void)
{
register char *p = (char *) &the_lconv;
- register char **q = (char **) &(__UCLIBC_CURLOCALE_DATA).decimal_point;
+ register char **q = (char **) &(__UCLIBC_CURLOCALE->decimal_point);
do {
*((char **)p) = *q;
@@ -364,15 +346,7 @@ libc_hidden_def(localeconv)
/**********************************************************************/
#if defined(L__locale_init) && !defined(__LOCALE_C_ONLY)
-libc_hidden_proto(__C_ctype_b)
-libc_hidden_proto(__C_ctype_tolower)
-#ifndef __UCLIBC_HAS_XLOCALE__
-libc_hidden_proto(__ctype_b)
-libc_hidden_proto(__ctype_tolower)
-libc_hidden_proto(__ctype_toupper)
-#endif
-
-__uclibc_locale_t __global_locale_data;
+struct __uclibc_locale_struct __global_locale_data;
__locale_t __global_locale = &__global_locale_data;
@@ -609,7 +583,7 @@ int attribute_hidden _locale_set_l(const unsigned char *p, __locale_t base)
if ((p[2*LC_COLLATE] != s[2*LC_COLLATE])
|| (p[2*LC_COLLATE + 1] != s[2*LC_COLLATE + 1])
) {
- row = (((int)(*p & 0x7f)) << 7) + (p[1] & 0x7f);
+ row = (((int)(*p & 0x7f)) << 7) + (p[1] & 0x7f);
assert(row < __LOCALE_DATA_NUM_LOCALES);
if (!init_cur_collate(__locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES
* row + 3 + LC_COLLATE ],
@@ -623,7 +597,7 @@ int attribute_hidden _locale_set_l(const unsigned char *p, __locale_t base)
do {
if ((*p != *s) || (p[1] != s[1])) {
- row = (((int)(*p & 0x7f)) << 7) + (p[1] & 0x7f);
+ row = (((int)(*p & 0x7f)) << 7) + (p[1] & 0x7f);
assert(row < __LOCALE_DATA_NUM_LOCALES);
*s = *p;
@@ -644,8 +618,8 @@ int attribute_hidden _locale_set_l(const unsigned char *p, __locale_t base)
io = (const uint16_t *)( ((char *)__locale_mmap) + *++stp );
ii = (const uint16_t *)( ((char *)__locale_mmap) + *++stp );
d = (const unsigned char *)( ((char *)__locale_mmap) + *++stp );
- for (c=0 ; c < len ; c++) {
- *(x + c) = d + ii[ r[crow + c] + io[c] ];
+ for (c = 0; c < len; c++) {
+ x[c] = (char*)(d + ii[r[crow + c] + io[c]]);
}
}
if (i == LC_CTYPE) {
@@ -658,7 +632,7 @@ int attribute_hidden _locale_set_l(const unsigned char *p, __locale_t base)
/* TODO - fix for bcc */
base->mb_cur_max = 6;
} else {
- assert(c==1);
+ assert(c == 1);
base->codeset = ascii;
base->encoding = __ctype_encoding_7_bit;
base->mb_cur_max = 1;
@@ -666,7 +640,8 @@ int attribute_hidden _locale_set_l(const unsigned char *p, __locale_t base)
} else {
const __codeset_8_bit_t *c8b;
r = CODESET_LIST;
- base->codeset = r + r[c -= 3];
+ c -= 3;
+ base->codeset = (char *) (r + r[c]);
base->encoding = __ctype_encoding_8_bit;
#ifdef __UCLIBC_MJN3_ONLY__
#warning REMINDER: update 8 bit mb_cur_max when translit implemented!
@@ -789,7 +764,7 @@ int attribute_hidden _locale_set_l(const unsigned char *p, __locale_t base)
+ __UCLIBC_CTYPE_TO_TBL_OFFSET;
base->__ctype_toupper = base->__ctype_toupper_data
+ __UCLIBC_CTYPE_TO_TBL_OFFSET;
-#else /* __UCLIBC_HAS_XLOCALE__ */
+#else /* __UCLIBC_HAS_XLOCALE__ */
__ctype_b = base->__ctype_b_data
+ __UCLIBC_CTYPE_B_TBL_OFFSET;
__ctype_tolower = base->__ctype_tolower_data
@@ -879,17 +854,17 @@ void attribute_hidden _locale_init_l(__locale_t base)
LC_ALL);
++base->category_item_count[0]; /* Increment for codeset entry. */
- base->category_offsets[0] = offsetof(__uclibc_locale_t, outdigit0_mb);
- base->category_offsets[1] = offsetof(__uclibc_locale_t, decimal_point);
- base->category_offsets[2] = offsetof(__uclibc_locale_t, int_curr_symbol);
- base->category_offsets[3] = offsetof(__uclibc_locale_t, abday_1);
-/* base->category_offsets[4] = offsetof(__uclibc_locale_t, collate???); */
- base->category_offsets[5] = offsetof(__uclibc_locale_t, yesexpr);
+ base->category_offsets[0] = offsetof(struct __uclibc_locale_struct, outdigit0_mb);
+ base->category_offsets[1] = offsetof(struct __uclibc_locale_struct, decimal_point);
+ base->category_offsets[2] = offsetof(struct __uclibc_locale_struct, int_curr_symbol);
+ base->category_offsets[3] = offsetof(struct __uclibc_locale_struct, abday_1);
+/* base->category_offsets[4] = offsetof(struct __uclibc_locale_struct, collate???); */
+ base->category_offsets[5] = offsetof(struct __uclibc_locale_struct, yesexpr);
#ifdef __CTYPE_HAS_8_BIT_LOCALES
base->tbl8ctype
= (const unsigned char *) &__locale_mmap->tbl8ctype;
- base->tbl8uplow
+ base->tbl8uplow
= (const unsigned char *) &__locale_mmap->tbl8uplow;
#ifdef __UCLIBC_HAS_WCHAR__
base->tbl8c2wc
@@ -905,7 +880,7 @@ void attribute_hidden _locale_init_l(__locale_t base)
base->tblwuplow
= (const unsigned char *) &__locale_mmap->tblwuplow;
base->tblwuplow_diff
- = (const uint16_t *) &__locale_mmap->tblwuplow_diff;
+ = (const int16_t *) &__locale_mmap->tblwuplow_diff;
/* base->tblwcomb */
/* = (const unsigned char *) &__locale_mmap->tblwcomb; */
/* width?? */
@@ -917,7 +892,7 @@ void attribute_hidden _locale_init_l(__locale_t base)
base->__ctype_b = __C_ctype_b;
base->__ctype_tolower = __C_ctype_tolower;
base->__ctype_toupper = __C_ctype_toupper;
-#else /* __UCLIBC_HAS_XLOCALE__ */
+#else /* __UCLIBC_HAS_XLOCALE__ */
__ctype_b = __C_ctype_b;
__ctype_tolower = __C_ctype_tolower;
__ctype_toupper = __C_ctype_toupper;
@@ -928,11 +903,9 @@ void attribute_hidden _locale_init_l(__locale_t base)
#endif
base->code2flag = __code2flag;
-
- _locale_set_l(C_LOCALE_SELECTOR, base);
+ _locale_set_l((unsigned char*) C_LOCALE_SELECTOR, base);
}
-void _locale_init(void) attribute_hidden;
void _locale_init(void)
{
/* TODO: mmap the locale file */
@@ -967,7 +940,7 @@ void _locale_init(void)
static const unsigned char nl_data[C_LC_ALL + 1 + 90 + 320] = {
/* static const char cat_start[LC_ALL + 1] = { */
- '\x00', '\x0b', '\x0e', '\x24', '\x56', '\x56', '\x5a',
+ '\x00', '\x0b', '\x0e', '\x24', '\x56', '\x56', '\x5a',
/* }; */
/* static const char item_offset[90] = { */
'\x00', '\x02', '\x04', '\x06', '\x08', '\x0a', '\x0c', '\x0e',
@@ -1026,7 +999,6 @@ static const unsigned char nl_data[C_LC_ALL + 1 + 90 + 320] = {
']', '\x00', '^', '[', 'n', 'N', ']', '\x00',
};
-libc_hidden_proto(nl_langinfo)
char *nl_langinfo(nl_item item)
{
unsigned int c;
@@ -1042,13 +1014,11 @@ char *nl_langinfo(nl_item item)
}
libc_hidden_def(nl_langinfo)
-#else /* __LOCALE_C_ONLY */
+#else /* __LOCALE_C_ONLY */
#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
-libc_hidden_proto(nl_langinfo)
-libc_hidden_proto(nl_langinfo_l)
char *nl_langinfo(nl_item item)
{
@@ -1056,13 +1026,13 @@ char *nl_langinfo(nl_item item)
}
libc_hidden_def(nl_langinfo)
-#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
+#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
libc_hidden_proto(__XL_NPP(nl_langinfo))
static const char empty[] = "";
-char *__XL_NPP(nl_langinfo)(nl_item item __LOCALE_PARAM )
+char *__XL_NPP(nl_langinfo)(nl_item item __LOCALE_PARAM )
{
unsigned int c = _NL_ITEM_CATEGORY(item);
unsigned int i = _NL_ITEM_INDEX(item);
@@ -1084,8 +1054,7 @@ libc_hidden_def(__XL_NPP(nl_langinfo))
/**********************************************************************/
#ifdef L_newlocale
-/* Experimentally off - libc_hidden_proto(stpcpy) */
-libc_hidden_proto(newlocale)
+#warning mask defines for extra locale categories
#ifdef __UCLIBC_MJN3_ONLY__
#warning TODO: Move posix and utf8 strings.
@@ -1117,7 +1086,7 @@ static int find_locale(int category_mask, const char *p,
/* locale name at least 5 chars long and 3rd char is '_' */
s = LOCALE_AT_MODIFIERS;
do {
- if (!strcmp(s+2, q+1)) {
+ if (!strcmp((char*) (s + 2), q + 1)) {
break;
}
s += 2 + *s; /* TODO - fix this throughout */
@@ -1142,11 +1111,11 @@ static int find_locale(int category_mask, const char *p,
/* TODO: maybe CODESET_LIST + *s ??? */
/* 7bit is 1, UTF-8 is 2, 8-bit is >= 3 */
codeset = 2;
- if (strcasecmp(utf8,p+6) != 0) {/* TODO - fix! */
+ if (strcasecmp(utf8, p + 6) != 0) {/* TODO - fix! */
s = CODESET_LIST;
do {
++codeset; /* Increment codeset first. */
- if (!strcmp(CODESET_LIST+*s, p+6)) {
+ if (!strcmp((char*) CODESET_LIST + *s, p + 6)) {
goto FIND_LANG_CULT;
}
} while (*++s);
@@ -1159,7 +1128,7 @@ static int find_locale(int category_mask, const char *p,
do { /* TODO -- do a binary search? */
/* TODO -- fix gen_mmap!*/
++lang_cult; /* Increment first since C/POSIX is 0. */
- if (!strncmp(s,p,5)) { /* Found a matching locale name; */
+ if (!strncmp((char*) s, p, 5)) { /* Found a matching locale name; */
goto FIND_LOCALE;
}
s += 5;
@@ -1217,7 +1186,8 @@ static unsigned char *composite_locale(int category_mask, const char *locale,
t = strtok_r(buf, "=", &e); /* This can't fail because of strchr test above. */
do {
c = 0;
- while (strcmp(CATEGORY_NAMES + (int) CATEGORY_NAMES[c], t)) {
+ /* CATEGORY_NAMES is unsigned char* */
+ while (strcmp((char*) CATEGORY_NAMES + (int) CATEGORY_NAMES[c], t)) {
if (++c == LC_ALL) { /* Unknown category name! */
return NULL;
}
@@ -1242,7 +1212,7 @@ static unsigned char *composite_locale(int category_mask, const char *locale,
__locale_t newlocale(int category_mask, const char *locale, __locale_t base)
{
- const unsigned char *p;
+ const char *p;
int i, j, k;
unsigned char new_selector[LOCALE_SELECTOR_SIZE];
@@ -1250,10 +1220,10 @@ __locale_t newlocale(int category_mask, const char *locale, __locale_t base)
category_mask = LC_ALL_MASK;
}
- if (!locale || (((unsigned int)(category_mask)) > LC_ALL_MASK)) {
- INVALID:
+ if (!locale || ((unsigned)(category_mask) > LC_ALL_MASK)) {
+ INVALID:
__set_errno(EINVAL);
- return NULL; /* No locale or illegal/unsupported category. */
+ return NULL; /* No locale or illegal/unsupported category. */
}
#ifdef __UCLIBC_MJN3_ONLY__
@@ -1262,11 +1232,13 @@ __locale_t newlocale(int category_mask, const char *locale, __locale_t base)
strcpy((char *) new_selector,
(base ? (char *) base->cur_locale : C_LOCALE_SELECTOR));
- if (!*locale) { /* locale == "", so check environment. */
-#ifndef __UCLIBC_HAS_THREADS__
- static /* If no threads, then envstr can be static. */
-#endif /* __UCLIBC_HAS_THREADS__ */
- const char *envstr[4] = { "LC_ALL", NULL, "LANG", posix };
+ if (!locale[0]) { /* locale == "", so check environment. */
+ const char *envstr[4];
+
+ envstr[0] = "LC_ALL";
+ envstr[1] = NULL;
+ envstr[2] = "LANG";
+ envstr[3] = posix;
i = 1;
k = 0;
@@ -1275,12 +1247,16 @@ __locale_t newlocale(int category_mask, const char *locale, __locale_t base)
/* Note: SUSv3 doesn't define a fallback mechanism here.
* So, if LC_ALL is invalid, we do _not_ continue trying
* the other environment vars. */
- envstr[1] = CATEGORY_NAMES + CATEGORY_NAMES[k];
+ envstr[1] = (char*) CATEGORY_NAMES + CATEGORY_NAMES[k];
j = 0;
- do {
+ while (1) {
p = envstr[j];
- } while ((++j < 4) && (!(p = getenv(p)) || !*p));
-
+ if (++j >= 4)
+ break; /* now p == "POSIX" */
+ p = getenv(p);
+ if (p && p[0])
+ break;
+ };
/* The user set something... is it valid? */
/* Note: Since we don't support user-supplied locales and
@@ -1313,9 +1289,9 @@ __locale_t newlocale(int category_mask, const char *locale, __locale_t base)
}
#else
if (!base) {
- if ((base = malloc(sizeof(__uclibc_locale_t))) == NULL) {
+ base = calloc(1, sizeof(struct __uclibc_locale_struct));
+ if (base == NULL)
return base;
- }
_locale_init_l(base);
}
@@ -1324,13 +1300,14 @@ __locale_t newlocale(int category_mask, const char *locale, __locale_t base)
return base;
}
+#ifdef __UCLIBC_HAS_XLOCALE__
libc_hidden_def(newlocale)
+#endif
#endif
/**********************************************************************/
#ifdef L_duplocale
-libc_hidden_proto(duplocale)
#ifdef __UCLIBC_MJN3_ONLY__
#warning REMINDER: When we allocate ctype tables, remember to dup them.
@@ -1344,12 +1321,12 @@ __locale_t duplocale(__locale_t dataset)
assert(dataset != LC_GLOBAL_LOCALE);
- if ((r = malloc(sizeof(__uclibc_locale_t))) != NULL) {
- n = 2*dataset->collate.max_col_index+2;
- if ((i2w = calloc(n, sizeof(uint16_t)))
- != NULL
- ) {
- memcpy(r, dataset, sizeof(__uclibc_locale_t));
+ r = malloc(sizeof(struct __uclibc_locale_struct));
+ if (r != NULL) {
+ n = 2 * dataset->collate.max_col_index + 2;
+ i2w = calloc(n, sizeof(uint16_t));
+ if (i2w != NULL) {
+ memcpy(r, dataset, sizeof(struct __uclibc_locale_struct));
r->collate.index2weight = i2w;
memcpy(i2w, dataset->collate.index2weight, n * sizeof(uint16_t));
} else {
@@ -1359,7 +1336,6 @@ __locale_t duplocale(__locale_t dataset)
}
return r;
}
-libc_hidden_def(duplocale)
#endif
/**********************************************************************/
@@ -1382,7 +1358,6 @@ void freelocale(__locale_t dataset)
/**********************************************************************/
#ifdef L_uselocale
-libc_hidden_proto(uselocale)
__locale_t uselocale(__locale_t dataset)
{
__locale_t old;
@@ -1416,8 +1391,9 @@ libc_hidden_def(uselocale)
__locale_t weak_const_function __curlocale(void)
{
- return __curlocale_var; /* This is overriden by the thread version. */
+ return __curlocale_var; /* This is overriden by the thread version. */
}
+libc_hidden_weak(__curlocale)
__locale_t weak_function __curlocale_set(__locale_t newloc)
{
@@ -1426,6 +1402,7 @@ __locale_t weak_function __curlocale_set(__locale_t newloc)
__curlocale_var = newloc;
return oldloc;
}
+libc_hidden_weak(__curlocale_set)
#endif