Implement missing POSIX function nl_langinfo_l

Change nl_langinfo to nl_langinfo_l using locale given as argument.
Remove outdated TRANSITION_PERIOD_HACK.  The codeset is stored in
the locale for quite some time now.  For !MB_CAPABLE targets, just
return "US_ASCII" as codeset.

Implement nl_langinfo by calling nl_langinfo_l.  Export nl_langinfo_l
from Cygwin DLL and bump minor API version number.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2016-08-20 17:22:41 +02:00
parent 7630e38462
commit 216054fa77
4 changed files with 61 additions and 94 deletions

View File

@ -32,6 +32,9 @@
#include <newlib.h> #include <newlib.h>
#include <sys/config.h> #include <sys/config.h>
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if __POSIX_VISIBLE >= 200809
#include <sys/_locale.h>
#endif
typedef int nl_item; typedef int nl_item;
@ -310,7 +313,10 @@ enum __nl_item
}; };
__BEGIN_DECLS __BEGIN_DECLS
char *nl_langinfo(nl_item); char *nl_langinfo (nl_item);
#if __POSIX_VISIBLE >= 200809
char *nl_langinfo_l (nl_item, locale_t);
#endif
__END_DECLS __END_DECLS
#endif /* !_LANGINFO_H_ */ #endif /* !_LANGINFO_H_ */

View File

@ -34,26 +34,22 @@
#include "setlocale.h" #include "setlocale.h"
#ifndef __CYGWIN__
#define TRANSITION_PERIOD_HACK
#endif
#undef offsetoff #undef offsetoff
#define _O(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) #define _O(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
#define _NLITEM(cat,memb) { { cat:__get_current_##cat##_locale }, \ #define _NLITEM(cat,memb) { { cat:__get_##cat##_locale }, \
_O (struct lc_##cat##_T, memb) } _O (struct lc_##cat##_T, memb) }
#ifdef __HAVE_LOCALE_INFO_EXTENDED__ #ifdef __HAVE_LOCALE_INFO_EXTENDED__
static struct _nl_item_t static struct _nl_item_t
{ {
union { union {
const struct lc_ctype_T * (*ctype)(void); const struct lc_ctype_T * (*ctype)(struct __locale_t *);
const struct lc_time_T * (*time)(void); const struct lc_time_T * (*time)(struct __locale_t *);
const struct lc_numeric_T * (*numeric)(void); const struct lc_numeric_T * (*numeric)(struct __locale_t *);
const struct lc_monetary_T * (*monetary)(void); const struct lc_monetary_T * (*monetary)(struct __locale_t *);
const struct lc_messages_T * (*messages)(void); const struct lc_messages_T * (*messages)(struct __locale_t *);
void * (*base)(void); void * (*base)(struct __locale_t *);
}; };
_off_t offset; _off_t offset;
} nl_ext[] = } nl_ext[] =
@ -172,47 +168,42 @@ static struct _nl_item_t
#define _REL(BASE) ((int)item-BASE) #define _REL(BASE) ((int)item-BASE)
char * char *nl_langinfo_l (nl_item item, struct __locale_t *locale)
_DEFUN(nl_langinfo, (item),
nl_item item)
{ {
char *ret, *cs; char *ret, *cs;
#ifndef __CYGWIN__ #ifndef __CYGWIN__
char *s; char *s;
#endif #endif
static char *csym = NULL; static char *csym = NULL;
#ifdef TRANSITION_PERIOD_HACK
static char *cset = NULL;
#endif /* TRANSITION_PERIOD_HACK */
char *nptr; char *nptr;
switch (item) { switch (item) {
#ifdef __HAVE_LOCALE_INFO__ #ifdef __HAVE_LOCALE_INFO__
case _NL_MESSAGES_CODESET: case _NL_MESSAGES_CODESET:
ret = (char *) __get_current_messages_locale ()->codeset; ret = (char *) __get_messages_locale (locale)->codeset;
goto do_codeset; goto do_codeset;
#ifdef __HAVE_LOCALE_INFO_EXTENDED__ #ifdef __HAVE_LOCALE_INFO_EXTENDED__
case _NL_TIME_CODESET: case _NL_TIME_CODESET:
ret = (char *) __get_current_time_locale ()->codeset; ret = (char *) __get_time_locale (locale)->codeset;
goto do_codeset; goto do_codeset;
case _NL_NUMERIC_CODESET: case _NL_NUMERIC_CODESET:
ret = (char *) __get_current_numeric_locale ()->codeset; ret = (char *) __get_numeric_locale (locale)->codeset;
goto do_codeset; goto do_codeset;
case _NL_MONETARY_CODESET: case _NL_MONETARY_CODESET:
ret = (char *) __get_current_monetary_locale ()->codeset; ret = (char *) __get_monetary_locale (locale)->codeset;
goto do_codeset; goto do_codeset;
#ifdef __CYGWIN__ #ifdef __CYGWIN__
case _NL_COLLATE_CODESET: case _NL_COLLATE_CODESET:
{ {
ret = (char *) __get_current_collate_locale ()->codeset; ret = (char *) __get_collate_locale (locale)->codeset;
goto do_codeset; goto do_codeset;
} }
#endif /* __CYGWIN__ */ #endif /* __CYGWIN__ */
#endif /* __HAVE_LOCALE_INFO_EXTENDED__ */ #endif /* __HAVE_LOCALE_INFO_EXTENDED__ */
#endif /* __HAVE_LOCALE_INFO__ */ #endif /* __HAVE_LOCALE_INFO__ */
case CODESET: case CODESET:
#ifdef __CYGWIN__ #ifdef _MB_CAPABLE
ret = (char *) __current_locale_charset (); ret = (char *) __locale_charset (locale);
#endif #endif
do_codeset: do_codeset:
#ifdef __CYGWIN__ #ifdef __CYGWIN__
@ -255,112 +246,75 @@ do_codeset:
fine by libiconv. */ fine by libiconv. */
ret = "CP932"; ret = "CP932";
} }
#else #elif !defined (_MB_CAPABLE)
ret = ""; ret = "US-ASCII";
if ((s = setlocale(LC_CTYPE, NULL)) != NULL) {
if ((cs = strchr(s, '.')) != NULL) {
ret = cs + 1;
#ifdef TRANSITION_PERIOD_HACK
if (strncmp(ret, "ISO_", 4) == 0) {
int slen = strlen(ret);
nptr = realloc(cset, slen);
if (!nptr && cset)
free (cset);
cset = nptr;
if (cset != NULL) {
strcpy(cset, "ISO");
strcat(cset, ret + 4);
ret = cset;
} else
ret = "";
} else if (strcmp(ret, "EUC") == 0) {
if (strncmp(s, "ja_JP", 5) == 0)
ret = "eucJP";
else if (strncmp(s, "ko_KR", 5) == 0)
ret = "eucKR";
else if (strncmp(s, "zh_CN", 5) == 0)
ret = "eucCN";
} else if (strcmp(ret, "ASCII") == 0)
ret = "US-ASCII";
#endif /* TRANSITION_PERIOD_HACK */
} else if (strcmp(s, "C") == 0 ||
strcmp(s, "POSIX") == 0
#ifdef TRANSITION_PERIOD_HACK
|| strstr(s, "ASCII") != NULL
#endif /* TRANSITION_PERIOD_HACK */
)
ret = "US-ASCII";
}
#endif /* __CYGWIN__ */ #endif /* __CYGWIN__ */
break; break;
case D_T_FMT: case D_T_FMT:
ret = (char *) __get_current_time_locale()->c_fmt; ret = (char *) __get_time_locale (locale)->c_fmt;
break; break;
case D_FMT: case D_FMT:
ret = (char *) __get_current_time_locale()->x_fmt; ret = (char *) __get_time_locale (locale)->x_fmt;
break; break;
case T_FMT: case T_FMT:
ret = (char *) __get_current_time_locale()->X_fmt; ret = (char *) __get_time_locale (locale)->X_fmt;
break; break;
case T_FMT_AMPM: case T_FMT_AMPM:
ret = (char *) __get_current_time_locale()->ampm_fmt; ret = (char *) __get_time_locale (locale)->ampm_fmt;
break; break;
case AM_STR: case AM_STR:
ret = (char *) __get_current_time_locale()->am_pm[0]; ret = (char *) __get_time_locale (locale)->am_pm[0];
break; break;
case PM_STR: case PM_STR:
ret = (char *) __get_current_time_locale()->am_pm[1]; ret = (char *) __get_time_locale (locale)->am_pm[1];
break; break;
case DAY_1: case DAY_2: case DAY_3: case DAY_1: case DAY_2: case DAY_3:
case DAY_4: case DAY_5: case DAY_6: case DAY_7: case DAY_4: case DAY_5: case DAY_6: case DAY_7:
ret = (char*) __get_current_time_locale()->weekday[_REL(DAY_1)]; ret = (char*) __get_time_locale (locale)->weekday[_REL(DAY_1)];
break; break;
case ABDAY_1: case ABDAY_2: case ABDAY_3: case ABDAY_1: case ABDAY_2: case ABDAY_3:
case ABDAY_4: case ABDAY_5: case ABDAY_6: case ABDAY_7: case ABDAY_4: case ABDAY_5: case ABDAY_6: case ABDAY_7:
ret = (char*) __get_current_time_locale()->wday[_REL(ABDAY_1)]; ret = (char*) __get_time_locale (locale)->wday[_REL(ABDAY_1)];
break; break;
case MON_1: case MON_2: case MON_3: case MON_4: case MON_1: case MON_2: case MON_3: case MON_4:
case MON_5: case MON_6: case MON_7: case MON_8: case MON_5: case MON_6: case MON_7: case MON_8:
case MON_9: case MON_10: case MON_11: case MON_12: case MON_9: case MON_10: case MON_11: case MON_12:
ret = (char*) __get_current_time_locale()->month[_REL(MON_1)]; ret = (char*) __get_time_locale (locale)->month[_REL(MON_1)];
break; break;
case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4: case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4:
case ABMON_5: case ABMON_6: case ABMON_7: case ABMON_8: case ABMON_5: case ABMON_6: case ABMON_7: case ABMON_8:
case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12: case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12:
ret = (char*) __get_current_time_locale()->mon[_REL(ABMON_1)]; ret = (char*) __get_time_locale (locale)->mon[_REL(ABMON_1)];
break; break;
case ERA: case ERA:
ret = (char*) __get_current_time_locale()->era; ret = (char*) __get_time_locale (locale)->era;
break; break;
case ERA_D_FMT: case ERA_D_FMT:
ret = (char*) __get_current_time_locale()->era_d_fmt; ret = (char*) __get_time_locale (locale)->era_d_fmt;
break; break;
case ERA_D_T_FMT: case ERA_D_T_FMT:
ret = (char*) __get_current_time_locale()->era_d_t_fmt; ret = (char*) __get_time_locale (locale)->era_d_t_fmt;
break; break;
case ERA_T_FMT: case ERA_T_FMT:
ret = (char*) __get_current_time_locale()->era_t_fmt; ret = (char*) __get_time_locale (locale)->era_t_fmt;
break; break;
case ALT_DIGITS: case ALT_DIGITS:
ret = (char*) __get_current_time_locale()->alt_digits; ret = (char*) __get_time_locale (locale)->alt_digits;
break; break;
case _DATE_FMT: /* GNU extension */ case _DATE_FMT: /* GNU extension */
ret = (char*) __get_current_time_locale()->date_fmt; ret = (char*) __get_time_locale (locale)->date_fmt;
break; break;
case RADIXCHAR: case RADIXCHAR:
ret = (char*) __get_current_numeric_locale()->decimal_point; ret = (char*) __get_numeric_locale (locale)->decimal_point;
break; break;
case THOUSEP: case THOUSEP:
ret = (char*) __get_current_numeric_locale()->thousands_sep; ret = (char*) __get_numeric_locale (locale)->thousands_sep;
break; break;
case YESEXPR: case YESEXPR:
ret = (char*) __get_current_messages_locale()->yesexpr; ret = (char*) __get_messages_locale (locale)->yesexpr;
break; break;
case NOEXPR: case NOEXPR:
ret = (char*) __get_current_messages_locale()->noexpr; ret = (char*) __get_messages_locale (locale)->noexpr;
break; break;
/* /*
* All items marked with LEGACY are available, but not recomended * All items marked with LEGACY are available, but not recomended
@ -368,22 +322,22 @@ do_codeset:
* to remove in future specification editions * to remove in future specification editions
*/ */
case YESSTR: /* LEGACY */ case YESSTR: /* LEGACY */
ret = (char*) __get_current_messages_locale()->yesstr; ret = (char*) __get_messages_locale (locale)->yesstr;
break; break;
case NOSTR: /* LEGACY */ case NOSTR: /* LEGACY */
ret = (char*) __get_current_messages_locale()->nostr; ret = (char*) __get_messages_locale (locale)->nostr;
break; break;
case CRNCYSTR: case CRNCYSTR:
ret = ""; ret = "";
cs = (char*) __get_current_monetary_locale()->currency_symbol; cs = (char*) __get_monetary_locale (locale)->currency_symbol;
if (*cs != '\0') { if (*cs != '\0') {
char pos = localeconv()->p_cs_precedes; char pos = __localeconv_l (locale)->p_cs_precedes;
if (pos == localeconv()->n_cs_precedes) { if (pos == __localeconv_l (locale)->n_cs_precedes) {
char psn = '\0'; char psn = '\0';
if (pos == CHAR_MAX) { if (pos == CHAR_MAX) {
if (strcmp(cs, __get_current_monetary_locale()->mon_decimal_point) == 0) if (strcmp(cs, __get_monetary_locale (locale)->mon_decimal_point) == 0)
psn = '.'; psn = '.';
} else } else
psn = pos ? '-' : '+'; psn = pos ? '-' : '+';
@ -406,11 +360,11 @@ do_codeset:
} }
break; break;
case D_MD_ORDER: /* local extension */ case D_MD_ORDER: /* local extension */
ret = (char *) __get_current_time_locale()->md_order; ret = (char *) __get_time_locale (locale)->md_order;
break; break;
#ifdef __HAVE_LOCALE_INFO__ #ifdef __HAVE_LOCALE_INFO__
case _NL_CTYPE_MB_CUR_MAX: case _NL_CTYPE_MB_CUR_MAX:
ret = (char *) __get_current_ctype_locale()->mb_cur_max; ret = (char *) __get_ctype_locale (locale)->mb_cur_max;
break; break;
#endif #endif
default: default:
@ -418,7 +372,7 @@ do_codeset:
if (item > _NL_LOCALE_EXTENDED_FIRST_ENTRY if (item > _NL_LOCALE_EXTENDED_FIRST_ENTRY
&& item < _NL_LOCALE_EXTENDED_LAST_ENTRY) { && item < _NL_LOCALE_EXTENDED_LAST_ENTRY) {
int idx = item - _NL_LOCALE_EXTENDED_FIRST_ENTRY - 1; int idx = item - _NL_LOCALE_EXTENDED_FIRST_ENTRY - 1;
return *(char **) ((char *) (*nl_ext[idx].base)() return *(char **) ((char *) (*nl_ext[idx].base)(locale)
+ nl_ext[idx].offset); + nl_ext[idx].offset);
} }
#endif #endif
@ -426,3 +380,8 @@ do_codeset:
} }
return (ret); return (ret);
} }
char *nl_langinfo (nl_item item)
{
return nl_langinfo_l (item, __get_current_locale ());
}

View File

@ -939,6 +939,7 @@ nexttowardl NOSIGFE
nftw SIGFE nftw SIGFE
nice SIGFE nice SIGFE
nl_langinfo SIGFE nl_langinfo SIGFE
nl_langinfo_l SIGFE
nrand48 NOSIGFE nrand48 NOSIGFE
ntohl NOSIGFE ntohl NOSIGFE
ntohs NOSIGFE ntohs NOSIGFE

View File

@ -466,12 +466,13 @@ details. */
301: Export strtod_l, strtof_l, strtol_l, strtold_l, strtoll_l, strtoul_l, 301: Export strtod_l, strtof_l, strtol_l, strtold_l, strtoll_l, strtoul_l,
strtoull_l, wcstod_l, wcstof_l, wcstol_l, wcstold_l, wcstoll_l, strtoull_l, wcstod_l, wcstof_l, wcstol_l, wcstold_l, wcstoll_l,
wcstoul_l, wcstoull_l. wcstoul_l, wcstoull_l.
302: Export nl_langinfo_l.
Note that we forgot to bump the api for ualarm, strtoll, strtoull, Note that we forgot to bump the api for ualarm, strtoll, strtoull,
sigaltstack, sethostname. */ sigaltstack, sethostname. */
#define CYGWIN_VERSION_API_MAJOR 0 #define CYGWIN_VERSION_API_MAJOR 0
#define CYGWIN_VERSION_API_MINOR 301 #define CYGWIN_VERSION_API_MINOR 302
/* There is also a compatibity version number associated with the shared memory /* There is also a compatibity version number associated with the shared memory
regions. It is incremented when incompatible changes are made to the shared regions. It is incremented when incompatible changes are made to the shared