From a6a477fa8190b13d4ef0150875e2bd114cb5b132 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 13 Jul 2016 16:51:33 +0200 Subject: POSIX-1.2008 per-thread locales, groundwork part 1 Introduce first cut of struct _thr_locale_t used for the locale_t definition. Introduce global instance called __global_locale used by default. Introduce internal inline functions __get_global_locale, __get_locale_r, __get_current_locale. Remove usage of global variables in favor of accessor functions pointing to __global_locale for now. Include all local headers in locale subdir from setlocale.h to get single include for internal locale access. Introduce __CTYPE_PTR macro to replace direct access to __ctype_ptr__ and use throughout in isxxx functions. Signed-off by: Corinna Vinschen --- winsup/cygwin/common.din | 1 + winsup/cygwin/ctype.cc | 27 +++++++++++------ winsup/cygwin/nlsfuncs.cc | 67 +++++++++++++++++++++++++++---------------- winsup/cygwin/regex/regcomp.c | 7 ++--- 4 files changed, 65 insertions(+), 37 deletions(-) (limited to 'winsup') diff --git a/winsup/cygwin/common.din b/winsup/cygwin/common.din index d8df00e..acb3fab 100644 --- a/winsup/cygwin/common.din +++ b/winsup/cygwin/common.din @@ -68,6 +68,7 @@ __isinfd = isinf NOSIGFE __isinff = isinff NOSIGFE __isnand = isnan NOSIGFE __isnanf = isnanf NOSIGFE +__locale_ctype_ptr NOSIGFE __locale_mb_cur_max NOSIGFE __main NOSIGFE __mempcpy = mempcpy NOSIGFE diff --git a/winsup/cygwin/ctype.cc b/winsup/cygwin/ctype.cc index fa8aad3..94de81e 100644 --- a/winsup/cygwin/ctype.cc +++ b/winsup/cygwin/ctype.cc @@ -1,6 +1,7 @@ #include "winsup.h" extern "C" { #include +#include "../locale/setlocale.h" #include #include @@ -18,9 +19,10 @@ extern const char __ctype_cp[22][128 + 256]; /* Newlib */ extern const char __ctype_iso[15][128 + 256]; /* Newlib */ void -__set_ctype (const char *charset) +__set_ctype (struct _reent *reent, const char *charset) { int idx; + char *ctype_ptr = NULL; switch (*charset) { @@ -36,8 +38,8 @@ __set_ctype (const char *charset) memcpy (_ctype_b, __ctype_iso[idx], 128); memcpy (_ctype_b + 256, __ctype_iso[idx] + 256, 128); } - __ctype_ptr__ = (char *) (__ctype_iso[idx] + 127); - return; + ctype_ptr = (char *) __ctype_iso[idx]; + break; case 'C': idx = __cp_index (charset + 2); if (idx < 0) @@ -47,17 +49,24 @@ __set_ctype (const char *charset) memcpy (_ctype_b, __ctype_cp[idx], 128); memcpy (_ctype_b + 256, __ctype_cp[idx] + 256, 128); } - __ctype_ptr__ = (char *) (__ctype_cp[idx] + 127); - return; + ctype_ptr = (char *) __ctype_cp[idx]; + break; default: break; } - if (CYGWIN_VERSION_CHECK_FOR_OLD_CTYPE) + if (!ctype_ptr) { - memset (_ctype_b, 0, 128); - memset (_ctype_b + 256, 0, 128); + if (CYGWIN_VERSION_CHECK_FOR_OLD_CTYPE) + { + memset (_ctype_b, 0, 128); + memset (_ctype_b + 256, 0, 128); + } + ctype_ptr = (char *) _ctype_b; } - __ctype_ptr__ = (char *) _ctype_b + 127; + if (reent) + __get_locale_r (reent)->ctype_ptr = ctype_ptr + 127; + else + __ctype_ptr__ = ctype_ptr + 127; } } /* extern "C" */ diff --git a/winsup/cygwin/nlsfuncs.cc b/winsup/cygwin/nlsfuncs.cc index 72e5f45..79ab3d1 100644 --- a/winsup/cygwin/nlsfuncs.cc +++ b/winsup/cygwin/nlsfuncs.cc @@ -17,11 +17,7 @@ details. */ #include "cygheap.h" #include "tls_pbuf.h" /* Internal headers from newlib */ -#include "../locale/timelocal.h" -#include "../locale/lctype.h" -#include "../locale/lnumeric.h" -#include "../locale/lmonetary.h" -#include "../locale/lmessages.h" +#include "../locale/setlocale.h" #include "lc_msg.h" #include "lc_era.h" @@ -689,8 +685,6 @@ __set_lc_time_from_win (const char *name, if (tmp != new_lc_time_buf) rebase_locale_buf (_time_locale, _time_locale + 1, tmp, new_lc_time_buf, lc_time_ptr); - if (*lc_time_buf) - free (*lc_time_buf); *lc_time_buf = tmp; return 1; } @@ -764,8 +758,6 @@ __set_lc_ctype_from_win (const char *name, if (tmp != new_lc_ctype_buf) rebase_locale_buf (_ctype_locale, _ctype_locale + 1, tmp, new_lc_ctype_buf, lc_ctype_ptr); - if (*lc_ctype_buf) - free (*lc_ctype_buf); *lc_ctype_buf = tmp; return 1; } @@ -841,8 +833,6 @@ __set_lc_numeric_from_win (const char *name, if (tmp != new_lc_numeric_buf) rebase_locale_buf (_numeric_locale, _numeric_locale + 1, tmp, new_lc_numeric_buf, lc_numeric_ptr); - if (*lc_numeric_buf) - free (*lc_numeric_buf); *lc_numeric_buf = tmp; return 1; } @@ -981,8 +971,6 @@ __set_lc_monetary_from_win (const char *name, if (tmp != new_lc_monetary_buf) rebase_locale_buf (_monetary_locale, _monetary_locale + 1, tmp, new_lc_monetary_buf, lc_monetary_ptr); - if (*lc_monetary_buf) - free (*lc_monetary_buf); *lc_monetary_buf = tmp; return 1; } @@ -1083,36 +1071,59 @@ __set_lc_messages_from_win (const char *name, _messages_locale->wnostr = (const wchar_t *) wc; wcpcpy (wc, msg->nostr); } - /* Aftermath. */ - if (*lc_messages_buf) - free (*lc_messages_buf); *lc_messages_buf = new_lc_messages_buf; return 1; } -LCID collate_lcid = 0; -static mbtowc_p collate_mbtowc = __ascii_mbtowc; -char collate_charset[ENCODING_LEN + 1] = "ASCII"; +struct lc_collate_T +{ + LCID lcid; + mbtowc_p mbtowc; + char codeset[ENCODING_LEN + 1]; +}; /* Called from newlib's setlocale() if category is LC_COLLATE. Stores LC_COLLATE locale information. This is subsequently accessed by the below functions strcoll, strxfrm, wcscoll, wcsxfrm. */ extern "C" int -__collate_load_locale (const char *name, mbtowc_p f_mbtowc, const char *charset) +__collate_load_locale (struct _thr_locale_t *locale, const char *name, + mbtowc_p f_mbtowc, const char *charset) { LCID lcid = __get_lcid_from_locale (name); if (lcid == (LCID) -1) return -1; - collate_lcid = lcid; - collate_mbtowc = f_mbtowc; - stpcpy (collate_charset, charset); + struct lc_collate_T *cop; + if (lcid) + { + cop = (struct lc_collate_T *) calloc (1, sizeof *cop); + if (!cop) + return -1; + cop->lcid = lcid; + cop->mbtowc = f_mbtowc; + stpcpy (cop->codeset, charset); + } return 0; } +extern "C" LCID +__get_current_collate_lcid () +{ + struct _thr_locale_t *cur_locale = __get_current_locale (); + return cur_locale->collate ? cur_locale->collate->lcid : 0; +} + extern "C" const char * __get_current_collate_codeset (void) { - return collate_charset; + struct _thr_locale_t *cur_locale = __get_current_locale (); + return cur_locale->collate ? cur_locale->collate->codeset : "ASCII"; +} + +static mbtowc_p +__get_current_collate_mbtowc () +{ + struct _thr_locale_t *cur_locale = __get_current_locale (); + return cur_locale->collate ? cur_locale->collate->mbtowc : __ascii_mbtowc; } /* We use the Windows functions for locale-specific string comparison and @@ -1122,6 +1133,7 @@ extern "C" int wcscoll (const wchar_t *__restrict ws1, const wchar_t *__restrict ws2) { int ret; + LCID collate_lcid = __get_current_collate_lcid (); if (!collate_lcid) return wcscmp (ws1, ws2); @@ -1138,11 +1150,14 @@ strcoll (const char *__restrict s1, const char *__restrict s2) wchar_t *ws1, *ws2; tmp_pathbuf tp; int ret; + LCID collate_lcid = __get_current_collate_lcid (); if (!collate_lcid) return strcmp (s1, s2); /* The ANSI version of CompareString uses the default charset of the lcid, so we must use the Unicode version. */ + mbtowc_p collate_mbtowc = __get_current_collate_mbtowc (); + const char *collate_charset = __get_current_collate_codeset (); n1 = lc_mbstowcs (collate_mbtowc, collate_charset, NULL, s1, 0) + 1; ws1 = (n1 > NT_MAX_PATH ? (wchar_t *) malloc (n1 * sizeof (wchar_t)) : tp.w_get ()); @@ -1176,6 +1191,7 @@ extern "C" size_t wcsxfrm (wchar_t *__restrict ws1, const wchar_t *__restrict ws2, size_t wsn) { size_t ret; + LCID collate_lcid = __get_current_collate_lcid (); if (!collate_lcid) return wcslcpy (ws1, ws2, wsn); @@ -1211,11 +1227,14 @@ strxfrm (char *__restrict s1, const char *__restrict s2, size_t sn) size_t n2; wchar_t *ws2; tmp_pathbuf tp; + LCID collate_lcid = __get_current_collate_lcid (); if (!collate_lcid) return strlcpy (s1, s2, sn); /* The ANSI version of LCMapString uses the default charset of the lcid, so we must use the Unicode version. */ + mbtowc_p collate_mbtowc = __get_current_collate_mbtowc (); + const char *collate_charset = __get_current_collate_codeset (); n2 = lc_mbstowcs (collate_mbtowc, collate_charset, NULL, s2, 0) + 1; ws2 = (n2 > NT_MAX_PATH ? (wchar_t *) malloc (n2 * sizeof (wchar_t)) : tp.w_get ()); diff --git a/winsup/cygwin/regex/regcomp.c b/winsup/cygwin/regex/regcomp.c index 554b43a..50d5dad 100644 --- a/winsup/cygwin/regex/regcomp.c +++ b/winsup/cygwin/regex/regcomp.c @@ -63,9 +63,8 @@ __FBSDID("$FreeBSD: src/lib/libc/regex/regcomp.c,v 1.36 2007/06/11 03:05:54 delp #include "cname.h" #ifdef __CYGWIN__ -/* These are defined in nlsfuncs.cc. */ -extern LCID collate_lcid; -extern char collate_charset[]; +/* Defined in nlsfuncs.cc. */ +extern LCID __get_current_collate_lcid (); #endif /* @@ -832,7 +831,7 @@ p_b_term(struct parse *p, cset *cs) CHadd(p, cs, start); else { #ifdef __CYGWIN__ - if (!collate_lcid) { + if (!__get_current_collate_lcid ()) { #else if (__collate_load_error) { #endif -- cgit v1.1