int vasprintf_l(char **str, locale_t locale, const char *fmt, __va_list ap) { int ret; FILE f; struct __sfileext fext; unsigned char *_base; FIX_LOCALE(locale); _FILEEXT_SETUP(&f, &fext); f._file = -1; f._flags = __SWR | __SSTR | __SALC; f._bf._base = f._p = (unsigned char *)malloc(128); if (f._bf._base == NULL) goto err; f._bf._size = f._w = 127; /* Leave room for the NUL */ ret = __vfprintf(&f, locale, fmt, ap); if (ret == -1) goto err; *f._p = '\0'; _base = realloc(f._bf._base, ret + 1); if (_base == NULL) goto err; *str = (char *)_base; return (ret); err: if (f._bf._base) { free(f._bf._base); f._bf._base = NULL; } *str = NULL; errno = ENOMEM; return (-1); }
int tre_regwncomp_l(regex_t *preg, const wchar_t *regex, size_t n, int cflags, locale_t loc) { FIX_LOCALE(loc); return tre_compile(preg, regex, n, cflags, loc); }
int vasprintf_l(char **str, locale_t locale, const char *fmt, __va_list ap) { FILE f = FAKE_FILE; int ret; FIX_LOCALE(locale); f._flags = __SWR | __SSTR | __SALC; f._bf._base = f._p = malloc(128); if (f._bf._base == NULL) { *str = NULL; errno = ENOMEM; return (-1); } f._bf._size = f._w = 127; /* Leave room for the NUL */ ret = __vfprintf(&f, locale, fmt, ap); if (ret < 0) { free(f._bf._base); *str = NULL; errno = ENOMEM; return (-1); } *f._p = '\0'; *str = (char *)f._bf._base; return (ret); }
_RuneLocale * __runes_for_locale(locale_t locale, int *mb_sb_limit) { FIX_LOCALE(locale); struct xlocale_ctype *c = XLOCALE_CTYPE(locale); *mb_sb_limit = c->__mb_sb_limit; return c->runes; }
int strcoll_l(const char *s, const char *s2, locale_t locale) { int len, len2, prim, prim2, sec, sec2, ret, ret2; DEF_STRONG(strcoll); const char *t, *t2; char *tt, *tt2; FIX_LOCALE(locale); struct xlocale_collate *table = (struct xlocale_collate*)locale->components[XLC_COLLATE]; if (table->__collate_load_error) return strcmp(s, s2); len = len2 = 1; ret = ret2 = 0; if (table->__collate_substitute_nontrivial) { t = tt = __collate_substitute(table, s); t2 = tt2 = __collate_substitute(table, s2); } else { tt = tt2 = NULL; t = s; t2 = s2; } while(*t && *t2) { prim = prim2 = 0; while(*t && !prim) { __collate_lookup(table, t, &len, &prim, &sec); t += len; } while(*t2 && !prim2) { __collate_lookup(table, t2, &len2, &prim2, &sec2); t2 += len2; } if(!prim || !prim2) break; if(prim != prim2) { ret = prim - prim2; goto end; } if(!ret2) ret2 = sec - sec2; } if(!*t && *t2) ret = -(int)((u_char)*t2); else if(*t && !*t2) ret = (u_char)*t; else if(!*t && !*t2) ret = ret2; end: free(tt); free(tt2); return ret; }
wint_t ungetwc_l(wint_t wc, FILE *fp, locale_t locale) { wint_t r; FIX_LOCALE(locale); FLOCKFILE(fp); r = __ungetwc(wc, fp, locale); FUNLOCKFILE(fp); return (r); }
int wctob_l(wint_t c, locale_t locale) { static const mbstate_t initial; mbstate_t mbs = initial; char buf[MB_LEN_MAX]; FIX_LOCALE(locale); if (c == WEOF || XLOCALE_CTYPE(locale)->__wcrtomb(buf, c, &mbs) != 1) return (EOF); return ((unsigned char)*buf); }
/* * Return the current locale conversion. */ struct lconv * localeconv_l(locale_t loc) { FIX_LOCALE(loc); struct lconv *ret = &loc->lconv; if (loc->monetary_locale_changed) { /* LC_MONETARY part */ struct lc_monetary_T * mptr; #define M_ASSIGN_STR(NAME) (ret->NAME = (char*)mptr->NAME) #define M_ASSIGN_CHAR(NAME) (ret->NAME = mptr->NAME[0]) mptr = __get_current_monetary_locale(loc); M_ASSIGN_STR(int_curr_symbol); M_ASSIGN_STR(currency_symbol); M_ASSIGN_STR(mon_decimal_point); M_ASSIGN_STR(mon_thousands_sep); M_ASSIGN_STR(mon_grouping); M_ASSIGN_STR(positive_sign); M_ASSIGN_STR(negative_sign); M_ASSIGN_CHAR(int_frac_digits); M_ASSIGN_CHAR(frac_digits); M_ASSIGN_CHAR(p_cs_precedes); M_ASSIGN_CHAR(p_sep_by_space); M_ASSIGN_CHAR(n_cs_precedes); M_ASSIGN_CHAR(n_sep_by_space); M_ASSIGN_CHAR(p_sign_posn); M_ASSIGN_CHAR(n_sign_posn); M_ASSIGN_CHAR(int_p_cs_precedes); M_ASSIGN_CHAR(int_n_cs_precedes); M_ASSIGN_CHAR(int_p_sep_by_space); M_ASSIGN_CHAR(int_n_sep_by_space); M_ASSIGN_CHAR(int_p_sign_posn); M_ASSIGN_CHAR(int_n_sign_posn); loc->monetary_locale_changed = 0; } if (loc->numeric_locale_changed) { /* LC_NUMERIC part */ struct lc_numeric_T * nptr; #define N_ASSIGN_STR(NAME) (ret->NAME = (char*)nptr->NAME) nptr = __get_current_numeric_locale(loc); N_ASSIGN_STR(decimal_point); N_ASSIGN_STR(thousands_sep); N_ASSIGN_STR(grouping); loc->numeric_locale_changed = 0; } return ret; }
/* * MT-safe version. */ wint_t fputwc_l(wchar_t wc, FILE *fp, locale_t locale) { wint_t r; FIX_LOCALE(locale); FLOCKFILE(fp); r = __fputwc(wc, fp, locale); FUNLOCKFILE(fp); return (r); }
int strcasecmp_l(const char *s1, const char *s2, locale_t locale) { const u_char *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; FIX_LOCALE(locale); while (tolower_l(*us1, locale) == tolower_l(*us2++, locale)) if (*us1++ == '\0') return (0); return (tolower_l(*us1, locale) - tolower_l(*--us2, locale)); }
/* * MT-safe version. */ wint_t fgetwc_l(FILE *fp, locale_t locale) { wint_t r; FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); r = __fgetwc(fp, locale); FUNLOCKFILE(fp); return (r); }
/* * MT-safe version. */ wint_t fputwc_l(wchar_t wc, FILE *fp, locale_t locale) { wint_t r; FIX_LOCALE(locale); FLOCKFILE_CANCELSAFE(fp); ORIENT(fp, 1); r = __fputwc(wc, fp, locale); FUNLOCKFILE_CANCELSAFE(); return (r); }
/* * MT-safe version */ int vfwprintf_l(FILE *fp, locale_t locale, const wchar_t *fmt0, va_list ap) { int ret; FIX_LOCALE(locale); FLOCKFILE(fp); /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) ret = __sbprintf(fp, locale, fmt0, ap); else ret = __vfwprintf(fp, locale, fmt0, ap); FUNLOCKFILE(fp); return (ret); }
int wcswidth_l(const wchar_t *pwcs, size_t n, locale_t locale) { wchar_t wc; int len, l; FIX_LOCALE(locale); len = 0; while (n-- > 0 && (wc = *pwcs++) != L'\0') { if ((l = wcwidth_l(wc, locale)) < 0) return (-1); len += l; } return (len); }
int wctomb_l(char *s, wchar_t wchar, locale_t locale) { static const mbstate_t initial; size_t rval; FIX_LOCALE(locale); if (s == NULL) { /* No support for state dependent encodings. */ locale->wctomb = initial; return (0); } if ((rval = XLOCALE_CTYPE(locale)->__wcrtomb(s, wchar, &locale->wctomb)) == (size_t)-1) return (-1); return ((int)rval); }
/* * __collate_equiv_value returns the primary collation value for the given * collating symbol specified by str and len. Zero or negative is returned * if the collating symbol was not found. This function is used by bracket * code in the TRE regex library. */ int __collate_equiv_value(locale_t locale, const wchar_t *str, size_t len) { int32_t e; if (len < 1 || len >= COLLATE_STR_LEN) return (-1); FIX_LOCALE(locale); struct xlocale_collate *table = (struct xlocale_collate*)locale->components[XLC_COLLATE]; if (table->__collate_load_error) return ((len == 1 && *str <= UCHAR_MAX) ? *str : -1); if (len == 1) { e = -1; if (*str <= UCHAR_MAX) e = table->char_pri_table[*str].pri[0]; else if (table->info->large_count > 0) { collate_large_t *match_large; match_large = largesearch(table, *str); if (match_large) e = match_large->pri.pri[0]; } if (e == 0) return (1); return (e > 0 ? e : 0); } if (table->info->chain_count > 0) { wchar_t name[COLLATE_STR_LEN]; collate_chain_t *match_chain; int clen; wcsncpy (name, str, len); name[len] = 0; match_chain = chainsearch(table, name, &clen); if (match_chain) { e = match_chain->pri[0]; if (e == 0) return (1); return (e < 0 ? -e : e); } } return (0); }
int wcswidth_l(const wchar_t *s, size_t n, locale_t locale) { int w, q; FIX_LOCALE(locale); w = 0; while (n && *s) { q = wcwidth_l(*s, locale); if (q == -1) return (-1); w += q; s++; n--; } return w; }
int strncasecmp_l(const char *s1, const char *s2, size_t n, locale_t locale) { FIX_LOCALE(locale); if (n != 0) { const u_char *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; do { if (tolower_l(*us1, locale) != tolower_l(*us2++, locale)) return (tolower_l(*us1, locale) - tolower_l(*--us2, locale)); if (*us1++ == '\0') break; } while (--n != 0); } return (0); }
/* * Find the first occurrence of find in s, ignore case. */ char * strcasestr_l(const char *s, const char *find, locale_t locale) { char c, sc; size_t len; FIX_LOCALE(locale); if ((c = *find++) != 0) { c = tolower_l((unsigned char)c, locale); len = strlen(find); do { do { if ((sc = *s++) == 0) return (NULL); } while ((char)tolower_l((unsigned char)sc, locale) != c); } while (strncasecmp_l(s, find, len, locale) != 0); s--; } return ((char *)s); }
wint_t btowc_l(int c, locale_t l) { static const mbstate_t initial; mbstate_t mbs = initial; char cc; wchar_t wc; FIX_LOCALE(l); if (c == EOF) return (WEOF); /* * We expect mbrtowc() to return 0 or 1, hence the check for n > 1 * which detects error return values as well as "impossible" byte * counts. */ cc = (char)c; if (XLOCALE_CTYPE(l)->__mbrtowc(&wc, &cc, 1, &mbs) > 1) return (WEOF); return (wc); }
/* * Placeholder implementation of wcscoll(). Attempts to use the single-byte * collation ordering where possible, and falls back on wcscmp() in locales * with extended character sets. */ int wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale) { char *mbs1, *mbs2; int diff, sverrno; FIX_LOCALE(locale); struct xlocale_collate *table = (struct xlocale_collate*)locale->components[XLC_COLLATE]; if (table->__collate_load_error || MB_CUR_MAX > 1) /* * Locale has no special collating order, could not be * loaded, or has an extended character set; do a fast binary * comparison. */ return (wcscmp(ws1, ws2)); if ((mbs1 = __mbsdup(ws1)) == NULL || (mbs2 = __mbsdup(ws2)) == NULL) { /* * Out of memory or illegal wide chars; fall back to wcscmp() * but leave errno indicating the error. Callers that don't * check for error will get a reasonable but often slightly * incorrect result. */ sverrno = errno; free(mbs1); errno = sverrno; return (wcscmp(ws1, ws2)); } diff = strcoll_l(mbs1, mbs2, locale); sverrno = errno; free(mbs1); free(mbs2); errno = sverrno; return (diff); }
int mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l) { FIX_LOCALE(__l); return __l->lc_ctype->cmapp->core.user_api->mbtowc(__l->lc_ctype->cmapp, __pwc, __pmb, __max); }
size_t strxfrm_l(char *__s1, const char *__s2, size_t __n, locale_t __l) { FIX_LOCALE(__l); return __l->lc_collate->core.user_api->strxfrm(__l->lc_collate, __s1, __s2, __n); }
int strcoll_l(const char *__s1, const char *__s2, locale_t __l) { FIX_LOCALE(__l); return __l->lc_collate->core.user_api->strcoll(__l->lc_collate, __s1, __s2); }
int wcscoll_l(const wchar_t *__s1, const wchar_t *__s2, locale_t __l) { FIX_LOCALE(__l); return __l->lc_collate->core.user_api->wcscoll(__l->lc_collate, __s1, __s2); }
size_t mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len, mbstate_t *__ps, locale_t __l) { FIX_LOCALE(__l); return __l->lc_ctype->cmapp->core.user_api->mbsrtowcs(__l->lc_ctype->cmapp, __dest, __src, __len, __ps); }
struct lconv *localeconv_l(locale_t __l) { FIX_LOCALE(__l); return __l->core.user_api->localeconv(__l); }
int wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale) { int len1, len2, pri1, pri2, ret; wchar_t *tr1 = NULL, *tr2 = NULL; int direc, pass; FIX_LOCALE(locale); struct xlocale_collate *table = (struct xlocale_collate*)locale->components[XLC_COLLATE]; if (table->__collate_load_error) /* * Locale has no special collating order or could not be * loaded, do a fast binary comparison. */ return (wcscmp(ws1, ws2)); ret = 0; /* * Once upon a time we had code to try to optimize this, but * it turns out that you really can't make many assumptions * safely. You absolutely have to run this pass by pass, * because some passes will be ignored for a given character, * while others will not. Simpler locales will benefit from * having fewer passes, and most comparisions should resolve * during the primary pass anyway. * * Note that we do one final extra pass at the end to pick * up UNDEFINED elements. There is special handling for them. */ for (pass = 0; pass <= table->info->directive_count; pass++) { const int32_t *st1 = NULL; const int32_t *st2 = NULL; const wchar_t *w1 = ws1; const wchar_t *w2 = ws2; int check1, check2; /* special pass for UNDEFINED */ if (pass == table->info->directive_count) { direc = DIRECTIVE_FORWARD | DIRECTIVE_UNDEFINED; } else { direc = table->info->directive[pass]; } if (direc & DIRECTIVE_BACKWARD) { wchar_t *bp, *fp, c; if ((tr1 = wcsdup(w1)) == NULL) goto fail; bp = tr1; fp = tr1 + wcslen(tr1) - 1; while (bp < fp) { c = *bp; *bp++ = *fp; *fp-- = c; } if ((tr2 = wcsdup(w2)) == NULL) goto fail; bp = tr2; fp = tr2 + wcslen(tr2) - 1; while (bp < fp) { c = *bp; *bp++ = *fp; *fp-- = c; } w1 = tr1; w2 = tr2; } if (direc & DIRECTIVE_POSITION) { while (*w1 && *w2) { pri1 = pri2 = 0; check1 = check2 = 1; while ((pri1 == pri2) && (check1 || check2)) { if (check1) { _collate_lookup(table, w1, &len1, &pri1, pass, &st1); if (pri1 < 0) { errno = EINVAL; goto fail; } if (!pri1) { pri1 = COLLATE_MAX_PRIORITY; st1 = NULL; } check1 = (st1 != NULL); } if (check2) { _collate_lookup(table, w2, &len2, &pri2, pass, &st2); if (pri2 < 0) { errno = EINVAL; goto fail; } if (!pri2) { pri2 = COLLATE_MAX_PRIORITY; st2 = NULL; } check2 = (st2 != NULL); } } if (pri1 != pri2) { ret = pri1 - pri2; goto end; } w1 += len1; w2 += len2; } } else { while (*w1 && *w2) { pri1 = pri2 = 0; check1 = check2 = 1; while ((pri1 == pri2) && (check1 || check2)) { while (check1 && *w1) { _collate_lookup(table, w1, &len1, &pri1, pass, &st1); if (pri1 > 0) break; if (pri1 < 0) { errno = EINVAL; goto fail; } st1 = NULL; w1 += 1; } check1 = (st1 != NULL); while (check2 && *w2) { _collate_lookup(table, w2, &len2, &pri2, pass, &st2); if (pri2 > 0) break; if (pri2 < 0) { errno = EINVAL; goto fail; } st2 = NULL; w2 += 1; } check2 = (st2 != NULL); if (!pri1 || !pri2) break; } if (!pri1 || !pri2) break; if (pri1 != pri2) { ret = pri1 - pri2; goto end; } w1 += len1; w2 += len2; } } if (!*w1) { if (*w2) { ret = -(int)*w2; goto end; } } else { ret = *w1; goto end; } } ret = 0; end: free(tr1); free(tr2); return (ret); fail: ret = wcscmp(ws1, ws2); goto end; }
size_t mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l) { FIX_LOCALE(__l); return __l->lc_ctype->cmapp->core.user_api->mbrlen(__l->lc_ctype->cmapp, __s, __n, __ps); }
size_t strftime_l(char *__s, size_t __size, const char *__fmt, const struct tm *__tm, locale_t __l) { FIX_LOCALE(__l); return __l->lc_time->core.user_api->strftime(__l->lc_time, __s, __size, __fmt, __tm); }