123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- Add a variant of `locale_charset' that returns its result based solely on
- information from the environment. See
- http://lists.gnu.org/archive/html/guile-devel/2011-11/msg00040.html for the
- rationale.
- --- a/lib/localcharset.c
- +++ b/lib/localcharset.c
- @@ -544,3 +544,120 @@ locale_charset (void)
-
- return codeset;
- }
- +
- +/* A variant of the above, without calls to `setlocale', `nl_langinfo',
- + etc. */
- +const char *
- +environ_locale_charset (void)
- +{
- + static char buf[2 + 10 + 1];
- + const char *codeset, *aliases;
- + const char *locale = NULL;
- +
- + locale = getenv ("LC_ALL");
- + if (locale == NULL || locale[0] == '\0')
- + {
- + locale = getenv ("LC_CTYPE");
- + if (locale == NULL || locale[0] == '\0')
- + locale = getenv ("LANG");
- + }
- +
- + if (locale != NULL && locale[0] != '\0')
- + {
- + /* If the locale name contains an encoding after the dot, return it. */
- + const char *dot = strchr (locale, '.');
- +
- + if (dot != NULL)
- + {
- + const char *modifier;
- +
- + dot++;
- + /* Look for the possible @... trailer and remove it, if any. */
- + modifier = strchr (dot, '@');
- + if (modifier == NULL)
- + return dot;
- + if (modifier - dot < sizeof (buf))
- + {
- + memcpy (buf, dot, modifier - dot);
- + buf [modifier - dot] = '\0';
- + return buf;
- + }
- + }
- + else if (strcmp (locale, "C") == 0)
- + {
- + strcpy (buf, "ASCII");
- + return buf;
- + }
- + else
- + codeset = "";
- + }
- + else
- + codeset = "";
- +
- + /* Resolve alias. */
- + {
- +# ifdef alias_table_defined
- + /* On some platforms, UTF-8 locales are the most frequently used ones.
- + Speed up the common case and slow down the less common cases by
- + testing for this case first. */
- +# if defined __OpenBSD__ || (defined __APPLE__ && defined __MACH__) || defined __sun || defined __CYGWIN__
- + if (strcmp (codeset, "UTF-8") == 0)
- + goto done_table_lookup;
- + else
- +# endif
- + {
- + const struct table_entry * const table = alias_table;
- + size_t const table_size =
- + sizeof (alias_table) / sizeof (struct table_entry);
- + /* The table is sorted. Perform a binary search. */
- + size_t hi = table_size;
- + size_t lo = 0;
- + while (lo < hi)
- + {
- + /* Invariant:
- + for i < lo, strcmp (table[i].alias, codeset) < 0,
- + for i >= hi, strcmp (table[i].alias, codeset) > 0. */
- + size_t mid = (hi + lo) >> 1; /* >= lo, < hi */
- + int cmp = strcmp (table[mid].alias, codeset);
- + if (cmp < 0)
- + lo = mid + 1;
- + else if (cmp > 0)
- + hi = mid;
- + else
- + {
- + /* Found an i with
- + strcmp (table[i].alias, codeset) == 0. */
- + codeset = table[mid].canonical;
- + goto done_table_lookup;
- + }
- + }
- + }
- + if (0)
- + done_table_lookup: ;
- + else
- +# endif
- + {
- + /* Did not find it in the table. */
- + /* On Mac OS X, all modern locales use the UTF-8 encoding.
- + BeOS and Haiku have a single locale, and it has UTF-8 encoding. */
- +# if (defined __APPLE__ && defined __MACH__) || defined __BEOS__ || defined __HAIKU__
- + codeset = "UTF-8";
- +# else
- + /* Don't return an empty string. GNU libc and GNU libiconv interpret
- + the empty string as denoting "the locale's character encoding",
- + thus GNU libiconv would call this function a second time. */
- + if (codeset[0] == '\0')
- + codeset = "ASCII";
- +# endif
- + }
- + }
- +
- + /* Don't return an empty string. GNU libc and GNU libiconv interpret
- + the empty string as denoting "the locale's character encoding",
- + thus GNU libiconv would call this function a second time. */
- + if (codeset[0] == '\0')
- + /* Default to Latin-1, for backward compatibility with Guile 1.8. */
- + codeset = "ISO-8859-1";
- +
- + return codeset;
- +}
|