int main () { struct locale_dependent_values expected_results; locale_t mixed1; locale_t mixed2; /* Set up a locale which is a mix between different system locales. */ setlocale (LC_ALL, "en_US.UTF-8"); setlocale (LC_NUMERIC, "de_DE.UTF-8"); setlocale (LC_TIME, "fr_FR.UTF-8"); get_locale_dependent_values (&expected_results); /* Save the locale in a locale_t object. */ mixed1 = duplocale (LC_GLOBAL_LOCALE); ASSERT (mixed1 != NULL); /* Use a per-thread locale. */ uselocale (newlocale (LC_ALL_MASK, "es_ES.UTF-8", NULL)); /* Save the locale in a locale_t object again. */ mixed2 = duplocale (LC_GLOBAL_LOCALE); ASSERT (mixed2 != NULL); /* Set up a default locale. */ setlocale (LC_ALL, "C"); uselocale (LC_GLOBAL_LOCALE); { struct locale_dependent_values c_results; get_locale_dependent_values (&c_results); } /* Now use the saved locale mixed1 again. */ setlocale (LC_ALL, "C"); uselocale (LC_GLOBAL_LOCALE); uselocale (mixed1); { struct locale_dependent_values results; get_locale_dependent_values (&results); ASSERT (strcmp (results.monetary, expected_results.monetary) == 0); ASSERT (strcmp (results.numeric, expected_results.numeric) == 0); ASSERT (strcmp (results.time, expected_results.time) == 0); } /* Now use the saved locale mixed2 again. */ setlocale (LC_ALL, "C"); uselocale (LC_GLOBAL_LOCALE); uselocale (mixed2); { struct locale_dependent_values results; get_locale_dependent_values (&results); ASSERT (strcmp (results.monetary, expected_results.monetary) == 0); ASSERT (strcmp (results.numeric, expected_results.numeric) == 0); ASSERT (strcmp (results.time, expected_results.time) == 0); } return 0; }
locale_t newlocale(int catmask, const char *locname, locale_t base) { locale_t loc; int i, e; if (catmask & ~(LC_ALL_MASK)) { errno = EINVAL; return (NULL); } /* * Technically passing LC_GLOBAL_LOCALE here is illegal, * but we allow it. */ if (base == NULL || base == ___global_locale) { loc = duplocale(___global_locale); } else { loc = duplocale(base); } if (loc == NULL) { return (NULL); } for (i = 0; i < LC_ALL; i++) { struct locdata *ldata; loc->loaded[i] = 0; if (((1 << i) & catmask) == 0) { /* Default to base locale if not overriding */ continue; } ldata = locdata_get(i, locname); if (ldata == NULL) { e = errno; freelocale(loc); errno = e; return (NULL); } loc->locdata[i] = ldata; } loc->collate = loc->locdata[LC_COLLATE]->l_data[0]; loc->ctype = loc->locdata[LC_CTYPE]->l_data[0]; loc->runelocale = loc->locdata[LC_CTYPE]->l_data[1]; loc->messages = loc->locdata[LC_MESSAGES]->l_data[0]; loc->monetary = loc->locdata[LC_MONETARY]->l_data[0]; loc->numeric = loc->locdata[LC_NUMERIC]->l_data[0]; loc->time = loc->locdata[LC_TIME]->l_data[0]; freelocale(base); return (mklocname(loc)); }
int main (void) { locale_t l; locale_t l2; int result; l = newlocale (1 << LC_ALL, "de_DE.ISO-8859-1", NULL); if (l == NULL) { printf ("newlocale failed: %m\n"); exit (EXIT_FAILURE); } puts ("Running tests of created locale"); result = do_test (l); l2 = duplocale (l); if (l2 == NULL) { printf ("duplocale failed: %m\n"); exit (EXIT_FAILURE); } freelocale (l); puts ("Running tests of duplicated locale"); result |= do_test (l2); return result; }
static int do_test (void) { locale_t d = duplocale (LC_GLOBAL_LOCALE); if (d != (locale_t) 0) freelocale (d); return 0; }
void locale_check_functions(locale_t l) { (void)duplocale(l); (void)freelocale(l); (void)localeconv(); (void)newlocale(0, "C", l); (void)setlocale(0, "C"); (void)uselocale(l); }
TEST(locale, duplocale) { locale_t cloned_global = duplocale(LC_GLOBAL_LOCALE); ASSERT_TRUE(cloned_global != NULL); freelocale(cloned_global); }
locale_t rpl_duplocale (locale_t locale) { /* Work around crash in the duplocale function in glibc < 2.12. See <http://sourceware.org/bugzilla/show_bug.cgi?id=10969>. Also, on AIX 7.1, duplocale(LC_GLOBAL_LOCALE) returns (locale_t)0 with errno set to EINVAL. */ if (locale == LC_GLOBAL_LOCALE) { /* Create a copy of the locale by fetching the name of each locale category, starting with LC_CTYPE. */ static struct { int cat; int mask; } const categories[] = { { LC_NUMERIC, LC_NUMERIC_MASK }, { LC_TIME, LC_TIME_MASK }, { LC_COLLATE, LC_COLLATE_MASK }, { LC_MONETARY, LC_MONETARY_MASK }, { LC_MESSAGES, LC_MESSAGES_MASK } #ifdef LC_PAPER , { LC_PAPER, LC_PAPER_MASK } #endif #ifdef LC_NAME , { LC_NAME, LC_NAME_MASK } #endif #ifdef LC_ADDRESS , { LC_ADDRESS, LC_ADDRESS_MASK } #endif #ifdef LC_TELEPHONE , { LC_TELEPHONE, LC_TELEPHONE_MASK } #endif #ifdef LC_MEASUREMENT , { LC_MEASUREMENT, LC_MEASUREMENT_MASK } #endif #ifdef LC_IDENTIFICATION , { LC_IDENTIFICATION, LC_IDENTIFICATION_MASK } #endif }; const char *base_name; locale_t base_copy; unsigned int i; base_name = setlocale (LC_CTYPE, NULL); base_copy = newlocale (LC_ALL_MASK, base_name, NULL); if (base_copy == NULL) return NULL; for (i = 0; i < SIZEOF (categories); i++) { int category = categories[i].cat; int category_mask = categories[i].mask; const char *name = setlocale (category, NULL); if (strcmp (name, base_name) != 0) { locale_t copy = newlocale (category_mask, name, base_copy); if (copy == NULL) { int saved_errno = errno; freelocale (base_copy); errno = saved_errno; return NULL; } /* No need to call freelocale (base_copy) if copy != base_copy; the newlocale function already takes care of doing it. */ base_copy = copy; } } return base_copy; } return duplocale (locale); }