summaryrefslogtreecommitdiff
path: root/src/locale
diff options
context:
space:
mode:
Diffstat (limited to 'src/locale')
-rw-r--r--src/locale/bind_textdomain_codeset.c6
-rw-r--r--src/locale/codepages.h11
-rw-r--r--src/locale/dcngettext.c13
-rw-r--r--src/locale/duplocale.c5
-rw-r--r--src/locale/freelocale.c5
-rw-r--r--src/locale/gb18030utf.h206
-rw-r--r--src/locale/iconv.c50
-rw-r--r--src/locale/locale_map.c22
-rw-r--r--src/locale/newlocale.c32
-rw-r--r--src/locale/setlocale.c11
-rw-r--r--src/locale/strtod_l.c22
11 files changed, 341 insertions, 42 deletions
diff --git a/src/locale/bind_textdomain_codeset.c b/src/locale/bind_textdomain_codeset.c
index 5ebfd5e8..240e83ed 100644
--- a/src/locale/bind_textdomain_codeset.c
+++ b/src/locale/bind_textdomain_codeset.c
@@ -5,7 +5,9 @@
char *bind_textdomain_codeset(const char *domainname, const char *codeset)
{
- if (codeset && strcasecmp(codeset, "UTF-8"))
+ if (codeset && strcasecmp(codeset, "UTF-8")) {
errno = EINVAL;
- return NULL;
+ return 0;
+ }
+ return "UTF-8";
}
diff --git a/src/locale/codepages.h b/src/locale/codepages.h
index 4e236ef3..a254f0f5 100644
--- a/src/locale/codepages.h
+++ b/src/locale/codepages.h
@@ -286,6 +286,17 @@
"\323\174\103\215\64\365\124\123\213\77\336\150\263\115\66\375\164\363\12\55"
"\255\304\42\261\57\266\234\162\17\56\260\240\162\113\56\263\310\62\66\50"
+"cp858\0"
+"\0\40"
+"\307\360\223\216\70\344\200\123\316\71\352\254\203\316\73\356\260\103\114\61"
+"\311\230\143\14\75\366\310\263\117\76\377\130\303\15\76\243\140\163\15\135"
+"\341\264\63\217\76\361\104\243\212\56\277\270\302\112\57\274\204\262\312\56"
+"\140\207\55\66\315\72\7\43\14\60\251\104\375\163\321\113\213\122\212\315"
+"\67\363\274\163\316\63\367\74\316\60\110\13\175\65\325\116\373\254\65\51"
+"\360\100\243\314\62\310\220\334\214\63\317\340\134\163\327\134\233\302\314\326"
+"\323\174\103\215\64\365\124\123\213\77\336\150\263\115\66\375\164\363\12\55"
+"\255\304\42\261\57\266\234\162\17\56\260\240\162\113\56\263\310\62\66\50"
+
"cp866\0"
"\0\40"
"\337\201\27\236\170\343\221\127\236\171\347\241\227\236\172"
diff --git a/src/locale/dcngettext.c b/src/locale/dcngettext.c
index 4c304393..0b53286d 100644
--- a/src/locale/dcngettext.c
+++ b/src/locale/dcngettext.c
@@ -10,6 +10,12 @@
#include "atomic.h"
#include "pleval.h"
#include "lock.h"
+#include "fork_impl.h"
+
+#define malloc __libc_malloc
+#define calloc __libc_calloc
+#define realloc undef
+#define free undef
struct binding {
struct binding *next;
@@ -34,9 +40,11 @@ static char *gettextdir(const char *domainname, size_t *dirlen)
return 0;
}
+static volatile int lock[1];
+volatile int *const __gettext_lockptr = lock;
+
char *bindtextdomain(const char *domainname, const char *dirname)
{
- static volatile int lock[1];
struct binding *p, *q;
if (!domainname) return 0;
@@ -124,6 +132,9 @@ char *dcngettext(const char *domainname, const char *msgid1, const char *msgid2,
struct binding *q;
int old_errno = errno;
+ /* match gnu gettext behaviour */
+ if (!msgid1) goto notrans;
+
if ((unsigned)category >= LC_ALL) goto notrans;
if (!domainname) domainname = __gettextdomain();
diff --git a/src/locale/duplocale.c b/src/locale/duplocale.c
index 030b64cb..5ce33ae6 100644
--- a/src/locale/duplocale.c
+++ b/src/locale/duplocale.c
@@ -3,6 +3,11 @@
#include "locale_impl.h"
#include "libc.h"
+#define malloc __libc_malloc
+#define calloc undef
+#define realloc undef
+#define free undef
+
locale_t __duplocale(locale_t old)
{
locale_t new = malloc(sizeof *new);
diff --git a/src/locale/freelocale.c b/src/locale/freelocale.c
index 802b8bfe..385d1206 100644
--- a/src/locale/freelocale.c
+++ b/src/locale/freelocale.c
@@ -1,6 +1,11 @@
#include <stdlib.h>
#include "locale_impl.h"
+#define malloc undef
+#define calloc undef
+#define realloc undef
+#define free __libc_free
+
void freelocale(locale_t l)
{
if (__loc_is_allocated(l)) free(l);
diff --git a/src/locale/gb18030utf.h b/src/locale/gb18030utf.h
new file mode 100644
index 00000000..322a2440
--- /dev/null
+++ b/src/locale/gb18030utf.h
@@ -0,0 +1,206 @@
+{ 0x80, 36 },
+{ 0xa5, 2 },
+{ 0xa9, 7 },
+{ 0xb2, 5 },
+{ 0xb8, 31 },
+{ 0xd8, 8 },
+{ 0xe2, 6 },
+{ 0xeb, 1 },
+{ 0xee, 4 },
+{ 0xf4, 3 },
+{ 0xf8, 1 },
+{ 0xfb, 1 },
+{ 0xfd, 4 },
+{ 0x102, 17 },
+{ 0x114, 7 },
+{ 0x11c, 15 },
+{ 0x12c, 24 },
+{ 0x145, 3 },
+{ 0x149, 4 },
+{ 0x14e, 29 },
+{ 0x16c, 98 },
+{ 0x1cf, 1 },
+{ 0x1d1, 1 },
+{ 0x1d3, 1 },
+{ 0x1d5, 1 },
+{ 0x1d7, 1 },
+{ 0x1d9, 1 },
+{ 0x1db, 1 },
+{ 0x1dd, 28 },
+{ 0x1fa, 87 },
+{ 0x252, 15 },
+{ 0x262, 101 },
+{ 0x2c8, 1 },
+{ 0x2cc, 13 },
+{ 0x2da, 183 },
+{ 0x3a2, 1 },
+{ 0x3aa, 7 },
+{ 0x3c2, 1 },
+{ 0x3ca, 55 },
+{ 0x402, 14 },
+{ 0x450, 1 },
+{ 0x452, 7102 },
+{ 0x2011, 2 },
+{ 0x2017, 1 },
+{ 0x201a, 2 },
+{ 0x201e, 7 },
+{ 0x2027, 9 },
+{ 0x2031, 1 },
+{ 0x2034, 1 },
+{ 0x2036, 5 },
+{ 0x203c, 112 },
+{ 0x20ad, 86 },
+{ 0x2104, 1 },
+{ 0x2106, 3 },
+{ 0x210a, 12 },
+{ 0x2117, 10 },
+{ 0x2122, 62 },
+{ 0x216c, 4 },
+{ 0x217a, 22 },
+{ 0x2194, 2 },
+{ 0x219a, 110 },
+{ 0x2209, 6 },
+{ 0x2210, 1 },
+{ 0x2212, 3 },
+{ 0x2216, 4 },
+{ 0x221b, 2 },
+{ 0x2221, 2 },
+{ 0x2224, 1 },
+{ 0x2226, 1 },
+{ 0x222c, 2 },
+{ 0x222f, 5 },
+{ 0x2238, 5 },
+{ 0x223e, 10 },
+{ 0x2249, 3 },
+{ 0x224d, 5 },
+{ 0x2253, 13 },
+{ 0x2262, 2 },
+{ 0x2268, 6 },
+{ 0x2270, 37 },
+{ 0x2296, 3 },
+{ 0x229a, 11 },
+{ 0x22a6, 25 },
+{ 0x22c0, 82 },
+{ 0x2313, 333 },
+{ 0x246a, 10 },
+{ 0x249c, 100 },
+{ 0x254c, 4 },
+{ 0x2574, 13 },
+{ 0x2590, 3 },
+{ 0x2596, 10 },
+{ 0x25a2, 16 },
+{ 0x25b4, 8 },
+{ 0x25be, 8 },
+{ 0x25c8, 3 },
+{ 0x25cc, 2 },
+{ 0x25d0, 18 },
+{ 0x25e6, 31 },
+{ 0x2607, 2 },
+{ 0x260a, 54 },
+{ 0x2641, 1 },
+{ 0x2643, 2110 },
+{ 0x2e82, 2 },
+{ 0x2e85, 3 },
+{ 0x2e89, 2 },
+{ 0x2e8d, 10 },
+{ 0x2e98, 15 },
+{ 0x2ea8, 2 },
+{ 0x2eab, 3 },
+{ 0x2eaf, 4 },
+{ 0x2eb4, 2 },
+{ 0x2eb8, 3 },
+{ 0x2ebc, 14 },
+{ 0x2ecb, 293 },
+{ 0x2ffc, 4 },
+{ 0x3004, 1 },
+{ 0x3018, 5 },
+{ 0x301f, 2 },
+{ 0x302a, 20 },
+{ 0x303f, 2 },
+{ 0x3094, 7 },
+{ 0x309f, 2 },
+{ 0x30f7, 5 },
+{ 0x30ff, 6 },
+{ 0x312a, 246 },
+{ 0x322a, 7 },
+{ 0x3232, 113 },
+{ 0x32a4, 234 },
+{ 0x3390, 12 },
+{ 0x339f, 2 },
+{ 0x33a2, 34 },
+{ 0x33c5, 9 },
+{ 0x33cf, 2 },
+{ 0x33d3, 2 },
+{ 0x33d6, 113 },
+{ 0x3448, 43 },
+{ 0x3474, 298 },
+{ 0x359f, 111 },
+{ 0x360f, 11 },
+{ 0x361b, 765 },
+{ 0x3919, 85 },
+{ 0x396f, 96 },
+{ 0x39d1, 14 },
+{ 0x39e0, 147 },
+{ 0x3a74, 218 },
+{ 0x3b4f, 287 },
+{ 0x3c6f, 113 },
+{ 0x3ce1, 885 },
+{ 0x4057, 264 },
+{ 0x4160, 471 },
+{ 0x4338, 116 },
+{ 0x43ad, 4 },
+{ 0x43b2, 43 },
+{ 0x43de, 248 },
+{ 0x44d7, 373 },
+{ 0x464d, 20 },
+{ 0x4662, 193 },
+{ 0x4724, 5 },
+{ 0x472a, 82 },
+{ 0x477d, 16 },
+{ 0x478e, 441 },
+{ 0x4948, 50 },
+{ 0x497b, 2 },
+{ 0x497e, 4 },
+{ 0x4984, 1 },
+{ 0x4987, 20 },
+{ 0x499c, 3 },
+{ 0x49a0, 22 },
+{ 0x49b8, 703 },
+{ 0x4c78, 39 },
+{ 0x4ca4, 111 },
+{ 0x4d1a, 148 },
+{ 0x4daf, 81 },
+{ 0x9fa6, 14426 },
+{ 0xe76c, 1 },
+{ 0xe7c8, 1 },
+{ 0xe7e7, 13 },
+{ 0xe815, 1 },
+{ 0xe819, 5 },
+{ 0xe81f, 7 },
+{ 0xe827, 4 },
+{ 0xe82d, 4 },
+{ 0xe833, 8 },
+{ 0xe83c, 7 },
+{ 0xe844, 16 },
+{ 0xe856, 14 },
+{ 0xe865, 4295 },
+{ 0xf92d, 76 },
+{ 0xf97a, 27 },
+{ 0xf996, 81 },
+{ 0xf9e8, 9 },
+{ 0xf9f2, 26 },
+{ 0xfa10, 1 },
+{ 0xfa12, 1 },
+{ 0xfa15, 3 },
+{ 0xfa19, 6 },
+{ 0xfa22, 1 },
+{ 0xfa25, 2 },
+{ 0xfa2a, 1030 },
+{ 0xfe32, 1 },
+{ 0xfe45, 4 },
+{ 0xfe53, 1 },
+{ 0xfe58, 1 },
+{ 0xfe67, 1 },
+{ 0xfe6c, 149 },
+{ 0xff5f, 129 },
+{ 0xffe6, 26 },
diff --git a/src/locale/iconv.c b/src/locale/iconv.c
index 3047c27b..4151411d 100644
--- a/src/locale/iconv.c
+++ b/src/locale/iconv.c
@@ -49,10 +49,10 @@ static const unsigned char charmaps[] =
"ucs4\0utf32\0\0\313"
"ucs2\0\0\314"
"eucjp\0\0\320"
-"shiftjis\0sjis\0\0\321"
+"shiftjis\0sjis\0cp932\0\0\321"
"iso2022jp\0\0\322"
"gb18030\0\0\330"
-"gbk\0\0\331"
+"gbk\0cp936\0windows936\0\0\331"
"gb2312\0\0\332"
"big5\0bigfive\0cp950\0big5hkscs\0\0\340"
"euckr\0ksc5601\0ksx1001\0cp949\0\0\350"
@@ -74,6 +74,10 @@ static const unsigned short gb18030[126][190] = {
#include "gb18030.h"
};
+static const unsigned short gb18030utf[][2] = {
+#include "gb18030utf.h"
+};
+
static const unsigned short big5[89][157] = {
#include "big5.h"
};
@@ -224,6 +228,8 @@ static unsigned uni_to_jis(unsigned c)
}
}
+#define countof(a) (sizeof (a) / sizeof *(a))
+
size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restrict out, size_t *restrict outb)
{
size_t x=0;
@@ -339,7 +345,10 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
} else if (d-159 <= 252-159) {
c++;
d -= 159;
+ } else {
+ goto ilseq;
}
+ if (c>=84) goto ilseq;
c = jis0208[c][d];
if (!c) goto ilseq;
break;
@@ -403,6 +412,10 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
if (c < 128) break;
if (c < 0xa1) goto ilseq;
case GBK:
+ if (c == 128) {
+ c = 0x20ac;
+ break;
+ }
case GB18030:
if (c < 128) break;
c -= 0x81;
@@ -423,15 +436,24 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
d = *((unsigned char *)*in + 3);
if (d-'0'>9) goto ilseq;
c += d-'0';
- c += 128;
- for (d=0; d<=c; ) {
- k = 0;
- for (int i=0; i<126; i++)
- for (int j=0; j<190; j++)
- if (gb18030[i][j]-d <= c-d)
- k++;
- d = c+1;
- c += k;
+ /* Starting at 90 30 81 30 (189000), mapping is
+ * linear without gaps, to U+10000 and up. */
+ if (c >= 189000) {
+ c -= 189000;
+ c += 0x10000;
+ if (c >= 0x110000) goto ilseq;
+ break;
+ }
+ /* Otherwise we must process an index into set
+ * of characters unmapped by 2-byte table. */
+ for (int i=0; ; i++) {
+ if (i==countof(gb18030utf))
+ goto ilseq;
+ if (c<gb18030utf[i][1]) {
+ c += gb18030utf[i][0];
+ break;
+ }
+ c -= gb18030utf[i][1];
}
break;
}
@@ -495,7 +517,7 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
if (c >= 93 || d >= 94) {
c += (0xa1-0x81);
d += 0xa1;
- if (c >= 93 || c>=0xc6-0x81 && d>0x52)
+ if (c > 0xc6-0x81 || c==0xc6-0x81 && d>0x52)
goto ilseq;
if (d-'A'<26) d = d-'A';
else if (d-'a'<26) d = d-'a'+26;
@@ -538,6 +560,10 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
if (*outb < k) goto toobig;
memcpy(*out, tmp, k);
} else k = wctomb_utf8(*out, c);
+ /* This failure condition should be unreachable, but
+ * is included to prevent decoder bugs from translating
+ * into advancement outside the output buffer range. */
+ if (k>4) goto ilseq;
*out += k;
*outb -= k;
break;
diff --git a/src/locale/locale_map.c b/src/locale/locale_map.c
index 2321bac0..da61f7fc 100644
--- a/src/locale/locale_map.c
+++ b/src/locale/locale_map.c
@@ -1,9 +1,16 @@
#include <locale.h>
#include <string.h>
#include <sys/mman.h>
+#include <stdlib.h>
#include "locale_impl.h"
#include "libc.h"
#include "lock.h"
+#include "fork_impl.h"
+
+#define malloc __libc_malloc
+#define calloc undef
+#define realloc undef
+#define free undef
const char *__lctrans_impl(const char *msg, const struct __locale_map *lm)
{
@@ -21,9 +28,11 @@ static const char envvars[][12] = {
"LC_MESSAGES",
};
+volatile int __locale_lock[1];
+volatile int *const __locale_lockptr = __locale_lock;
+
const struct __locale_map *__get_locale(int cat, const char *val)
{
- static volatile int lock[1];
static void *volatile loc_head;
const struct __locale_map *p;
struct __locale_map *new = 0;
@@ -54,20 +63,12 @@ const struct __locale_map *__get_locale(int cat, const char *val)
for (p=loc_head; p; p=p->next)
if (!strcmp(val, p->name)) return p;
- LOCK(lock);
-
- for (p=loc_head; p; p=p->next)
- if (!strcmp(val, p->name)) {
- UNLOCK(lock);
- return p;
- }
-
if (!libc.secure) path = getenv("MUSL_LOCPATH");
/* FIXME: add a default path? */
if (path) for (; *path; path=z+!!*z) {
z = __strchrnul(path, ':');
- l = z - path - !!*z;
+ l = z - path;
if (l >= sizeof buf - n - 2) continue;
memcpy(buf, path, l);
buf[l] = '/';
@@ -108,6 +109,5 @@ const struct __locale_map *__get_locale(int cat, const char *val)
* requested name was "C" or "POSIX". */
if (!new && cat == LC_CTYPE) new = (void *)&__c_dot_utf8;
- UNLOCK(lock);
return new;
}
diff --git a/src/locale/newlocale.c b/src/locale/newlocale.c
index d20a8489..9ac3cd38 100644
--- a/src/locale/newlocale.c
+++ b/src/locale/newlocale.c
@@ -2,16 +2,15 @@
#include <string.h>
#include <pthread.h>
#include "locale_impl.h"
+#include "lock.h"
-static pthread_once_t default_locale_once;
-static struct __locale_struct default_locale, default_ctype_locale;
+#define malloc __libc_malloc
+#define calloc undef
+#define realloc undef
+#define free undef
-static void default_locale_init(void)
-{
- for (int i=0; i<LC_ALL; i++)
- default_locale.cat[i] = __get_locale(i, "");
- default_ctype_locale.cat[LC_CTYPE] = default_locale.cat[LC_CTYPE];
-}
+static int default_locale_init_done;
+static struct __locale_struct default_locale, default_ctype_locale;
int __loc_is_allocated(locale_t loc)
{
@@ -19,7 +18,7 @@ int __loc_is_allocated(locale_t loc)
&& loc != &default_locale && loc != &default_ctype_locale;
}
-locale_t __newlocale(int mask, const char *name, locale_t loc)
+static locale_t do_newlocale(int mask, const char *name, locale_t loc)
{
struct __locale_struct tmp;
@@ -44,7 +43,12 @@ locale_t __newlocale(int mask, const char *name, locale_t loc)
/* And provide builtins for the initial default locale, and a
* variant of the C locale honoring the default locale's encoding. */
- pthread_once(&default_locale_once, default_locale_init);
+ if (!default_locale_init_done) {
+ for (int i=0; i<LC_ALL; i++)
+ default_locale.cat[i] = __get_locale(i, "");
+ default_ctype_locale.cat[LC_CTYPE] = default_locale.cat[LC_CTYPE];
+ default_locale_init_done = 1;
+ }
if (!memcmp(&tmp, &default_locale, sizeof tmp)) return &default_locale;
if (!memcmp(&tmp, &default_ctype_locale, sizeof tmp))
return &default_ctype_locale;
@@ -55,4 +59,12 @@ locale_t __newlocale(int mask, const char *name, locale_t loc)
return loc;
}
+locale_t __newlocale(int mask, const char *name, locale_t loc)
+{
+ LOCK(__locale_lock);
+ loc = do_newlocale(mask, name, loc);
+ UNLOCK(__locale_lock);
+ return loc;
+}
+
weak_alias(__newlocale, newlocale);
diff --git a/src/locale/setlocale.c b/src/locale/setlocale.c
index 2bc7b500..360c4437 100644
--- a/src/locale/setlocale.c
+++ b/src/locale/setlocale.c
@@ -9,12 +9,11 @@ static char buf[LC_ALL*(LOCALE_NAME_MAX+1)];
char *setlocale(int cat, const char *name)
{
- static volatile int lock[1];
const struct __locale_map *lm;
if ((unsigned)cat > LC_ALL) return 0;
- LOCK(lock);
+ LOCK(__locale_lock);
/* For LC_ALL, setlocale is required to return a string which
* encodes the current setting for all categories. The format of
@@ -36,7 +35,7 @@ char *setlocale(int cat, const char *name)
}
lm = __get_locale(i, part);
if (lm == LOC_MAP_FAILED) {
- UNLOCK(lock);
+ UNLOCK(__locale_lock);
return 0;
}
tmp_locale.cat[i] = lm;
@@ -57,14 +56,14 @@ char *setlocale(int cat, const char *name)
s += l+1;
}
*--s = 0;
- UNLOCK(lock);
+ UNLOCK(__locale_lock);
return same==LC_ALL ? (char *)part : buf;
}
if (name) {
lm = __get_locale(cat, name);
if (lm == LOC_MAP_FAILED) {
- UNLOCK(lock);
+ UNLOCK(__locale_lock);
return 0;
}
libc.global_locale.cat[cat] = lm;
@@ -73,7 +72,7 @@ char *setlocale(int cat, const char *name)
}
char *ret = lm ? (char *)lm->name : "C";
- UNLOCK(lock);
+ UNLOCK(__locale_lock);
return ret;
}
diff --git a/src/locale/strtod_l.c b/src/locale/strtod_l.c
new file mode 100644
index 00000000..574ba148
--- /dev/null
+++ b/src/locale/strtod_l.c
@@ -0,0 +1,22 @@
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <locale.h>
+
+float strtof_l(const char *restrict s, char **restrict p, locale_t l)
+{
+ return strtof(s, p);
+}
+
+double strtod_l(const char *restrict s, char **restrict p, locale_t l)
+{
+ return strtod(s, p);
+}
+
+long double strtold_l(const char *restrict s, char **restrict p, locale_t l)
+{
+ return strtold(s, p);
+}
+
+weak_alias(strtof_l, __strtof_l);
+weak_alias(strtod_l, __strtod_l);
+weak_alias(strtold_l, __strtold_l);