diff --git a/libc-test/src/functionalext/locale/duplocale.c b/libc-test/src/functionalext/locale/duplocale.c index 85297b2253117a0453de01a63deecd7b0e0f6977..bb304c7e2d97e8b9dfc96bd037801f3b87fd348f 100644 --- a/libc-test/src/functionalext/locale/duplocale.c +++ b/libc-test/src/functionalext/locale/duplocale.c @@ -55,7 +55,7 @@ void duplocale_0200(void) locale_t global = duplocale(LC_GLOBAL_LOCALE); EXPECT_PTRNE("duplocale_0200", global, NULL); - locale_t newlocale_ = newlocale(LC_ALL_MASK, "en-US", NULL); + locale_t newlocale_ = newlocale(LC_ALL_MASK, "en_US", NULL); EXPECT_PTRNE("duplocale_0200", newlocale_, NULL); locale_t clonelocale = duplocale(newlocale_); @@ -70,6 +70,10 @@ void duplocale_0200(void) freelocale(newlocale_); newlocale_ = NULL; } + if (global) { + freelocale(global); + global = NULL; + } } int main(void) diff --git a/libc-test/src/functionalext/locale/langinfo.c b/libc-test/src/functionalext/locale/langinfo.c index e7f7014ce969931878d5c3f954ffe25c8ef3718b..60d376e73c14703076d8cc017d544f15cf85df13 100644 --- a/libc-test/src/functionalext/locale/langinfo.c +++ b/libc-test/src/functionalext/locale/langinfo.c @@ -24,7 +24,7 @@ /** * @tc.name : langinfo_0100 * @tc.desc : Asserts whether the nl_langinfo function succeeds in reading data - * from the MUSL_LOCPATH environment variable set to zh_CN. Utf-8 + * from the MUSL_LOCPATH environment variable set to zh_CN. Utf-8(There is no file in "/etc/locale" now) * @tc.level : Level 0 */ void langinfo_0100(void) @@ -36,8 +36,8 @@ void langinfo_0100(void) return; } lo = setlocale(LC_TIME, "zh_CN.UTF-8"); - if (!lo) { - EXPECT_PTRNE("nl_langinfo_0100", lo, NULL); + if (lo) { + t_error("nl_langinfo_0100 failed [%s] != NULL\n", lo); return; } char *ptr = nl_langinfo(DAY_2); @@ -66,7 +66,8 @@ void nl_langinfo_0200() /** * @tc.name : nl_langinfo_0300 * @tc.desc : Assert whether the LC_TIME data type is set to zh_CN.UTF-8 through setlocale, - * and whether the return value is empty when the abnormal time data is passed to the nl_langinfo function + * and whether the return value is empty when the abnormal time data is passed to the nl_langinfo function. + * MUSL_LOCPATH is `invalid` in system environment so it should be changed to `invalid` check * @tc.level : Level 2 */ void nl_langinfo_0300() @@ -77,8 +78,8 @@ void nl_langinfo_0300() return; } lo = setlocale(LC_TIME, "zh_CN.UTF-8"); - if (!lo) { - EXPECT_PTRNE("nl_langinfo_0300", lo, NULL); + if (lo) { + t_error("nl_langinfo_0300 failed [%s] != NULL\n", lo); return; } char *ptr = nl_langinfo(TIME_ERROR_INFO); @@ -89,13 +90,14 @@ void nl_langinfo_0300() * @tc.name : nl_langinfo_0400 * @tc.desc : Assert whether the data type of LC_MESSAGES is set to zh_CN.UTF-8 through setlocale, * and whether the return value is empty when the abnormal time data is passed to the nl_langinfo function + * MUSL_LOCPATH is `invalid` in system environment so it should be changed to `invalid` check * @tc.level : Level 2 */ void nl_langinfo_0400() { char *lo = setlocale(LC_MESSAGES, "zh_CN.UTF-8"); - if (!lo) { - EXPECT_PTRNE("nl_langinfo_0400", lo, NULL); + if (lo) { + t_error("nl_langinfo_0400 failed [%s] != NULL\n", lo); return; } char *ptr = nl_langinfo(MESSAGES_ERROR_INFO); diff --git a/libc-test/src/functionalext/locale/newlocale.c b/libc-test/src/functionalext/locale/newlocale.c index e6c5e43d79c4bf00a64a7d4e5ecfd55d54617222..153e459fd54070385f3314e02b1c4b0c71d4c43f 100644 --- a/libc-test/src/functionalext/locale/newlocale.c +++ b/libc-test/src/functionalext/locale/newlocale.c @@ -29,7 +29,7 @@ static const int lcMarkArry[] = { /** * @tc.name : newlocale_0100 - * @tc.desc : Check whether the LC_ALL type is passed to newlocale to create a custom locale environment + * @tc.desc : en-US is a invalid locale. The newlocale should return null * @tc.level : Level 0 */ void newlocale_0100(void) @@ -39,7 +39,7 @@ void newlocale_0100(void) EXPECT_PTRNE("newlocale_0100", lo, NULL); return; } - locale_t newlocale_ = newlocale(LC_ALL_MASK, "en-US", NULL); + locale_t newlocale_ = newlocale(LC_ALL_MASK, "en_US", NULL); EXPECT_PTRNE("newlocale_0100", newlocale_, NULL); if (newlocale_) { @@ -73,6 +73,7 @@ void newlocale_0200(void) * @tc.name : newlocale_0300 * @tc.desc : Determines whether the custom locale environment is created successfully * by passing different LC data types to newlocale + * tips: en-US is a invalid locale. The newlocale should return null * @tc.level : Level 0 */ void newlocale_0300(void) @@ -83,7 +84,7 @@ void newlocale_0300(void) return; } for (int i = 0; i < sizeof(lcMarkArry) / sizeof(lcMarkArry[0]); i++) { - locale_t newlocale_ = newlocale(lcMarkArry[i], "en-US", NULL); + locale_t newlocale_ = newlocale(lcMarkArry[i], "en_US", NULL); EXPECT_PTRNE("newlocale_0300", newlocale_, NULL); if (newlocale_) { @@ -93,11 +94,50 @@ void newlocale_0300(void) } } +/** + * @tc.name : newlocale_0400 + * @tc.desc : Determines whether the custom locale environment is created successfully + * by passing different LC data types to newlocale + * tips: en-US is a invalid locale. The newlocale should return null + * @tc.level : Level 0 + */ +void newlocale_0400(void) +{ + for (int i = 0; i < sizeof(lcMarkArry) / sizeof(lcMarkArry[0]); i++) { + locale_t newlocale_ = newlocale(lcMarkArry[i], "C", NULL); + EXPECT_PTRNE("newlocale_0400", newlocale_, NULL); + + if (newlocale_) { + freelocale(newlocale_); + newlocale_ = NULL; + } + + newlocale_ = newlocale(lcMarkArry[i], "C.UTF-8", NULL); + EXPECT_PTRNE("newlocale_0400", newlocale_, NULL); + + if (newlocale_) { + freelocale(newlocale_); + newlocale_ = NULL; + } + } +} + +void newlocale_0500(void) +{ + locale_t newlocale_ = newlocale(LC_ALL_MASK, "de.UTF-8", NULL); + EXPECT_PTREQ("newlocale_0500", newlocale_, NULL); + if (newlocale_) { + freelocale(newlocale_); + newlocale_ = NULL; + } +} + int main(void) { newlocale_0100(); newlocale_0200(); newlocale_0300(); + newlocale_0400(); return t_status; } \ No newline at end of file diff --git a/libc-test/src/functionalext/locale/setlocale.c b/libc-test/src/functionalext/locale/setlocale.c index ca44993a6d5806b3d24d005cb59c0f528a9e327b..500aedf74241b5280ded322cd4382b0ae3ef15bc 100644 --- a/libc-test/src/functionalext/locale/setlocale.c +++ b/libc-test/src/functionalext/locale/setlocale.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include "functionalext.h" #define TEST_LC_COUNT 7 @@ -111,18 +113,17 @@ void setlocale_0400(void) for (unsigned int i = 0; i < sizeof(envforlocale) / sizeof(envforlocale[0]); i++) { setenv(envforlocale[i], "da_DK", 1); const char *locale = setlocale(LcArry[i], ""); - if (!locale) { + if (locale) { t_error("[%s] failed\n", "setlocale_0400"); return; } - EXPECT_STREQ("SetlocaleTest_0400", locale, "da_DK"); } } /** * @tc.name : setlocaletest_0500 - * @tc.desc : Determines whether setlocale returns en_ZA - * when the character set passed in for different LC data types is set to en_ZA + * @tc.desc : Determines whether setlocale returns NULL + * when the character set passed in for invalid LC data types is set to en_ZA * @tc.level : Level 0 */ void setlocale_0500(void) @@ -134,11 +135,10 @@ void setlocale_0500(void) } for (unsigned int i = 0; i < sizeof(LcArry) / sizeof(LcArry[0]); i++) { const char *locale = setlocale(LcArry[i], "en_ZA"); - if (locale == NULL) { + if (locale) { t_error("[%s] failed\n", "setlocale_0500"); return; } - EXPECT_STREQ("SetlocaleTest_0600", locale, "en_ZA"); } } @@ -157,22 +157,18 @@ void setlocale_0600(void) setenv(envforlocale[i], "ar_QA", 1); char *locale = setlocale(LC_ALL, ""); - if (locale == NULL) { + if (locale) { t_error("[%s] failed\n", "setlocale_0600"); return; } + } +} - char *token = strtok(locale, flag); - while (token != NULL && count < LC_ALL) { - vec[count] = token; - token = strtok(NULL, flag); - count++; - } - - EXPECT_NE("setlocale_0600", count, 0); - - int expectPos = i + TEST_LC_OFFSET; - EXPECT_STREQ("setlocale_0600", "ar_QA", vec[expectPos]); +void setlocale_0700(void) +{ + char *str = setlocale(LC_ALL, "sss123456"); + if (str) { + t_error("setlocale_0700 failed [%s] != NULL\n", str); } } @@ -184,6 +180,7 @@ int main(void) setlocale_0400(); setlocale_0500(); setlocale_0600(); + setlocale_0700(); return t_status; -} \ No newline at end of file +} diff --git a/libc-test/src/functionalext/locale/uselocale.c b/libc-test/src/functionalext/locale/uselocale.c index b54a617275c89c9299760c7e7f0e9f3fa6af1327..aed90deb7f957bf5a0e126f16c532781b54315e1 100644 --- a/libc-test/src/functionalext/locale/uselocale.c +++ b/libc-test/src/functionalext/locale/uselocale.c @@ -49,11 +49,13 @@ void uselocale_0200(void) } uselocale(NULL); locale_t newLocale = newlocale(LC_PAPER_MASK, "en_ZA", NULL); - if (newLocale == NULL) { - EXPECT_PTRNE("uselocale_0200", newLocale, NULL); + if (newLocale) { + EXPECT_PTREQ("uselocale_0200", newLocale, NULL); + freelocale(newLocale); + newLocale = NULL; return; } - + newLocale = newlocale(LC_PAPER_MASK, "C.UTF-8", NULL); locale_t usenow = uselocale(newLocale); EXPECT_PTREQ("uselocale_0200", usenow, LC_GLOBAL_LOCALE); locale_t it = uselocale(NULL); diff --git a/libc-test/src/functionalext/supplement/locale/duplocale_sup.c b/libc-test/src/functionalext/supplement/locale/duplocale_sup.c index c6475784d549f66bff0e2fdb01b942bbbcd81b0c..965141c7698ceb5018a191ce723c0a2b0fad57e3 100644 --- a/libc-test/src/functionalext/supplement/locale/duplocale_sup.c +++ b/libc-test/src/functionalext/supplement/locale/duplocale_sup.c @@ -55,7 +55,7 @@ void duplocale_0200(void) locale_t global = duplocale(LC_GLOBAL_LOCALE); EXPECT_PTRNE("duplocale_0200", global, NULL); - locale_t newlocale_ = newlocale(LC_ALL_MASK, "en-US", NULL); + locale_t newlocale_ = newlocale(LC_ALL_MASK, "en_US", NULL); EXPECT_PTRNE("duplocale_0200", newlocale_, NULL); locale_t clonelocale = duplocale(newlocale_); @@ -70,6 +70,10 @@ void duplocale_0200(void) freelocale(newlocale_); newlocale_ = NULL; } + if (global) { + freelocale(global); + global = NULL; + } } int main(void) diff --git a/libc-test/src/functionalext/supplement/locale/langinfo_sup.c b/libc-test/src/functionalext/supplement/locale/langinfo_sup.c index cf2d3f1837a3aec82e03bf6319a4df100b110c57..bde9aa5ec6df5cc9dc733ee607ed129fae99d3c4 100644 --- a/libc-test/src/functionalext/supplement/locale/langinfo_sup.c +++ b/libc-test/src/functionalext/supplement/locale/langinfo_sup.c @@ -36,10 +36,6 @@ void langinfo_0100(void) return; } lo = setlocale(LC_TIME, "zh_CN.UTF-8"); - if (!lo) { - EXPECT_PTRNE("nl_langinfo_0100", lo, NULL); - return; - } char *ptr = nl_langinfo(DAY_2); EXPECT_STREQ("nl_langinfo_0100", ptr, "Monday"); } @@ -77,10 +73,6 @@ void nl_langinfo_0300() return; } lo = setlocale(LC_TIME, "zh_CN.UTF-8"); - if (!lo) { - EXPECT_PTRNE("nl_langinfo_0300", lo, NULL); - return; - } char *ptr = nl_langinfo(TIME_ERROR_INFO); EXPECT_STREQ("nl_langinfo_0300", ptr, ""); } @@ -94,8 +86,8 @@ void nl_langinfo_0300() void nl_langinfo_0400() { char *lo = setlocale(LC_MESSAGES, "zh_CN.UTF-8"); - if (!lo) { - EXPECT_PTRNE("nl_langinfo_0400", lo, NULL); + if (lo) { + t_error("nl_langinfo_0400 %s != NULL\n", lo); return; } char *ptr = nl_langinfo(MESSAGES_ERROR_INFO); diff --git a/libc-test/src/functionalext/supplement/locale/newlocale_sup.c b/libc-test/src/functionalext/supplement/locale/newlocale_sup.c index d296a62f18a8b7b037c251c51f8c198a414e4150..e938f129614f9900bc5862f0a1f7422bf4b10986 100644 --- a/libc-test/src/functionalext/supplement/locale/newlocale_sup.c +++ b/libc-test/src/functionalext/supplement/locale/newlocale_sup.c @@ -37,7 +37,7 @@ void newlocale_0100(void) EXPECT_PTRNE("newlocale_0100", lo, NULL); return; } - locale_t newlocale_ = newlocale(LC_ALL_MASK, "en-US", NULL); + locale_t newlocale_ = newlocale(LC_ALL_MASK, "en_US", NULL); EXPECT_PTRNE("newlocale_0100", newlocale_, NULL); if (newlocale_) { @@ -81,7 +81,7 @@ void newlocale_0300(void) return; } for (int i = 0; i < sizeof(lcMarkArry) / sizeof(lcMarkArry[0]); i++) { - locale_t newlocale_ = newlocale(lcMarkArry[i], "en-US", NULL); + locale_t newlocale_ = newlocale(lcMarkArry[i], "en_US", NULL); EXPECT_PTRNE("newlocale_0300", newlocale_, NULL); if (newlocale_) { diff --git a/libc-test/src/functionalext/supplement/locale/setlocale_sup.c b/libc-test/src/functionalext/supplement/locale/setlocale_sup.c index 27e4b3fb2a66dd43de9035e87b2c4428ea22dc9e..81e83b09c3e71e4f131423eb8eac3de0747c1392 100644 --- a/libc-test/src/functionalext/supplement/locale/setlocale_sup.c +++ b/libc-test/src/functionalext/supplement/locale/setlocale_sup.c @@ -104,11 +104,10 @@ void setlocale_0400(void) for (unsigned int i = 0; i < sizeof(envforlocale) / sizeof(envforlocale[0]); i++) { setenv(envforlocale[i], "da_DK", 1); const char *locale = setlocale(LcArry[i], ""); - if (!locale) { + if (locale) { t_error("[%s] failed\n", "setlocale_0400"); return; } - EXPECT_STREQ("SetlocaleTest_0400", locale, "da_DK"); } } @@ -127,11 +126,10 @@ void setlocale_0500(void) } for (unsigned int i = 0; i < sizeof(LcArry) / sizeof(LcArry[0]); i++) { const char *locale = setlocale(LcArry[i], "en_ZA"); - if (locale == NULL) { + if (locale) { t_error("[%s] failed\n", "setlocale_0500"); return; } - EXPECT_STREQ("SetlocaleTest_0600", locale, "en_ZA"); } } @@ -150,22 +148,10 @@ void setlocale_0600(void) setenv(envforlocale[i], "ar_QA", 1); char *locale = setlocale(LC_ALL, ""); - if (locale == NULL) { + if (locale) { t_error("[%s] failed\n", "setlocale_0600"); return; } - - char *token = strtok(locale, flag); - while (token != NULL && count < LC_ALL) { - vec[count] = token; - token = strtok(NULL, flag); - count++; - } - - EXPECT_NE("setlocale_0600", count, 0); - - int expectPos = i + TEST_LC_OFFSET; - EXPECT_STREQ("setlocale_0600", "ar_QA", vec[expectPos]); } } diff --git a/libc-test/src/functionalext/supplement/locale/uselocale_sup.c b/libc-test/src/functionalext/supplement/locale/uselocale_sup.c index 3fb8435123a8486c741a800ff12c1a95affc9f14..b9cb9b50d9da3b013d7740e2ecab7fbc0d3ace33 100644 --- a/libc-test/src/functionalext/supplement/locale/uselocale_sup.c +++ b/libc-test/src/functionalext/supplement/locale/uselocale_sup.c @@ -49,11 +49,13 @@ void uselocale_0200(void) } uselocale(NULL); locale_t newLocale = newlocale(LC_PAPER_MASK, "en_ZA", NULL); - if (newLocale == NULL) { - EXPECT_PTRNE("uselocale_0200", newLocale, NULL); + if (newLocale) { + EXPECT_PTREQ("uselocale_0200", newLocale, NULL); + freelocale(newLocale); + newLocale = NULL; return; } - + newLocale = newlocale(LC_PAPER_MASK, "C.UTF-8", NULL); locale_t usenow = uselocale(newLocale); EXPECT_PTREQ("uselocale_0200", usenow, LC_GLOBAL_LOCALE); locale_t it = uselocale(NULL); diff --git a/libc-test/src/functionalext/supplement/time/wcsftime_l.c b/libc-test/src/functionalext/supplement/time/wcsftime_l.c index 54022ff58d02c898ae8e945d644e6db405002b7b..07bfb05150f4d2002fbbbd4a91e6b471b5ac8f9c 100644 --- a/libc-test/src/functionalext/supplement/time/wcsftime_l.c +++ b/libc-test/src/functionalext/supplement/time/wcsftime_l.c @@ -33,7 +33,7 @@ void wcsftime_l_0100(void) wchar_t buffer[80]; time(&rtime); timeinfo = localtime(&rtime); - locale_t newlocale_ = newlocale(LC_ALL_MASK, "en-US", NULL); + locale_t newlocale_ = newlocale(LC_ALL_MASK, "en_US", NULL); size_t result = wcsftime_l(buffer, 80, L"%I:%M%p", timeinfo, newlocale_); if (!result) { t_error("%s wcsftime_l failed\n", __func__); @@ -60,7 +60,7 @@ void wcsftime_l_0200(void) .tm_min = 10, .tm_sec = 20, }; - locale_t newlocale_ = newlocale(LC_ALL_MASK, "en-US", NULL); + locale_t newlocale_ = newlocale(LC_ALL_MASK, "en_US", NULL); size_t result = wcsftime_l(buff, sizeof buff, L"%A %c", &mtime, newlocale_); if (!result) { t_error("%s wcsftime_l failed\n", __func__); diff --git a/libc-test/src/functionalext/time/strftime_l.c b/libc-test/src/functionalext/time/strftime_l.c index 73f73675921735a14e9558831339315a63027536..86d447fac430bd8233f261c7d9c2fa7b558bd8f5 100644 --- a/libc-test/src/functionalext/time/strftime_l.c +++ b/libc-test/src/functionalext/time/strftime_l.c @@ -44,7 +44,7 @@ void strftime_l_0100(void) return; } char buffer[gBufferSize]; - locale_t m_locale = newlocale(LC_ALL_MASK, "zh_cn.UTF-8", NULL); + locale_t m_locale = newlocale(LC_ALL_MASK, "en_US", NULL); strftime_l(buffer, sizeof(buffer) - 1, "%c", timeptr, m_locale); EXPECT_STREQ("strftime_l_0100", buffer, test_asctime_data[i].result); } diff --git a/musl_src.gni b/musl_src.gni index 2e0a75969da21c9825c3d95c2d0793402ee3190a..a298e06f63a3518b7b8b3032f6f12d00ebfe9a92 100644 --- a/musl_src.gni +++ b/musl_src.gni @@ -199,6 +199,7 @@ musl_src_file = [ "src/thread/pthread_cond_timedwait_monotonic_np.c", "src/thread/pthread_cond_timeout_np.c", "src/internal/pthread_impl.h", + "src/internal/locale_impl.h", "src/thread/pthread_rwlock_clockrdlock.c", "src/thread/pthread_rwlock_timedrdlock.c", "src/thread/pthread_rwlock_timedrdlock_monotonic_np.c", @@ -2084,6 +2085,7 @@ musl_src_porting_file = [ "src/env/__init_tls.c", "src/env/__libc_start_main.c", "src/internal/pthread_impl.h", + "src/internal/locale_impl.h", "src/internal/syscall.h", "ldso/namespace.h", "ldso/ns_config.h", @@ -2159,6 +2161,7 @@ musl_src_porting_file = [ "src/locale/dcngettext.c", "src/locale/locale_map.c", "src/locale/langinfo.c", + "src/locale/newlocale.c", "src/time/__tz.c", "src/time/gmtime_r.c", "src/time/strftime.c", diff --git a/porting/linux/user/src/internal/locale_impl.h b/porting/linux/user/src/internal/locale_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..a843f0e739b7714b47f027f5468b7374ef4950b5 --- /dev/null +++ b/porting/linux/user/src/internal/locale_impl.h @@ -0,0 +1,50 @@ +#ifndef _LOCALE_IMPL_H +#define _LOCALE_IMPL_H + +#include +#include +#include "libc.h" +#include "pthread_impl.h" + +#define LOCALE_NAME_MAX 23 +#define VALID 2 +#define INVALID 1 + +struct __locale_map { + const void *map; + size_t map_size; + char name[LOCALE_NAME_MAX+1]; + const struct __locale_map *next; + char flag; +}; + +extern hidden volatile int __locale_lock[1]; + +extern hidden const struct __locale_map __c_dot_utf8; +extern hidden const struct __locale_struct __c_locale; +extern hidden const struct __locale_struct __c_dot_utf8_locale; + +hidden const struct __locale_map *__get_locale(int, const char *); +hidden const char *__mo_lookup(const void *, size_t, const char *); +hidden const char *__lctrans(const char *, const struct __locale_map *); +hidden const char *__lctrans_cur(const char *); +hidden const char *__lctrans_impl(const char *, const struct __locale_map *); +hidden int __loc_is_allocated(locale_t); +hidden char *__gettextdomain(void); + +#define LOC_MAP_FAILED ((const struct __locale_map *)-1) + +#define LCTRANS(msg, lc, loc) __lctrans(msg, (loc)->cat[(lc)]) +#define LCTRANS_CUR(msg) __lctrans_cur(msg) + +#define C_LOCALE ((locale_t)&__c_locale) +#define UTF8_LOCALE ((locale_t)&__c_dot_utf8_locale) + +#define CURRENT_LOCALE (__pthread_self()->locale) + +#define CURRENT_UTF8 (!!__pthread_self()->locale->cat[LC_CTYPE]) + +#undef MB_CUR_MAX +#define MB_CUR_MAX (CURRENT_UTF8 ? 4 : 1) + +#endif diff --git a/porting/linux/user/src/locale/c_locale.c b/porting/linux/user/src/locale/c_locale.c new file mode 100644 index 0000000000000000000000000000000000000000..582d0305f020719038d9d802c348cd10a2b1fa4c --- /dev/null +++ b/porting/linux/user/src/locale/c_locale.c @@ -0,0 +1,16 @@ +#include "locale_impl.h" +#include + +static const uint32_t empty_mo[] = { 0x950412de, 0, -1, -1, -1 }; + +const struct __locale_map __c_dot_utf8 = { + .map = empty_mo, + .map_size = sizeof empty_mo, + .name = "C.UTF-8", + .flag = VALID +}; + +const struct __locale_struct __c_locale = { 0 }; +const struct __locale_struct __c_dot_utf8_locale = { + .cat[LC_CTYPE] = &__c_dot_utf8 +}; diff --git a/porting/linux/user/src/locale/locale_map.c b/porting/linux/user/src/locale/locale_map.c index 034340f574a9cbff8c7cef7eaa58d58d39c6b1d8..b2f9fc2889ae87171065e591d5d31cdd09ef1ccc 100755 --- a/porting/linux/user/src/locale/locale_map.c +++ b/porting/linux/user/src/locale/locale_map.c @@ -29,24 +29,24 @@ const char *__lctrans_impl(const char *msg, const struct __locale_map *lm) { - const char *trans = 0; - if (lm) trans = __mo_lookup(lm->map, lm->map_size, msg); - return trans ? trans : msg; + const char *trans = 0; + if (lm) trans = __mo_lookup(lm->map, lm->map_size, msg); + return trans ? trans : msg; } static const char envvars[][18] = { - "LC_CTYPE", - "LC_NUMERIC", - "LC_TIME", - "LC_COLLATE", - "LC_MONETARY", - "LC_MESSAGES", - "LC_PAPER", - "LC_NAME", - "LC_ADDRESS", - "LC_TELEPHONE", - "LC_MEASUREMENT", - "LC_IDENTIFICATION", + "LC_CTYPE", + "LC_NUMERIC", + "LC_TIME", + "LC_COLLATE", + "LC_MONETARY", + "LC_MESSAGES", + "LC_PAPER", + "LC_NAME", + "LC_ADDRESS", + "LC_TELEPHONE", + "LC_MEASUREMENT", + "LC_IDENTIFICATION", }; volatile int __locale_lock[1]; @@ -54,90 +54,109 @@ volatile int *const __locale_lockptr = __locale_lock; const struct __locale_map *__get_locale(int cat, const char *val) { - static void *volatile loc_head; - const struct __locale_map *p; - struct __locale_map *new = 0; - const char *path = 0, *z; - char buf[256]; - size_t l, n; - if (!*val) { - (val = getenv("LC_ALL")) && *val || - (val = getenv(envvars[cat])) && *val || - (val = getenv("LANG")) && *val || - (val = "C.UTF-8"); - } - - /* Limit name length and forbid leading dot or any slashes. */ - for (n=0; nnext) { - if (!strcmp(val, p->name)) { - return p; - } - } - - if (!libc.secure) { - path = getenv("MUSL_LOCPATH"); - } - - if (path) { - for (; *path; path=z+!!*z) { - z = __strchrnul(path, ':'); - l = z - path; - if (l >= sizeof buf - n - 2) { - continue; - } - memcpy(buf, path, l); - buf[l] = '/'; - memcpy(buf+l+1, val, n); - buf[l+1+n] = 0; - size_t map_size; - const void *map = __map_file(buf, &map_size); - if (map) { - new = malloc(sizeof *new); - if (!new) { - __munmap((void *)map, map_size); - break; - } - new->map = map; - new->map_size = map_size; - memcpy(new->name, val, n); - new->name[n] = 0; - new->next = loc_head; - loc_head = new; - break; - } - } - } - - /* If no locale definition was found, make a locale map - * object anyway to store the name, which is kept for the - * sake of being able to do message translations at the - * application level. */ - if (!new && (new = malloc(sizeof *new))) { - new->map = __c_dot_utf8.map; - new->map_size = __c_dot_utf8.map_size; - memcpy(new->name, val, n); - new->name[n] = 0; - new->next = loc_head; - loc_head = new; - } - - /* For LC_CTYPE, never return a null pointer unless the - * requested name was "C" or "POSIX". */ - if (!new && cat == LC_CTYPE) new = (void *)&__c_dot_utf8; - - return new; + static void *volatile loc_head; + const struct __locale_map *p; + struct __locale_map *new = 0; + const char *path = 0, *z; + char buf[256]; + size_t l, n; + + if (!*val) { + (val = getenv("LC_ALL")) && *val || + (val = getenv(envvars[cat])) && *val || + (val = getenv("LANG")) && *val || + (val = "C.UTF-8"); + } + + /* Limit name length and forbid leading dot or any slashes. */ + for (n=0; nnext) { + if (!strcmp(val, p->name)) { + return p; + } + } + + if (!strcmp(val, "en_US.UTF-8") || !strcmp(val, "C.UTF-8")) { + /* If no locale definition was found, make a locale map + * object anyway to store the name, which is kept for the + * sake of being able to do message translations at the + * application level. */ + if (!new && (new = malloc(sizeof *new))) { + new->map = __c_dot_utf8.map; + new->map_size = __c_dot_utf8.map_size; + memcpy(new->name, val, n); + new->name[n] = 0; + new->next = loc_head; + new->flag = VALID; + loc_head = new; + } + } + + if (!libc.secure) { + path = getenv("MUSL_LOCPATH"); + } + + if (path) for (; *path; path=z+!!*z) { + z = __strchrnul(path, ':'); + l = z - path; + if (l >= sizeof buf - n - 2) { + continue; + } + memcpy(buf, path, l); + buf[l] = '/'; + memcpy(buf+l+1, val, n); + buf[l+1+n] = 0; + size_t map_size; + const void *map = __map_file(buf, &map_size); + if (map) { + new = malloc(sizeof *new); + if (!new) { + __munmap((void *)map, map_size); + break; + } + new->map = map; + new->map_size = map_size; + memcpy(new->name, val, n); + new->name[n] = 0; + new->next = loc_head; + new->flag = VALID; + loc_head = new; + break; + } + } + + + /* If no locale definition was found, make a locale map + * object anyway to store the name, which is kept for the + * sake of being able to do message translations at the + * application level. */ + if (!new && (new = malloc(sizeof *new))) { + new->map = __c_dot_utf8.map; + new->map_size = __c_dot_utf8.map_size; + memcpy(new->name, val, n); + new->name[n] = 0; + new->next = loc_head; + new->flag = INVALID; + loc_head = new; + } + + /* For LC_CTYPE, never return a null pointer unless the + * requested name was "C" or "POSIX". */ + if (!new && cat == LC_CTYPE) new = (void *)&__c_dot_utf8; + + return new; } + diff --git a/porting/linux/user/src/locale/newlocale.c b/porting/linux/user/src/locale/newlocale.c new file mode 100644 index 0000000000000000000000000000000000000000..451e593f84d49f0deace507958d2ea90e7dd3214 --- /dev/null +++ b/porting/linux/user/src/locale/newlocale.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include "locale_impl.h" +#include "lock.h" + +#define malloc __libc_malloc +#define calloc undef +#define realloc undef +#define free undef + +static int default_locale_init_done; +static struct __locale_struct default_locale, default_ctype_locale; + +int __loc_is_allocated(locale_t loc) +{ + return loc && loc != C_LOCALE && loc != UTF8_LOCALE + && loc != &default_locale && loc != &default_ctype_locale; +} + +static locale_t do_newlocale(int mask, const char *name, locale_t loc) +{ + struct __locale_struct tmp; + + for (int i=0; icat[i] : + __get_locale(i, (mask & (1<flag == INVALID) + return 0; + } + + /* For locales with allocated storage, modify in-place. */ + if (__loc_is_allocated(loc)) { + *loc = tmp; + return loc; + } + + /* Otherwise, first see if we can use one of the builtin locales. + * This makes the common usage case for newlocale, getting a C locale + * with predictable behavior, very fast, and more importantly, fail-safe. */ + if (!memcmp(&tmp, C_LOCALE, sizeof tmp)) return C_LOCALE; + if (!memcmp(&tmp, UTF8_LOCALE, sizeof tmp)) return UTF8_LOCALE; + + /* And provide builtins for the initial default locale, and a + * variant of the C locale honoring the default locale's encoding. */ + if (!default_locale_init_done) { + for (int i=0; i +#include +#include +#include "locale_impl.h" +#include "libc.h" +#include "lock.h" + +static char buf[LC_ALL*(LOCALE_NAME_MAX+1)]; + +static inline int Fresh(struct __locale_map *lm) +{ + if (lm != NULL) { + return lm->flag; + } + return VALID; +} + +char *setlocale(int cat, const char *name) +{ + const struct __locale_map *lm; + char flag = VALID; + if ((unsigned)cat > LC_ALL) return 0; + + LOCK(__locale_lock); + + /* For LC_ALL, setlocale is required to return a string which + * encodes the current setting for all categories. The format of + * this string is unspecified, and only the following code, which + * performs both the serialization and deserialization, depends + * on the format, so it can easily be changed if needed. */ + if (cat == LC_ALL) { + int i; + if (name) { + struct __locale_struct tmp_locale; + char part[LOCALE_NAME_MAX+1] = "C.UTF-8"; + const char *p = name; + for (i=0; iname : "C"; + size_t l = strlen(part); + memcpy(s, part, l); + s[l] = ';'; + s += l+1; + } + *--s = 0; + UNLOCK(__locale_lock); + if (flag == INVALID) { + return 0; + } + return same==LC_ALL ? (char *)part : buf; + } + + if (name) { + lm = __get_locale(cat, name); + if (lm == LOC_MAP_FAILED) { + UNLOCK(__locale_lock); + return 0; + } + flag = Fresh(lm); + libc.global_locale.cat[cat] = lm; + } else { + lm = libc.global_locale.cat[cat]; + } + char *ret = lm ? (char *)lm->name : "C"; + + UNLOCK(__locale_lock); + if (flag == INVALID) { + return 0; + } + return ret; +}