newlib-cygwin/newlib/libc/locale/locale.c

302 lines
7.7 KiB
C

/*
FUNCTION
<<setlocale>>, <<localeconv>>---select or query locale
INDEX
setlocale
INDEX
localeconv
INDEX
_setlocale_r
INDEX
_localeconv_r
ANSI_SYNOPSIS
#include <locale.h>
char *setlocale(int <[category]>, const char *<[locale]>);
lconv *localeconv(void);
char *_setlocale_r(void *<[reent]>,
int <[category]>, const char *<[locale]>);
lconv *_localeconv_r(void *<[reent]>);
TRAD_SYNOPSIS
#include <locale.h>
char *setlocale(<[category]>, <[locale]>)
int <[category]>;
char *<[locale]>;
lconv *localeconv();
char *_setlocale_r(<[reent]>, <[category]>, <[locale]>)
char *<[reent]>;
int <[category]>;
char *<[locale]>;
lconv *_localeconv_r(<[reent]>);
char *<[reent]>;
DESCRIPTION
<<setlocale>> is the facility defined by ANSI C to condition the
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">>.)
If you use <<NULL>> as the <[locale]> argument, <<setlocale>> returns
a pointer to the string representing the current locale (always
<<"C">> in this implementation). The acceptable values for
<[category]> are defined in `<<locale.h>>' as macros beginning with
<<"LC_">>, but this implementation does not check the values you pass
in the <[category]> argument.
<<localeconv>> returns a pointer to a structure (also defined in
`<<locale.h>>') describing the locale-specific conventions currently
in effect.
<<_localeconv_r>> and <<_setlocale_r>> are reentrant versions of
<<localeconv>> and <<setlocale>> respectively. The extra argument
<[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>>.
<<localeconv>> returns a pointer to a structure of type <<lconv>>,
which describes the formatting and collating conventions in effect (in
this implementation, always those of the C locale).
PORTABILITY
ANSI C requires <<setlocale>>, but the only locale required across all
implementations is the C locale.
No supporting OS subroutines are required.
*/
/*
* setlocale, localeconv : internationalize your locale.
* (Only "C" or null supported).
*/
#include <newlib.h>
#include <locale.h>
#include <string.h>
#include <limits.h>
#include <reent.h>
#ifdef __CYGWIN__
int __declspec(dllexport) __mb_cur_max = 1;
#else
int __mb_cur_max = 1;
#endif
int __nlocale_changed = 0;
int __mlocale_changed = 0;
char *_PathLocale = NULL;
static _CONST struct lconv lconv =
{
".", "", "", "", "", "", "", "", "", "",
CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX,
CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX,
};
char * _EXFUN(__locale_charset,(_VOID));
static char *charset = "ISO-8859-1";
char __lc_ctype[12] = "C";
char *
_DEFUN(_setlocale_r, (p, category, locale),
struct _reent *p _AND
int category _AND
_CONST char *locale)
{
#ifndef _MB_CAPABLE
if (locale)
{
if (strcmp (locale, "C") && strcmp (locale, ""))
return 0;
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";
if (locale)
{
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;
}
}
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;
}
else
{
if (category == LC_CTYPE)
return __lc_ctype;
else if (category == LC_MESSAGES)
return lc_messages;
}
return "C";
#endif
}
char *
_DEFUN_VOID(__locale_charset)
{
return charset;
}
struct lconv *
_DEFUN(_localeconv_r, (data),
struct _reent *data)
{
return (struct lconv *) &lconv;
}
#ifndef _REENT_ONLY
char *
_DEFUN(setlocale, (category, locale),
int category _AND
_CONST char *locale)
{
return _setlocale_r (_REENT, category, locale);
}
struct lconv *
_DEFUN_VOID(localeconv)
{
return _localeconv_r (_REENT);
}
#endif