未验证 提交 c1f2352b 编写于 作者: O openharmony_ci 提交者: Gitee

!974 Fix `setlocale` return value to be same as Linux

Merge pull request !974 from zzulilyw/master
......@@ -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)
......
......@@ -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);
......
......@@ -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
......@@ -16,6 +16,8 @@
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <stdio.h>
#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
}
......@@ -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);
......
......@@ -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)
......
......@@ -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);
......
......@@ -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_) {
......
......@@ -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]);
}
}
......
......@@ -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);
......
......@@ -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__);
......
......@@ -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);
}
......
......@@ -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",
......
#ifndef _LOCALE_IMPL_H
#define _LOCALE_IMPL_H
#include <locale.h>
#include <stdlib.h>
#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
#include "locale_impl.h"
#include <stdint.h>
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
};
......@@ -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; n<LOCALE_NAME_MAX && val[n] && val[n]!='/'; n++);
if (val[0]=='.' || val[n]) {
val = "C.UTF-8";
}
int builtin = (val[0]=='C' && !val[1])
|| !strcmp(val, "C.UTF-8")
|| !strcmp(val, "POSIX");
if (builtin) {
if (cat == LC_CTYPE && val[1]=='.')
return (void *)&__c_dot_utf8;
return 0;
}
for (p=loc_head; p; p=p->next) {
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; n<LOCALE_NAME_MAX && val[n] && val[n]!='/'; n++);
if (val[0]=='.' || val[n]) {
val = "C.UTF-8";
}
int builtin = (val[0]=='C' && !val[1])
|| !strcmp(val, "POSIX")
|| !strcmp(val, "en_US");
if (builtin) {
if (cat == LC_CTYPE && val[1] == '.')
return (void *)&__c_dot_utf8;
return 0;
}
for (p=loc_head; p; p=p->next) {
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;
}
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#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; i<LC_ALL; i++) {
tmp.cat[i] = (!(mask & (1<<i)) && loc) ? loc->cat[i] :
__get_locale(i, (mask & (1<<i)) ? name : "");
if (tmp.cat[i] == LOC_MAP_FAILED || tmp.cat[i] && tmp.cat[i]->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<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;
/* If no builtin locale matched, attempt to allocate and copy. */
if ((loc = malloc(sizeof *loc))) *loc = tmp;
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);
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#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; i<LC_ALL; i++) {
const char *z = __strchrnul(p, ';');
if (z-p <= LOCALE_NAME_MAX) {
memcpy(part, p, z-p);
part[z-p] = 0;
if (*z) p = z+1;
}
lm = __get_locale(i, part);
if (lm == LOC_MAP_FAILED) {
UNLOCK(__locale_lock);
return 0;
}
if(Fresh(lm) == INVALID) {
flag = INVALID;
}
tmp_locale.cat[i] = lm;
}
libc.global_locale = tmp_locale;
}
char *s = buf;
const char *part;
int same = 0;
for (i=0; i<LC_ALL; i++) {
const struct __locale_map *lm =
libc.global_locale.cat[i];
if (lm == libc.global_locale.cat[0]) same++;
part = lm ? lm->name : "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;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册