GIF89a;
EcchiShell v1.0
/
/
proc/
self/
root/
usr/
share/
gettext/
= hi, strcmp (table[i].code, string) > 0. */
size_t mid = (hi + lo) >> 1; /* >= lo, < hi */
int cmp = strcmp (table[mid].code, string);
if (cmp < 0)
lo = mid + 1;
else if (cmp > 0)
hi = mid;
else
{
/* Found an i with
strcmp (language_table[i].code, string) == 0.
Find the entire interval of such i. */
{
size_t i;
for (i = mid; i > lo; )
{
i--;
if (strcmp (table[i].code, string) < 0)
{
lo = i + 1;
break;
}
}
}
{
size_t i;
for (i = mid; i < hi; i++)
{
if (strcmp (table[i].code, string) > 0)
{
hi = i;
break;
}
}
}
/* The set of i with
strcmp (language_table[i].code, string) == 0
is the interval [lo, hi-1]. */
break;
}
}
result->lo = lo;
result->hi = hi;
}
/* Like setlocale, but accept also locale names in the form ll or ll_CC,
where ll is an ISO 639 language code and CC is an ISO 3166 country code. */
static char *
setlocale_unixlike (int category, const char *locale)
{
char *result;
char llCC_buf[64];
char ll_buf[64];
char CC_buf[64];
/* First, try setlocale with the original argument unchanged. */
result = setlocale (category, locale);
if (result != NULL)
return result;
/* Otherwise, assume the argument is in the form
language[_territory][.codeset][@modifier]
and try to map it using the tables. */
if (strlen (locale) < sizeof (llCC_buf))
{
/* Second try: Remove the codeset part. */
{
const char *p = locale;
char *q = llCC_buf;
/* Copy the part before the dot. */
for (; *p != '\0' && *p != '.'; p++, q++)
*q = *p;
if (*p == '.')
/* Skip the part up to the '@', if any. */
for (; *p != '\0' && *p != '@'; p++)
;
/* Copy the part starting with '@', if any. */
for (; *p != '\0'; p++, q++)
*q = *p;
*q = '\0';
}
/* llCC_buf now contains
language[_territory][@modifier]
*/
if (strcmp (llCC_buf, locale) != 0)
{
result = setlocale (category, llCC_buf);
if (result != NULL)
return result;
}
/* Look it up in language_table. */
{
range_t range;
size_t i;
search (language_table,
sizeof (language_table) / sizeof (language_table[0]),
llCC_buf,
&range);
for (i = range.lo; i < range.hi; i++)
{
/* Try the replacement in language_table[i]. */
result = setlocale (category, language_table[i].english);
if (result != NULL)
return result;
}
}
/* Split language[_territory][@modifier]
into ll_buf = language[@modifier]
and CC_buf = territory
*/
{
const char *underscore = strchr (llCC_buf, '_');
if (underscore != NULL)
{
const char *territory_start = underscore + 1;
const char *territory_end = strchr (territory_start, '@');
if (territory_end == NULL)
territory_end = territory_start + strlen (territory_start);
memcpy (ll_buf, llCC_buf, underscore - llCC_buf);
strcpy (ll_buf + (underscore - llCC_buf), territory_end);
memcpy (CC_buf, territory_start, territory_end - territory_start);
CC_buf[territory_end - territory_start] = '\0';
{
/* Look up ll_buf in language_table
and CC_buf in country_table. */
range_t language_range;
search (language_table,
sizeof (language_table) / sizeof (language_table[0]),
ll_buf,
&language_range);
if (language_range.lo < language_range.hi)
{
range_t country_range;
search (country_table,
sizeof (country_table) / sizeof (country_table[0]),
CC_buf,
&country_range);
if (country_range.lo < country_range.hi)
{
size_t i;
size_t j;
for (i = language_range.lo; i < language_range.hi; i++)
for (j = country_range.lo; j < country_range.hi; j++)
{
/* Concatenate the replacements. */
const char *part1 = language_table[i].english;
size_t part1_len = strlen (part1);
const char *part2 = country_table[j].english;
size_t part2_len = strlen (part2) + 1;
char buf[64+64];
if (!(part1_len + 1 + part2_len <= sizeof (buf)))
abort ();
memcpy (buf, part1, part1_len);
buf[part1_len] = '_';
memcpy (buf + part1_len + 1, part2, part2_len);
/* Try the concatenated replacements. */
result = setlocale (category, buf);
if (result != NULL)
return result;
}
}
/* Try omitting the country entirely. This may set a locale
corresponding to the wrong country, but is better than
failing entirely. */
{
size_t i;
for (i = language_range.lo; i < language_range.hi; i++)
{
/* Try only the language replacement. */
result =
setlocale (category, language_table[i].english);
if (result != NULL)
return result;
}
}
}
}
}
}
}
/* Failed. */
return NULL;
}
# else
# define setlocale_unixlike setlocale
# endif
# if LC_MESSAGES == 1729
/* The system does not store an LC_MESSAGES locale category. Do it here. */
static char lc_messages_name[64] = "C";
/* Like setlocale, but support also LC_MESSAGES. */
static char *
setlocale_single (int category, const char *locale)
{
if (category == LC_MESSAGES)
{
if (locale != NULL)
{
lc_messages_name[sizeof (lc_messages_name) - 1] = '\0';
strncpy (lc_messages_name, locale, sizeof (lc_messages_name) - 1);
}
return lc_messages_name;
}
else
return setlocale_unixlike (category, locale);
}
# else
# define setlocale_single setlocale_unixlike
# endif
DLL_EXPORTED
char *
libintl_setlocale (int category, const char *locale)
{
if (locale != NULL && locale[0] == '\0')
{
/* A request to the set the current locale to the default locale. */
if (category == LC_ALL)
{
/* Set LC_CTYPE first. Then the other categories. */
static int const categories[] =
{
LC_NUMERIC,
LC_TIME,
LC_COLLATE,
LC_MONETARY,
LC_MESSAGES
};
char *saved_locale;
const char *base_name;
unsigned int i;
/* Back up the old locale, in case one of the steps fails. */
saved_locale = setlocale (LC_ALL, NULL);
if (saved_locale == NULL)
return NULL;
saved_locale = strdup (saved_locale);
if (saved_locale == NULL)
return NULL;
/* Set LC_CTYPE category. Set all other categories (except possibly
LC_MESSAGES) to the same value in the same call; this is likely to
save calls. */
base_name =
gl_locale_name_environ (LC_CTYPE, category_to_name (LC_CTYPE));
if (base_name == NULL)
base_name = gl_locale_name_default ();
if (setlocale_unixlike (LC_ALL, base_name) == NULL)
goto fail;
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* On native Windows, setlocale(LC_ALL,...) may succeed but set the
LC_CTYPE category to an invalid value ("C") when it does not
support the specified encoding. Report a failure instead. */
if (strchr (base_name, '.') != NULL
&& strcmp (setlocale (LC_CTYPE, NULL), "C") == 0)
goto fail;
# endif
for (i = 0; i < sizeof (categories) / sizeof (categories[0]); i++)
{
int cat = categories[i];
const char *name;
name = gl_locale_name_environ (cat, category_to_name (cat));
if (name == NULL)
name = gl_locale_name_default ();
/* If name is the same as base_name, it has already been set
through the setlocale call before the loop. */
if (strcmp (name, base_name) != 0
# if LC_MESSAGES == 1729
|| cat == LC_MESSAGES
# endif
)
if (setlocale_single (cat, name) == NULL)
goto fail;
}
/* All steps were successful. */
++_nl_msg_cat_cntr;
free (saved_locale);
return setlocale (LC_ALL, NULL);
fail:
if (saved_locale[0] != '\0') /* don't risk an endless recursion */
setlocale (LC_ALL, saved_locale);
free (saved_locale);
return NULL;
}
else
{
char *result;
const char *name =
gl_locale_name_environ (category, category_to_name (category));
if (name == NULL)
name = gl_locale_name_default ();
result = setlocale_single (category, name);
if (result != NULL)
++_nl_msg_cat_cntr;
return result;
}
}
else
{
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
if (category == LC_ALL && locale != NULL && strchr (locale, '.') != NULL)
{
char *saved_locale;
/* Back up the old locale. */
saved_locale = setlocale (LC_ALL, NULL);
if (saved_locale == NULL)
return NULL;
saved_locale = strdup (saved_locale);
if (saved_locale == NULL)
return NULL;
if (setlocale_unixlike (LC_ALL, locale) == NULL)
{
free (saved_locale);
return NULL;
}
/* On native Windows, setlocale(LC_ALL,...) may succeed but set the
LC_CTYPE category to an invalid value ("C") when it does not
support the specified encoding. Report a failure instead. */
if (strcmp (setlocale (LC_CTYPE, NULL), "C") == 0)
{
if (saved_locale[0] != '\0') /* don't risk an endless recursion */
setlocale (LC_ALL, saved_locale);
free (saved_locale);
return NULL;
}
/* It was really successful. */
++_nl_msg_cat_cntr;
free (saved_locale);
return setlocale (LC_ALL, NULL);
}
else
# endif
{
char *result = setlocale_single (category, locale);
if (result != NULL)
++_nl_msg_cat_cntr;
return result;
}
}
}
# if HAVE_NEWLOCALE
DLL_EXPORTED
locale_t
libintl_newlocale (int category_mask, const char *locale, locale_t base)
{
if (category_mask != 0 && locale != NULL && locale[0] == '\0')
{
/* A request to construct a locale_t object that refers to the default
locale. */
/* Set LC_CTYPE first. Then the other categories. */
static struct { int cat; int mask; } const categories[] =
{
{ LC_CTYPE, LC_CTYPE_MASK },
{ 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 }
};
locale_t orig_base = base;
if ((LC_ALL_MASK & ~category_mask) == 0)
{
const char *base_name;
unsigned int i;
/* Set LC_CTYPE category. Set all other categories (except possibly
LC_MESSAGES) to the same value in the same call; this is likely to
save calls. */
base_name =
gl_locale_name_environ (LC_CTYPE, category_to_name (LC_CTYPE));
if (base_name == NULL)
base_name = gl_locale_name_default ();
base = newlocale (LC_ALL_MASK, base_name, base);
if (base == NULL)
return NULL;
for (i = 1; i < sizeof (categories) / sizeof (categories[0]); i++)
{
int category = categories[i].cat;
int category_mask = categories[i].mask;
const char *name;
name =
gl_locale_name_environ (category, category_to_name (category));
if (name == NULL)
name = gl_locale_name_default ();
/* If name is the same as base_name, it has already been set
through the setlocale call before the loop. */
if (strcmp (name, base_name) != 0)
{
locale_t copy = newlocale (category_mask, name, base);
if (copy == NULL)
goto fail;
/* No need to call freelocale (base) if copy != base; the
newlocale function already takes care of doing it. */
base = copy;
}
}
}
else
{
unsigned int i;
for (i = 0; i < sizeof (categories) / sizeof (categories[0]); i++)
{
int cat_mask = categories[i].mask;
if ((category_mask & cat_mask) != 0)
{
int cat = categories[i].cat;
const char *name;
locale_t copy;
name = gl_locale_name_environ (cat, category_to_name (cat));
if (name == NULL)
name = gl_locale_name_default ();
copy = newlocale (cat_mask, name, base);
if (copy == NULL)
goto fail;
/* No need to call freelocale (base) if copy != base; the
newlocale function already takes care of doing it. */
base = copy;
}
}
}
/* All steps were successful. */
return base;
fail:
if (base != NULL && orig_base == NULL)
{
int saved_errno = errno;
freelocale (base);
errno = saved_errno;
}
return NULL;
}
else
return newlocale (category_mask, locale, base);
}
# endif
#endif