📄 locale.c
字号:
'\x00', 'F', 'e', 'b', '\x00', 'M', 'a', 'r', '\x00', 'A', 'p', 'r', '\x00', 'M', 'a', 'y', '\x00', 'J', 'u', 'n', '\x00', 'J', 'u', 'l', '\x00', 'A', 'u', 'g', '\x00', 'S', 'e', 'p', '\x00', 'O', 'c', 't', '\x00', 'N', 'o', 'v', '\x00', 'D', 'e', 'c', '\x00', 'J', 'a', 'n', 'u', 'a', 'r', 'y', '\x00', 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'y', '\x00', 'M', 'a', 'r', 'c', 'h', '\x00', 'A', 'p', 'r', 'i', 'l', '\x00', 'M', 'a', 'y', '\x00', 'J', 'u', 'n', 'e', '\x00', 'J', 'u', 'l', 'y', '\x00', 'A', 'u', 'g', 'u', 's', 't', '\x00', 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', '\x00', 'O', 'c', 't', 'o', 'b', 'e', 'r', '\x00', 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', '\x00', 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', '\x00', 'A', 'M', '\x00', 'P', 'M', '\x00', '%', 'a', ' ', '%', 'b', ' ', '%', 'e', ' ', '%', 'H', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'Y', '\x00', '%', 'm', '/', '%', 'd', '/', '%', 'y', '\x00', '%', 'H', ':', '%', 'M', ':', '%', 'S', '\x00', '%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p', '\x00', '^', '[', 'y', 'Y', ']', '\x00', '^', '[', 'n', 'N', ']', '\x00', };char *nl_langinfo(nl_item item){ unsigned int c; unsigned int i; if ((c = _NL_ITEM_CATEGORY(item)) < C_LC_ALL) { if ((i = cat_start[c] + _NL_ITEM_INDEX(item)) < cat_start[c+1]) {/* return (char *) C_locale_data + item_offset[i] + (i & 64); */ return (char *) C_locale_data + nl_data[C_LC_ALL+1+i] + 2*(i & 64); } } return (char *) cat_start; /* Conveniently, this is the empty string. */}#else /* __LOCALE_C_ONLY */#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)char *nl_langinfo(nl_item item){ return __nl_langinfo_l(item, __UCLIBC_CURLOCALE);}#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */static const char empty[] = "";char *__XL(nl_langinfo)(nl_item item __LOCALE_PARAM ){ unsigned int c = _NL_ITEM_CATEGORY(item); unsigned int i = _NL_ITEM_INDEX(item); if ((c < LC_ALL) && (i < __LOCALE_PTR->category_item_count[c])) { return ((char **)(((char *) __LOCALE_PTR) + __LOCALE_PTR->category_offsets[c]))[i]; } return (char *) empty;}#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */#endif /* __LOCALE_C_ONLY */#endif/**********************************************************************/#ifdef L_newlocale#ifdef __UCLIBC_MJN3_ONLY__#warning TODO: Move posix and utf8 strings.#endifstatic const char posix[] = "POSIX";static const char utf8[] = "UTF-8";static int find_locale(int category_mask, const char *p, unsigned char *new_locale){ int i; const unsigned char *s; uint16_t n; unsigned char lang_cult, codeset;#if defined(__LOCALE_DATA_AT_MODIFIERS_LENGTH) && 1 /* Support standard locale handling for @-modifiers. */#ifdef __UCLIBC_MJN3_ONLY__#warning REMINDER: Fix buf size in find_locale.#endif char buf[18]; /* TODO: 7+{max codeset name length} */ const char *q; if ((q = strchr(p,'@')) != NULL) { if ((((size_t)((q-p)-5)) > (sizeof(buf) - 5)) || (p[2] != '_')) { return 0; } /* locale name at least 5 chars long and 3rd char is '_' */ s = LOCALE_AT_MODIFIERS; do { if (!strcmp(s+2, q+1)) { break; } s += 2 + *s; /* TODO - fix this throughout */ } while (*s); if (!*s) { return 0; } assert(q - p < sizeof(buf)); memcpy(buf, p, q-p); buf[q-p] = 0; buf[2] = s[1]; p = buf; }#endif lang_cult = codeset = 0; /* Assume C and default codeset. */ if (((*p == 'C') && !p[1]) || !strcmp(p, posix)) { goto FIND_LOCALE; } if ((strlen(p) > 5) && (p[5] == '.')) { /* Codeset in locale name? */ /* TODO: maybe CODESET_LIST + *s ??? */ /* 7bit is 1, UTF-8 is 2, 8-bit is >= 3 */ codeset = 2; if (strcmp(utf8,p+6) != 0) {/* TODO - fix! */ s = CODESET_LIST; do { ++codeset; /* Increment codeset first. */ if (!strcmp(CODESET_LIST+*s, p+6)) { goto FIND_LANG_CULT; } } while (*++s); return 0; /* No matching codeset! */ } } FIND_LANG_CULT: /* Find language_culture number. */ s = LOCALE_NAMES; do { /* TODO -- do a binary search? */ /* TODO -- fix gen_mmap!*/ ++lang_cult; /* Increment first since C/POSIX is 0. */ if (!strncmp(s,p,5)) { /* Found a matching locale name; */ goto FIND_LOCALE; } s += 5; } while (lang_cult < __LOCALE_DATA_NUM_LOCALE_NAMES); return 0; /* No matching language_culture! */ FIND_LOCALE: /* Find locale row matching name and codeset */ s = LOCALES; n = 0; do { /* TODO -- do a binary search? */ if ((lang_cult == *s) && ((codeset == s[1]) || (codeset == s[2]))) { i = 1; s = new_locale + 1; do { if (category_mask & i) { /* Encode current locale row number. */ ((unsigned char *) s)[0] = (n >> 7) | 0x80; ((unsigned char *) s)[1] = (n & 0x7f) | 0x80; } s += 2; i += i; } while (i < (1 << LC_ALL)); return i; /* Return non-zero */ } s += __LOCALE_DATA_WIDTH_LOCALES; ++n; } while (n <= __LOCALE_DATA_NUM_LOCALES); /* We started at 1!!! */ return 0; /* Unsupported locale. */}static unsigned char *composite_locale(int category_mask, const char *locale, unsigned char *new_locale){ char buf[MAX_LOCALE_STR]; char *t; char *e; int c; int component_mask; if (!strchr(locale,'=')) { if (!find_locale(category_mask, locale, new_locale)) { return NULL; } return new_locale; } if (strlen(locale) >= sizeof(buf)) { return NULL; } stpcpy(buf, locale); component_mask = 0; t = strtok_r(buf, "=", &e); /* This can't fail because of strchr test above. */ do { c = 0; while (strcmp(CATEGORY_NAMES + (int) CATEGORY_NAMES[c], t)) { if (++c == LC_ALL) { /* Unknown category name! */ return NULL; } } t = strtok_r(NULL, ";", &e); c = (1 << c); if (component_mask & c) { /* Multiple components for one category. */ return NULL; } component_mask |= c; if ((category_mask & c) && (!t || !find_locale(c, t, new_locale))) { return NULL; } } while ((t = strtok_r(NULL, "=", &e)) != NULL); if (category_mask & ~component_mask) { /* Category component(s) missing. */ return NULL; } return new_locale;}__locale_t __newlocale(int category_mask, const char *locale, __locale_t base){ const unsigned char *p; int i, j, k; unsigned char new_selector[LOCALE_SELECTOR_SIZE]; if (category_mask == (1 << LC_ALL)) { category_mask = LC_ALL_MASK; } if (!locale || (((unsigned int)(category_mask)) > LC_ALL_MASK)) { INVALID: __set_errno(EINVAL); return NULL; /* No locale or illegal/unsupported category. */ }#ifdef __UCLIBC_MJN3_ONLY__#warning TODO: Rename cur_locale to locale_selector.#endif strcpy((char *) new_selector, (base ? (char *) base->cur_locale : C_LOCALE_SELECTOR)); if (!*locale) { /* locale == "", so check environment. */#ifndef __UCLIBC_HAS_THREADS__ static /* If no threads, then envstr can be static. */#endif /* __UCLIBC_HAS_THREADS__ */ const char *envstr[4] = { "LC_ALL", NULL, "LANG", posix }; i = 1; k = 0; do { if (category_mask & i) { /* Note: SUSv3 doesn't define a fallback mechanism here. * So, if LC_ALL is invalid, we do _not_ continue trying * the other environment vars. */ envstr[1] = CATEGORY_NAMES + CATEGORY_NAMES[k]; j = 0; do { p = envstr[j]; } while ((++j < 4) && (!(p = getenv(p)) || !*p)); /* The user set something... is it valid? */ /* Note: Since we don't support user-supplied locales and * alternate paths, we don't need to worry about special * handling for suid/sgid apps. */ if (!find_locale(i, p, new_selector)) { goto INVALID; } } i += i; } while (++k < LC_ALL); } else if (!composite_locale(category_mask, locale, new_selector)) { goto INVALID; }#ifdef __UCLIBC_MJN3_ONLY__#warning TODO: Do a compatible codeset check!#endif /* If we get here, the new selector corresponds to a valid locale. */#ifdef __UCLIBC_MJN3_ONLY__#warning CONSIDER: Probably want a _locale_new func to allow for caching of locales.#endif#if 0 if (base) { _locale_set_l(new_selector, base); } else { base = _locale_new(new_selector); }#else if (!base) { if ((base = malloc(sizeof(__uclibc_locale_t))) == NULL) { return base; } _locale_init_l(base); } _locale_set_l(new_selector, base);#endif return base;}weak_alias(__newlocale, newlocale)#endif/**********************************************************************/#ifdef L_duplocale#ifdef __UCLIBC_MJN3_ONLY__#warning REMINDER: When we allocate ctype tables, remember to dup them.#endif__locale_t __duplocale(__locale_t dataset){ __locale_t r; uint16_t * i2w; size_t n; assert(dataset != LC_GLOBAL_LOCALE); if ((r = malloc(sizeof(__uclibc_locale_t))) != NULL) { n = 2*dataset->collate.max_col_index+2; if ((i2w = calloc(n, sizeof(uint16_t))) != NULL ) { memcpy(r, dataset, sizeof(__uclibc_locale_t)); r->collate.index2weight = i2w; memcpy(i2w, dataset->collate.index2weight, n * sizeof(uint16_t)); } else { free(r); r = NULL; } } return r;}weak_alias(__duplocale, duplocale)#endif/**********************************************************************/#ifdef L_freelocale#ifdef __UCLIBC_MJN3_ONLY__#warning REMINDER: When we allocate ctype tables, remember to free them.#endifvoid __freelocale(__locale_t dataset){ assert(dataset != __global_locale); assert(dataset != LC_GLOBAL_LOCALE); free(dataset->collate.index2weight); /* Free collation data. */ free(dataset); /* Free locale */}weak_alias(__freelocale, freelocale)#endif/**********************************************************************/#ifdef L_uselocale__locale_t __uselocale(__locale_t dataset){ __locale_t old; if (!dataset) { old = __UCLIBC_CURLOCALE; } else { if (dataset == LC_GLOBAL_LOCALE) { dataset = __global_locale; }#ifdef __UCLIBC_HAS_THREADS__ old = __curlocale_set(dataset);#else old = __curlocale_var; __curlocale_var = dataset;#endif } if (old == __global_locale) { return LC_GLOBAL_LOCALE; } return old;}weak_alias(__uselocale, uselocale)#endif/**********************************************************************/#ifdef L___curlocale#ifdef __UCLIBC_HAS_THREADS____locale_t weak_const_function __curlocale(void){ return __curlocale_var; /* This is overriden by the thread version. */}__locale_t weak_function __curlocale_set(__locale_t newloc){ __locale_t oldloc = __curlocale_var; assert(newloc != LC_GLOBAL_LOCALE); __curlocale_var = newloc; return oldloc;}#endif#endif/**********************************************************************/#ifdef L___locale_mbrtowc_l/* NOTE: This returns an int... not size_t. Also, it is not a general * routine. It is actually a very stripped-down version of mbrtowc * that takes a __locale_t arg. This is used by strcoll and strxfrm. * It is also used above to generate wchar_t versions of the decimal point * and thousands seperator. */#ifndef __CTYPE_HAS_UTF_8_LOCALES#warning __CTYPE_HAS_UTF_8_LOCALES not set!#endif#ifndef __CTYPE_HAS_8_BIT_LOCALES#warning __CTYPE_HAS_8_BIT_LOCALES not set!#endif#define Cc2wc_IDX_SHIFT __LOCALE_DATA_Cc2wc_IDX_SHIFT#define Cc2wc_ROW_LEN __LOCALE_DATA_Cc2wc_ROW_LENextern size_t _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn, const char **__restrict src, size_t n, mbstate_t *ps, int allow_continuation);int __locale_mbrtowc_l(wchar_t *__restrict dst, const char *__restrict src, __locale_t loc ){#ifdef __CTYPE_HAS_UTF_8_LOCALES if (loc->encoding == __ctype_encoding_utf8) { mbstate_t ps; const char *p = src; size_t r; ps.__mask = 0; r = _wchar_utf8sntowcs(dst, 1, &p, SIZE_MAX, &ps, 1); return (r == 1) ? (p-src) : r; /* Need to return 0 if nul char. */ }#endif#ifdef __CTYPE_HAS_8_BIT_LOCALES assert((loc->encoding == __ctype_encoding_7_bit) || (loc->encoding == __ctype_encoding_8_bit));#else assert(loc->encoding == __ctype_encoding_7_bit);#endif if ((*dst = ((unsigned char)(*src))) < 0x80) { /* ASCII... */ return (*src != 0); }#ifdef __CTYPE_HAS_8_BIT_LOCALES if (loc->encoding == __ctype_encoding_8_bit) { wchar_t wc = *dst - 0x80; *dst = loc->tbl8c2wc[ (loc->idx8c2wc[wc >> Cc2wc_IDX_SHIFT] << Cc2wc_IDX_SHIFT) + (wc & (Cc2wc_ROW_LEN - 1))]; if (*dst) { return 1; } }#endif return -1;}#endif/**********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -