* libc/locale/locale.c (_setlocale_r): New implementation based on

FreeBSD's setlocale.
	(currentlocale): New helper function.
	(loadlocale): Ditto.
	(__locale_charset): New function.
	(__locale_msgcharset): Rename from __locale_charset.
	* libc/ctype/local.h (__lc_ctype): Remove declaration.
	(__locale_charset): Declare.
	* libc/ctype/iswalpha.c (iswalpha): Call __locale_charset instead of
	using __lc_ctype directly.  Only compare against the charset alone.
	* libc/ctype/iswblank.c (iswblank): Ditto.
	* libc/ctype/iswcntrl.c (iswcntrl): Ditto.
	* libc/ctype/iswprint.c (iswprint): Ditto.
	* libc/ctype/iswpunct.c (iswpunct): Ditto.
	* libc/ctype/iswspace.c (iswspace): Ditto.
	* libc/ctype/towlower.c (towlower): Ditto.
	* libc/ctype/towupper.c (towupper): Ditto.
	* libc/stdlib/mbtowc_r.c (_mbtowc_r): Ditto.
	* libc/stdlib/wctomb_r.c (_wctomb_r): Ditto.
	* libc/sys/linux/intl/loadmsgcat.c (_nl_init_domain_conv): Call
	__locale_msgcharset instead of __locale_charset.
This commit is contained in:
Corinna Vinschen 2009-03-03 09:28:45 +00:00
parent e81ae92910
commit d6cd9169dc
14 changed files with 456 additions and 244 deletions

View File

@ -1,3 +1,27 @@
2009-03-03 Corinna Vinschen <corinna@vinschen.de>
* libc/locale/locale.c (_setlocale_r): New implementation based on
FreeBSD's setlocale.
(currentlocale): New helper function.
(loadlocale): Ditto.
(__locale_charset): New function.
(__locale_msgcharset): Rename from __locale_charset.
* libc/ctype/local.h (__lc_ctype): Remove declaration.
(__locale_charset): Declare.
* libc/ctype/iswalpha.c (iswalpha): Call __locale_charset instead of
using __lc_ctype directly. Only compare against the charset alone.
* libc/ctype/iswblank.c (iswblank): Ditto.
* libc/ctype/iswcntrl.c (iswcntrl): Ditto.
* libc/ctype/iswprint.c (iswprint): Ditto.
* libc/ctype/iswpunct.c (iswpunct): Ditto.
* libc/ctype/iswspace.c (iswspace): Ditto.
* libc/ctype/towlower.c (towlower): Ditto.
* libc/ctype/towupper.c (towupper): Ditto.
* libc/stdlib/mbtowc_r.c (_mbtowc_r): Ditto.
* libc/stdlib/wctomb_r.c (_wctomb_r): Ditto.
* libc/sys/linux/intl/loadmsgcat.c (_nl_init_domain_conv): Call
__locale_msgcharset instead of __locale_charset.
2009-03-02 Jeff Johnston <jjohnstn@redhat.com>
* libc/stdlib/wctomb_r.c (_wctomb_r): When checking single-byte
@ -33,8 +57,7 @@
2009-02-25 Corinna Vinschen <corinna@vinschen.de>
* libc/stdlib/mbtowc_r.c (_mbtowc_r): Remove conversion of 5 and 6
byte UTF-8
sequences since they are invalid in the Unicode standard.
byte UTF-8 sequences since they are invalid in the Unicode standard.
Handle surrogate pairs in case of wchar_t == UTF-16.
* libc/stdlib/wctomb_r.c (_wctomb_r): Don't convert invalid Unicode
wchar_t values beyond 0x10ffff into UTF-8 chars. Handle surrogate

View File

@ -69,29 +69,25 @@ No supporting OS subroutines are required.
int
_DEFUN(iswalpha,(c), wint_t c)
{
int unicode = 0;
if (__lc_ctype[0] == 'C' && __lc_ctype[1] == '\0')
{
unicode = 0;
/* fall-through */
}
#ifdef _MB_CAPABLE
else if (!strcmp (__lc_ctype, "C-JIS"))
int unicode = 0;
if (!strcmp (__locale_charset (), "JIS"))
{
c = __jp2uc (c, JP_JIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-SJIS"))
else if (!strcmp (__locale_charset (), "SJIS"))
{
c = __jp2uc (c, JP_SJIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-EUCJP"))
else if (!strcmp (__locale_charset (), "EUCJP"))
{
c = __jp2uc (c, JP_EUCJP);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-UTF-8"))
else if (!strcmp (__locale_charset (), "UTF-8"))
{
unicode = 1;
}

View File

@ -65,29 +65,25 @@ No supporting OS subroutines are required.
int
_DEFUN(iswblank,(c), wint_t c)
{
int unicode = 0;
if (__lc_ctype[0] == 'C' && __lc_ctype[1] == '\0')
{
unicode = 0;
/* fall-through */
}
#ifdef _MB_CAPABLE
else if (!strcmp (__lc_ctype, "C-JIS"))
int unicode = 0;
if (!strcmp (__locale_charset (), "JIS"))
{
c = __jp2uc (c, JP_JIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-SJIS"))
else if (!strcmp (__locale_charset (), "SJIS"))
{
c = __jp2uc (c, JP_SJIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-EUCJP"))
else if (!strcmp (__locale_charset (), "EUCJP"))
{
c = __jp2uc (c, JP_EUCJP);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-UTF-8"))
else if (!strcmp (__locale_charset (), "UTF-8"))
{
unicode = 1;
}

View File

@ -65,29 +65,25 @@ No supporting OS subroutines are required.
int
_DEFUN(iswcntrl,(c), wint_t c)
{
int unicode = 0;
if (__lc_ctype[0] == 'C' && __lc_ctype[1] == '\0')
{
unicode = 0;
/* fall-through */
}
#ifdef _MB_CAPABLE
else if (!strcmp (__lc_ctype, "C-JIS"))
int unicode = 0;
if (!strcmp (__locale_charset (), "JIS"))
{
c = __jp2uc (c, JP_JIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-SJIS"))
else if (!strcmp (__locale_charset (), "SJIS"))
{
c = __jp2uc (c, JP_SJIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-EUCJP"))
else if (!strcmp (__locale_charset (), "EUCJP"))
{
c = __jp2uc (c, JP_EUCJP);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-UTF-8"))
else if (!strcmp (__locale_charset (), "UTF-8"))
{
unicode = 1;
}

View File

@ -69,29 +69,25 @@ No supporting OS subroutines are required.
int
_DEFUN(iswprint,(c), wint_t c)
{
int unicode = 0;
if (__lc_ctype[0] == 'C' && __lc_ctype[1] == '\0')
{
unicode = 0;
/* fall-through */
}
#ifdef _MB_CAPABLE
else if (!strcmp (__lc_ctype, "C-JIS"))
int unicode = 0;
if (!strcmp (__locale_charset (), "JIS"))
{
c = __jp2uc (c, JP_JIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-SJIS"))
else if (!strcmp (__locale_charset (), "SJIS"))
{
c = __jp2uc (c, JP_SJIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-EUCJP"))
else if (!strcmp (__locale_charset (), "EUCJP"))
{
c = __jp2uc (c, JP_EUCJP);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-UTF-8"))
else if (!strcmp (__locale_charset (), "UTF-8"))
{
unicode = 1;
}

View File

@ -69,29 +69,25 @@ No supporting OS subroutines are required.
int
_DEFUN(iswpunct,(c), wint_t c)
{
int unicode = 0;
if (__lc_ctype[0] == 'C' && __lc_ctype[1] == '\0')
{
unicode = 0;
/* fall-through */
}
#ifdef _MB_CAPABLE
else if (!strcmp (__lc_ctype, "C-JIS"))
int unicode = 0;
if (!strcmp (__locale_charset (), "JIS"))
{
c = __jp2uc (c, JP_JIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-SJIS"))
else if (!strcmp (__locale_charset (), "SJIS"))
{
c = __jp2uc (c, JP_SJIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-EUCJP"))
else if (!strcmp (__locale_charset (), "EUCJP"))
{
c = __jp2uc (c, JP_EUCJP);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-UTF-8"))
else if (!strcmp (__locale_charset (), "UTF-8"))
{
unicode = 1;
}

View File

@ -65,29 +65,25 @@ No supporting OS subroutines are required.
int
_DEFUN(iswspace,(c), wint_t c)
{
int unicode = 0;
if (__lc_ctype[0] == 'C' && __lc_ctype[1] == '\0')
{
unicode = 0;
/* fall-through */
}
#ifdef _MB_CAPABLE
else if (!strcmp (__lc_ctype, "C-JIS"))
int unicode = 0;
if (!strcmp (__locale_charset (), "JIS"))
{
c = __jp2uc (c, JP_JIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-SJIS"))
else if (!strcmp (__locale_charset (), "SJIS"))
{
c = __jp2uc (c, JP_SJIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-EUCJP"))
else if (!strcmp (__locale_charset (), "EUCJP"))
{
c = __jp2uc (c, JP_EUCJP);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-UTF-8"))
else if (!strcmp (__locale_charset (), "UTF-8"))
{
unicode = 1;
}

View File

@ -20,7 +20,7 @@
#define WC_UPPER 11
#define WC_XDIGIT 12
extern char __lc_ctype[12];
extern char *__locale_charset ();
/* Japanese encoding types supported */
#define JP_JIS 1

View File

@ -69,30 +69,25 @@ No supporting OS subroutines are required.
wint_t
_DEFUN(towlower,(c), wint_t c)
{
#ifdef _MB_CAPABLE
int unicode = 0;
if (__lc_ctype[0] == 'C' && __lc_ctype[1] == '\0')
{
unicode = 0;
/* fall-through */
}
#ifdef _MB_CAPABLE
else if (!strcmp (__lc_ctype, "C-JIS"))
if (!strcmp (__locale_charset (), "JIS"))
{
c = __jp2uc (c, JP_JIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-SJIS"))
else if (!strcmp (__locale_charset (), "SJIS"))
{
c = __jp2uc (c, JP_SJIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-EUCJP"))
else if (!strcmp (__locale_charset (), "EUCJP"))
{
c = __jp2uc (c, JP_EUCJP);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-UTF-8"))
else if (!strcmp (__locale_charset (), "UTF-8"))
{
unicode = 1;
}

View File

@ -69,30 +69,25 @@ No supporting OS subroutines are required.
wint_t
_DEFUN(towupper,(c), wint_t c)
{
#ifdef _MB_CAPABLE
int unicode = 0;
if (__lc_ctype[0] == 'C' && __lc_ctype[1] == '\0')
{
unicode = 0;
/* fall-through */
}
#ifdef _MB_CAPABLE
else if (!strcmp (__lc_ctype, "C-JIS"))
if (!strcmp (__locale_charset (), "JIS"))
{
c = __jp2uc (c, JP_JIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-SJIS"))
else if (!strcmp (__locale_charset (), "SJIS"))
{
c = __jp2uc (c, JP_SJIS);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-EUCJP"))
else if (!strcmp (__locale_charset (), "EUCJP"))
{
c = __jp2uc (c, JP_EUCJP);
unicode = 1;
}
else if (!strcmp (__lc_ctype, "C-UTF-8"))
else if (!strcmp (__locale_charset (), "UTF-8"))
{
unicode = 1;
}

View File

@ -42,13 +42,16 @@ execution environment for international collating and formatting
information; <<localeconv>> reports on the settings of the current
locale.
This is a minimal implementation, supporting only the required <<"C">>
value for <[locale]>; strings representing other locales are not
honored unless _MB_CAPABLE is defined in which case three new
extensions are allowed for LC_CTYPE or LC_MESSAGES only: <<"C-JIS">>,
<<"C-EUCJP">>, <<"C-SJIS">>, or <<"C-ISO-8859-1">>. (<<"">> is
also accepted; it represents the default locale
for an implementation, here equivalent to <<"C">>.)
This is a minimal implementation, supporting only the required <<"POSIX">>
and <<"C">> values for <[locale]>; strings representing other locales are not
honored unless _MB_CAPABLE is defined in which case POSIX locale strings
are allowed, plus five extensions supported for backward compatibility with
older implementations using newlib: <<"C-UTF-8">>, <<"C-JIS">>, <<"C-EUCJP">>,
<<"C-SJIS">>, or <<"C-ISO-8859-x">> with 1 <= x <= 15. Even when using
POSIX locale strings, the only charsets allowed are <<"UTF-8">>, <<"JIS">>,
<<"EUCJP">>, <<"SJIS">>, or <<"ISO-8859-x">> with 1 <= x <= 15. (<<"">> is
also accepted; if given, the settings are read from the corresponding
LC_* environment variables and $LANG according to POSIX rules.
If you use <<NULL>> as the <[locale]> argument, <<setlocale>> returns
a pointer to the string representing the current locale (always
@ -66,9 +69,13 @@ in effect.
<[reent]> is a pointer to a reentrancy structure.
RETURNS
<<setlocale>> returns either a pointer to a string naming the locale
currently in effect (always <<"C">> for this implementation, or, if
the locale request cannot be honored, <<NULL>>.
A successful call to <<setlocale>> returns a pointer to a string
associated with the specified category for the new locale. The string
returned by <<setlocale>> is such that a subsequent call using that
string will restore that category (or all categories in case of LC_ALL),
to that state. The application shall not modify the string returned
which may be overwritten by a subsequent call to <<setlocale>>.
On error, <<setlocale>> returns <<NULL>>.
<<localeconv>> returns a pointer to a structure of type <<lconv>>,
which describes the formatting and collating conventions in effect (in
@ -81,16 +88,50 @@ implementations is the C locale.
No supporting OS subroutines are required.
*/
/* Parts of this code are originally taken from FreeBSD. */
/*
* setlocale, localeconv : internationalize your locale.
* (Only "C" or null supported).
* Copyright (c) 1996 - 2002 FreeBSD Project
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Paul Borman at Krystal Technologies.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <newlib.h>
#include <errno.h>
#include <locale.h>
#include <string.h>
#include <limits.h>
#include <reent.h>
#include <stdlib.h>
#define _LC_LAST 7
#define ENCODING_LEN 31
#ifdef __CYGWIN__
int __declspec(dllexport) __mb_cur_max = 1;
@ -109,11 +150,48 @@ static _CONST struct lconv lconv =
CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX,
};
#ifdef _MB_CAPABLE
/*
* Category names for getenv()
*/
static char *categories[_LC_LAST] = {
"LC_ALL",
"LC_COLLATE",
"LC_CTYPE",
"LC_MONETARY",
"LC_NUMERIC",
"LC_TIME",
"LC_MESSAGES",
};
char * _EXFUN(__locale_charset,(_VOID));
/*
* Current locales for each category
*/
static char current_categories[_LC_LAST][ENCODING_LEN + 1] = {
"C",
"C",
"C",
"C",
"C",
"C",
"C",
};
static char *charset = "ISO-8859-1";
char __lc_ctype[12] = "C";
/*
* The locales we are going to try and load
*/
static char new_categories[_LC_LAST][ENCODING_LEN + 1];
static char saved_categories[_LC_LAST][ENCODING_LEN + 1];
static char current_locale_string[_LC_LAST * (ENCODING_LEN + 1/*"/"*/ + 1)];
static char *currentlocale(void);
static char *loadlocale(struct _reent *, int);
static const char *__get_locale_env(struct _reent *, int);
#endif
static char lc_ctype_charset[ENCODING_LEN + 1] = "ISO-8859-1";
static char lc_message_charset[ENCODING_LEN + 1] = "ISO-8859-1";
char *
_DEFUN(_setlocale_r, (p, category, locale),
@ -124,154 +202,303 @@ _DEFUN(_setlocale_r, (p, category, locale),
#ifndef _MB_CAPABLE
if (locale)
{
if (strcmp (locale, "C") && strcmp (locale, ""))
return 0;
if (strcmp (locale, "POSIX") && strcmp (locale, "C")
&& strcmp (locale, ""))
return NULL;
p->_current_category = category;
p->_current_locale = locale;
}
return "C";
#else
static char last_lc_ctype[12] = "C";
static char lc_messages[12] = "C";
static char last_lc_messages[12] = "C";
int i, j, len, saverr;
const char *env, *r;
if (locale)
if (category < LC_ALL || category >= _LC_LAST)
{
char *locale_name = (char *)locale;
if (category != LC_CTYPE && category != LC_MESSAGES)
{
if (strcmp (locale, "C") && strcmp (locale, ""))
return 0;
if (category == LC_ALL)
{
strcpy (last_lc_ctype, __lc_ctype);
strcpy (__lc_ctype, "C");
strcpy (last_lc_messages, lc_messages);
strcpy (lc_messages, "C");
__mb_cur_max = 1;
}
}
p->_errno = EINVAL;
return NULL;
}
if (locale == NULL)
return category != LC_ALL ? current_categories[category] : currentlocale();
/*
* Default to the current locale for everything.
*/
for (i = 1; i < _LC_LAST; ++i)
strcpy (new_categories[i], current_categories[i]);
/*
* Now go fill up new_categories from the locale argument
*/
if (!*locale)
{
if (category == LC_ALL)
{
for (i = 1; i < _LC_LAST; ++i)
{
env = __get_locale_env (p, i);
if (strlen (env) > ENCODING_LEN)
{
p->_errno = EINVAL;
return NULL;
}
strcpy (new_categories[i], env);
}
}
else
{
if (locale[0] == 'C' && locale[1] == '-')
{
switch (locale[2])
{
case 'U':
if (strcmp (locale, "C-UTF-8"))
return 0;
break;
case 'J':
if (strcmp (locale, "C-JIS"))
return 0;
break;
case 'E':
if (strcmp (locale, "C-EUCJP"))
return 0;
break;
case 'S':
if (strcmp (locale, "C-SJIS"))
return 0;
break;
case 'I':
if (strcmp (locale, "C-ISO-8859-1"))
return 0;
break;
default:
return 0;
}
}
else
{
if (strcmp (locale, "C") && strcmp (locale, ""))
return 0;
locale_name = "C"; /* C is always the default locale */
}
if (category == LC_CTYPE)
{
strcpy (last_lc_ctype, __lc_ctype);
strcpy (__lc_ctype, locale_name);
__mb_cur_max = 1;
if (locale[1] == '-')
{
switch (locale[2])
{
case 'U':
__mb_cur_max = 6;
break;
case 'J':
__mb_cur_max = 8;
break;
case 'E':
__mb_cur_max = 2;
break;
case 'S':
__mb_cur_max = 2;
break;
case 'I':
default:
__mb_cur_max = 1;
}
}
}
else
{
strcpy (last_lc_messages, lc_messages);
strcpy (lc_messages, locale_name);
charset = "ISO-8859-1";
if (locale[1] == '-')
{
switch (locale[2])
{
case 'U':
charset = "UTF-8";
break;
case 'J':
charset = "JIS";
break;
case 'E':
charset = "EUCJP";
break;
case 'S':
charset = "SJIS";
break;
case 'I':
charset = "ISO-8859-1";
break;
default:
return 0;
}
}
}
}
p->_current_category = category;
p->_current_locale = locale;
if (category == LC_CTYPE)
return last_lc_ctype;
else if (category == LC_MESSAGES)
return last_lc_messages;
{
env = __get_locale_env (p, category);
if (strlen (env) > ENCODING_LEN)
{
p->_errno = EINVAL;
return NULL;
}
strcpy (new_categories[category], env);
}
}
else if (category != LC_ALL)
{
if (strlen (locale) > ENCODING_LEN)
{
p->_errno = EINVAL;
return NULL;
}
strcpy (new_categories[category], locale);
}
else
{
if (category == LC_CTYPE)
return __lc_ctype;
else if (category == LC_MESSAGES)
return lc_messages;
if ((r = strchr (locale, '/')) == NULL)
{
if (strlen (locale) > ENCODING_LEN)
{
p->_errno = EINVAL;
return NULL;
}
for (i = 1; i < _LC_LAST; ++i)
strcpy (new_categories[i], locale);
}
else
{
for (i = 1; r[1] == '/'; ++r)
;
if (!r[1])
{
p->_errno = EINVAL;
return NULL; /* Hmm, just slashes... */
}
do
{
if (i == _LC_LAST)
break; /* Too many slashes... */
if ((len = r - locale) > ENCODING_LEN)
{
p->_errno = EINVAL;
return NULL;
}
strlcpy (new_categories[i], locale, len + 1);
i++;
while (*r == '/')
r++;
locale = r;
while (*r && *r != '/')
r++;
}
while (*locale);
while (i < _LC_LAST)
{
strcpy (new_categories[i], new_categories[i-1]);
i++;
}
}
}
return "C";
if (category != LC_ALL)
return loadlocale (p, category);
for (i = 1; i < _LC_LAST; ++i)
{
strcpy (saved_categories[i], current_categories[i]);
if (loadlocale (p, i) == NULL)
{
saverr = p->_errno;
for (j = 1; j < i; j++)
{
strcpy (new_categories[j], saved_categories[j]);
if (loadlocale (p, j) == NULL)
{
strcpy (new_categories[j], "C");
loadlocale (p, j);
}
}
p->_errno = saverr;
return NULL;
}
}
return currentlocale ();
#endif
}
#ifdef _MB_CAPABLE
static char *
currentlocale()
{
int i;
(void)strcpy(current_locale_string, current_categories[1]);
for (i = 2; i < _LC_LAST; ++i)
if (strcmp(current_categories[1], current_categories[i])) {
for (i = 2; i < _LC_LAST; ++i) {
(void)strcat(current_locale_string, "/");
(void)strcat(current_locale_string,
current_categories[i]);
}
break;
}
return (current_locale_string);
}
#endif
#ifdef _MB_CAPABLE
static char *
loadlocale(struct _reent *p, int category)
{
/* At this point a full-featured system would just load the locale
specific data from the locale files.
What we do here for now is to check the incoming string for correctness.
The string must be in one of the allowed locale strings, either
one in POSIX-style, or one in the old newlib style to maintain
backward compatibility. If the local string is correct, the charset
is extracted and stored in lc_ctype_charset or lc_message_charset
dependent on the cateogry. */
char *locale = new_categories[category];
char charset[ENCODING_LEN + 1];
unsigned long val;
char *end;
int mbc_max;
/* "POSIX" is translated to "C", as on Linux. */
if (!strcmp (locale, "POSIX"))
strcpy (locale, "C");
if (!strcmp (locale, "C")) /* Default "C" locale */
strcpy (charset, "ISO-8859-1");
else if (locale[0] == 'C' && locale[1] == '-') /* Old newlib style */
strcpy (charset, locale + 2);
else /* POSIX style */
{
char *c = locale;
/* Don't use ctype macros here, they might be localized. */
/* Language */
if (c[0] <= 'a' || c[0] >= 'z'
|| c[1] <= 'a' || c[1] >= 'z')
return NULL;
c += 2;
if (c[0] == '_')
{
/* Territory */
++c;
if (c[0] <= 'A' || c[0] >= 'Z'
|| c[1] <= 'A' || c[1] >= 'Z')
return NULL;
c += 2;
}
if (c[0] == '.')
{
/* Charset */
strcpy (charset, c + 1);
if ((c = strchr (charset, '@')))
/* Strip off modifier */
*c = '\0';
}
else if (c[0] == '\0' || c[0] == '@')
/* End of string or just a modifier */
strcpy (charset, "ISO-8859-1");
else
/* Invalid string */
return NULL;
}
/* We only support this subset of charsets. */
switch (charset[0])
{
case 'U':
if (strcmp (charset, "UTF-8"))
return NULL;
mbc_max = 6;
break;
case 'J':
if (strcmp (charset, "JIS"))
return NULL;
mbc_max = 8;
break;
case 'E':
if (strcmp (charset, "EUCJP"))
return NULL;
mbc_max = 2;
break;
case 'S':
if (strcmp (charset, "SJIS"))
return NULL;
mbc_max = 2;
break;
case 'I':
default:
/* Must be exactly one of ISO-8859-1, [...] ISO-8859-15. */
if (strncmp (charset, "ISO-8859-", 9))
return NULL;
val = strtol (charset + 9, &end, 10);
if (val < 1 || val > 15 || *end)
return NULL;
mbc_max = 1;
break;
}
if (category == LC_CTYPE)
{
strcpy (lc_ctype_charset, charset);
__mb_cur_max = mbc_max;
}
else if (category == LC_MESSAGES)
strcpy (lc_message_charset, charset);
p->_current_category = category;
p->_current_locale = locale;
return strcpy(current_categories[category], new_categories[category]);
}
static const char *
__get_locale_env(struct _reent *p, int category)
{
const char *env;
/* 1. check LC_ALL. */
env = _getenv_r (p, categories[0]);
/* 2. check LC_* */
if (env == NULL || !*env)
env = _getenv_r (p, categories[category]);
/* 3. check LANG */
if (env == NULL || !*env)
env = _getenv_r (p, "LANG");
/* 4. if none is set, fall to "C" */
if (env == NULL || !*env)
env = "C";
return env;
}
#endif
char *
_DEFUN_VOID(__locale_charset)
{
return charset;
return lc_ctype_charset;
}
char *
_DEFUN_VOID(__locale_msgcharset)
{
return lc_message_charset;
}
struct lconv *

View File

@ -45,8 +45,6 @@ static JIS_ACTION JIS_action_table[JIS_S_NUM][JIS_C_NUM] = {
/* we override the mbstate_t __count field for more complex encodings and use it store a state value */
#define __state __count
extern char __lc_ctype[12];
int
_DEFUN (_mbtowc_r, (r, pwc, s, n, state),
struct _reent *r _AND
@ -65,9 +63,9 @@ _DEFUN (_mbtowc_r, (r, pwc, s, n, state),
return -2;
#ifdef _MB_CAPABLE
if (strlen (__lc_ctype) <= 1)
if (strlen (__locale_charset ()) <= 1)
{ /* fall-through */ }
else if (!strcmp (__lc_ctype, "C-UTF-8"))
else if (!strcmp (__locale_charset (), "UTF-8"))
{
int ch;
int i = 0;
@ -221,7 +219,7 @@ _DEFUN (_mbtowc_r, (r, pwc, s, n, state),
else
return -1;
}
else if (!strcmp (__lc_ctype, "C-SJIS"))
else if (!strcmp (__locale_charset (), "SJIS"))
{
int ch;
int i = 0;
@ -251,7 +249,7 @@ _DEFUN (_mbtowc_r, (r, pwc, s, n, state),
return -1;
}
}
else if (!strcmp (__lc_ctype, "C-EUCJP"))
else if (!strcmp (__locale_charset (), "EUCJP"))
{
int ch;
int i = 0;
@ -281,7 +279,7 @@ _DEFUN (_mbtowc_r, (r, pwc, s, n, state),
return -1;
}
}
else if (!strcmp (__lc_ctype, "C-JIS"))
else if (!strcmp (__locale_charset (), "JIS"))
{
JIS_STATE curr_state;
JIS_ACTION action;

View File

@ -8,8 +8,6 @@
/* for some conversions, we use the __count field as a place to store a state value */
#define __state __count
extern char __lc_ctype[12];
int
_DEFUN (_wctomb_r, (r, s, wchar, state),
struct _reent *r _AND
@ -22,9 +20,9 @@ _DEFUN (_wctomb_r, (r, s, wchar, state),
is 4, as is the case on cygwin. */
wint_t wchar = _wchar;
if (strlen (__lc_ctype) <= 1)
if (strlen (__locale_charset ()) <= 1)
{ /* fall-through */ }
else if (!strcmp (__lc_ctype, "C-UTF-8"))
else if (!strcmp (__locale_charset (), "UTF-8"))
{
if (s == NULL)
return 0; /* UTF-8 encoding is not state-dependent */
@ -106,7 +104,7 @@ _DEFUN (_wctomb_r, (r, s, wchar, state),
return -1;
}
}
else if (!strcmp (__lc_ctype, "C-SJIS"))
else if (!strcmp (__locale_charset (), "SJIS"))
{
unsigned char char2 = (unsigned char)wchar;
unsigned char char1 = (unsigned char)(wchar >> 8);
@ -130,7 +128,7 @@ _DEFUN (_wctomb_r, (r, s, wchar, state),
}
}
}
else if (!strcmp (__lc_ctype, "C-EUCJP"))
else if (!strcmp (__locale_charset (), "EUCJP"))
{
unsigned char char2 = (unsigned char)wchar;
unsigned char char1 = (unsigned char)(wchar >> 8);
@ -154,7 +152,7 @@ _DEFUN (_wctomb_r, (r, s, wchar, state),
}
}
}
else if (!strcmp (__lc_ctype, "C-JIS"))
else if (!strcmp (__locale_charset (), "JIS"))
{
int cnt = 0;
unsigned char char2 = (unsigned char)wchar;

View File

@ -266,8 +266,8 @@ _nl_init_domain_conv (domain_file, domain, domainbinding)
outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
# else
# if HAVE_ICONV
extern const char *__locale_charset (void);
outcharset = __locale_charset ();
extern const char *__locale_msgcharset (void);
outcharset = __locale_msgcharset ();
# endif
# endif
}