aboutsummaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2016-07-13 16:51:33 +0200
committerCorinna Vinschen <corinna@vinschen.de>2016-08-15 10:56:56 +0200
commita6a477fa8190b13d4ef0150875e2bd114cb5b132 (patch)
tree0a4902cd997922c684b4ad4488f31eb2bde66f22 /winsup
parent51b669f679119556a12798096794845cd1049d95 (diff)
downloadnewlib-a6a477fa8190b13d4ef0150875e2bd114cb5b132.zip
newlib-a6a477fa8190b13d4ef0150875e2bd114cb5b132.tar.gz
newlib-a6a477fa8190b13d4ef0150875e2bd114cb5b132.tar.bz2
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 <corinna@vinschen.de>
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/common.din1
-rw-r--r--winsup/cygwin/ctype.cc27
-rw-r--r--winsup/cygwin/nlsfuncs.cc67
-rw-r--r--winsup/cygwin/regex/regcomp.c7
4 files changed, 65 insertions, 37 deletions
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 <ctype.h>
+#include "../locale/setlocale.h"
#include <stdlib.h>
#include <wctype.h>
@@ -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