"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "bootstrapped/tests/localename.c" between
gnuastro-0.7.tar.lz and gnuastro-0.8.tar.lz

About: Gnuastro (GNU Astronomy Utilities) consists of separate command line programs for the manipulation and analysis of astronomical data.

localename.c  (gnuastro-0.7.tar.lz):localename.c  (gnuastro-0.8.tar.lz)
skipping to change at line 38 skipping to change at line 38
#endif #endif
#include <limits.h> #include <limits.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <locale.h> #include <locale.h>
#include <string.h> #include <string.h>
#include "flexmember.h" #include "flexmember.h"
#if HAVE_USELOCALE /* We cannot support uselocale() on platforms where the locale_t type is fake.
See intl-thread-locale.m4 for details. */
#if HAVE_WORKING_USELOCALE && !HAVE_FAKE_LOCALES
# define HAVE_GOOD_USELOCALE 1
#endif
#if HAVE_GOOD_USELOCALE
/* Mac OS X 10.5 defines the locale_t type in <xlocale.h>. */ /* Mac OS X 10.5 defines the locale_t type in <xlocale.h>. */
# if defined __APPLE__ && defined __MACH__ # if defined __APPLE__ && defined __MACH__
# include <xlocale.h> # include <xlocale.h>
# endif # endif
# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || (defined __linux__ && HAVE_LANGI NFO_H) || defined __CYGWIN__ # if (__GLIBC__ >= 2 && !defined __UCLIBC__) || (defined __linux__ && HAVE_LANGI NFO_H) || defined __CYGWIN__
# include <langinfo.h> # include <langinfo.h>
# endif # endif
# if !defined IN_LIBINTL # if !defined IN_LIBINTL
# include "glthread/lock.h" # include "glthread/lock.h"
# endif # endif
# if defined __sun && HAVE_GETLOCALENAME_L # if defined __sun
# if HAVE_GETLOCALENAME_L
/* Solaris >= 12. */ /* Solaris >= 12. */
extern char * getlocalename_l(int, locale_t); extern char * getlocalename_l(int, locale_t);
# elif HAVE_SOLARIS114_LOCALES
# include <sys/localedef.h>
# endif
# endif
# if HAVE_NAMELESS_LOCALES
# include <errno.h>
# include "localename-table.h"
# endif # endif
#endif #endif
#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE #if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
# include <CoreFoundation/CFString.h> # include <CoreFoundation/CFString.h>
# if HAVE_CFLOCALECOPYCURRENT # if HAVE_CFLOCALECOPYCURRENT
# include <CoreFoundation/CFLocale.h> # include <CoreFoundation/CFLocale.h>
# elif HAVE_CFPREFERENCESCOPYAPPVALUE # elif HAVE_CFPREFERENCESCOPYAPPVALUE
# include <CoreFoundation/CFPreferences.h> # include <CoreFoundation/CFPreferences.h>
# endif # endif
skipping to change at line 1145 skipping to change at line 1159
/* GetLocaleInfoA operations. */ /* GetLocaleInfoA operations. */
# ifndef LOCALE_SNAME # ifndef LOCALE_SNAME
# define LOCALE_SNAME 0x5c # define LOCALE_SNAME 0x5c
# endif # endif
# ifndef LOCALE_NAME_MAX_LENGTH # ifndef LOCALE_NAME_MAX_LENGTH
# define LOCALE_NAME_MAX_LENGTH 85 # define LOCALE_NAME_MAX_LENGTH 85
# endif # endif
#endif #endif
#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE #if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
/* Mac OS X 10.2 or newer */ /* Mac OS X 10.4 or newer */
/* Canonicalize a Mac OS X locale name to a Unix locale name. /* Canonicalize a Mac OS X locale name to a Unix locale name.
NAME is a sufficiently large buffer. NAME is a sufficiently large buffer.
On input, it contains the Mac OS X locale name. On input, it contains the Mac OS X locale name.
On output, it contains the Unix locale name. */ On output, it contains the Unix locale name. */
# if !defined IN_LIBINTL # if !defined IN_LIBINTL
static static
# endif # endif
void void
gl_locale_name_canonicalize (char *name) gl_locale_name_canonicalize (char *name)
skipping to change at line 1310 skipping to change at line 1324
}; };
/* Convert new-style locale names with language tags (ISO 639 and ISO 15924) /* Convert new-style locale names with language tags (ISO 639 and ISO 15924)
to Unix (ISO 639 and ISO 3166) names. */ to Unix (ISO 639 and ISO 3166) names. */
typedef struct { const char langtag[7+1]; const char unixy[12+1]; } typedef struct { const char langtag[7+1]; const char unixy[12+1]; }
langtag_entry; langtag_entry;
static const langtag_entry langtag_table[] = { static const langtag_entry langtag_table[] = {
/* Mac OS X has "az-Arab", "az-Cyrl", "az-Latn". /* Mac OS X has "az-Arab", "az-Cyrl", "az-Latn".
The default script for az on Unix is Latin. */ The default script for az on Unix is Latin. */
{ "az-Latn", "az" }, { "az-Latn", "az" },
/* Mac OS X has "bs-Cyrl", "bs-Latn".
The default script for bs on Unix is Latin. */
{ "bs-Latn", "bs" },
/* Mac OS X has "ga-dots". Does not yet exist on Unix. */ /* Mac OS X has "ga-dots". Does not yet exist on Unix. */
{ "ga-dots", "ga" }, { "ga-dots", "ga" },
/* Mac OS X has "kk-Cyrl". Does not yet exist on Unix. */ /* Mac OS X has "kk-Cyrl".
The default script for kk on Unix is Cyrillic. */
{ "kk-Cyrl", "kk" },
/* Mac OS X has "mn-Cyrl", "mn-Mong". /* Mac OS X has "mn-Cyrl", "mn-Mong".
The default script for mn on Unix is Cyrillic. */ The default script for mn on Unix is Cyrillic. */
{ "mn-Cyrl", "mn" }, { "mn-Cyrl", "mn" },
/* Mac OS X has "ms-Arab", "ms-Latn". /* Mac OS X has "ms-Arab", "ms-Latn".
The default script for ms on Unix is Latin. */ The default script for ms on Unix is Latin. */
{ "ms-Latn", "ms" }, { "ms-Latn", "ms" },
/* Mac OS X has "pa-Arab", "pa-Guru".
Country codes are used to distinguish these on Unix. */
{ "pa-Arab", "pa_PK" },
{ "pa-Guru", "pa_IN" },
/* Mac OS X has "shi-Latn", "shi-Tfng". Does not yet exist on Unix. */
/* Mac OS X has "sr-Cyrl", "sr-Latn".
The default script for sr on Unix is Cyrillic. */
{ "sr-Cyrl", "sr" },
/* Mac OS X has "tg-Cyrl". /* Mac OS X has "tg-Cyrl".
The default script for tg on Unix is Cyrillic. */ The default script for tg on Unix is Cyrillic. */
{ "tg-Cyrl", "tg" }, { "tg-Cyrl", "tg" },
/* Mac OS X has "tk-Cyrl". Does not yet exist on Unix. */ /* Mac OS X has "tk-Cyrl".
The default script for tk on Unix is Cyrillic. */
{ "tk-Cyrl", "tk" },
/* Mac OS X has "tt-Cyrl". /* Mac OS X has "tt-Cyrl".
The default script for tt on Unix is Cyrillic. */ The default script for tt on Unix is Cyrillic. */
{ "tt-Cyrl", "tt" }, { "tt-Cyrl", "tt" },
/* Mac OS X has "uz-Arab", "uz-Cyrl", "uz-Latn".
The default script for uz on Unix is Latin. */
{ "uz-Latn", "uz" },
/* Mac OS X has "vai-Latn", "vai-Vaii". Does not yet exist on Unix. */
/* Mac OS X has "yue-Hans", "yue-Hant".
The default script for yue on Unix is Simplified Han. */
{ "yue-Hans", "yue" },
/* Mac OS X has "zh-Hans", "zh-Hant". /* Mac OS X has "zh-Hans", "zh-Hant".
Country codes are used to distinguish these on Unix. */ Country codes are used to distinguish these on Unix. */
{ "zh-Hans", "zh_CN" }, { "zh-Hans", "zh_CN" },
{ "zh-Hant", "zh_TW" } { "zh-Hant", "zh_TW" }
}; };
/* Convert script names (ISO 15924) to Unix conventions. /* Convert script names (ISO 15924) to Unix conventions.
See https://www.unicode.org/iso15924/iso15924-codes.html */ See https://www.unicode.org/iso15924/iso15924-codes.html */
typedef struct { const char script[4+1]; const char unixy[9+1]; } typedef struct { const char script[4+1]; const char unixy[9+1]; }
script_entry; script_entry;
static const script_entry script_table[] = { static const script_entry script_table[] = {
{ "Arab", "arabic" }, { "Arab", "arabic" },
{ "Cyrl", "cyrillic" }, { "Cyrl", "cyrillic" },
{ "Latn", "latin" },
{ "Mong", "mongolian" } { "Mong", "mongolian" }
}; };
/* Step 1: Convert using legacy_table. */ /* Step 1: Convert using legacy_table. */
if (name[0] >= 'A' && name[0] <= 'Z') if (name[0] >= 'A' && name[0] <= 'Z')
{ {
unsigned int i1, i2; unsigned int i1, i2;
i1 = 0; i1 = 0;
i2 = sizeof (legacy_table) / sizeof (legacy_entry); i2 = sizeof (legacy_table) / sizeof (legacy_entry);
while (i2 - i1 > 1) while (i2 - i1 > 1)
skipping to change at line 2592 skipping to change at line 2629
last_lcid = found_lcid; last_lcid = found_lcid;
strcpy (last_locale, locale_name); strcpy (last_locale, locale_name);
} }
gl_lock_unlock (get_lcid_lock); gl_lock_unlock (get_lcid_lock);
return found_lcid; return found_lcid;
} }
# endif # endif
#endif #endif
#if HAVE_USELOCALE /* glibc, Mac OS X, Solaris 11 OpenIndiana, or Solaris 12 */ #if HAVE_GOOD_USELOCALE /* glibc, Mac OS X, FreeBSD >= 9.1, Cygwin >= 2.6,
Solaris 11 OpenIndiana, or Solaris >= 11.4 */
/* Simple hash set of strings. We don't want to drag in lots of hash table /* Simple hash set of strings. We don't want to drag in lots of hash table
code here. */ code here. */
# define SIZE_BITS (sizeof (size_t) * CHAR_BIT) # define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
/* A hash function for NUL-terminated char* strings using /* A hash function for NUL-terminated char* strings using
the method described by Bruno Haible. the method described by Bruno Haible.
See https://www.haible.de/bruno/hashfunc.html. */ See https://www.haible.de/bruno/hashfunc.html. */
static size_t _GL_ATTRIBUTE_PURE static size_t _GL_ATTRIBUTE_PURE
skipping to change at line 2618 skipping to change at line 2656
for (; *s; s++) for (; *s; s++)
h = *s + ((h << 9) | (h >> (SIZE_BITS - 9))); h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
return h; return h;
} }
/* A hash table of fixed size. Multiple threads can access it read-only /* A hash table of fixed size. Multiple threads can access it read-only
simultaneously, but only one thread can insert into it at the same time. */ simultaneously, but only one thread can insert into it at the same time. */
/* A node in a hash bucket collision list. */ /* A node in a hash bucket collision list. */
struct hash_node struct struniq_hash_node
{ {
struct hash_node * volatile next; struct struniq_hash_node * volatile next;
char contents[FLEXIBLE_ARRAY_MEMBER]; char contents[FLEXIBLE_ARRAY_MEMBER];
}; };
# define HASH_TABLE_SIZE 257 # define STRUNIQ_HASH_TABLE_SIZE 257
static struct hash_node * volatile struniq_hash_table[HASH_TABLE_SIZE] static struct struniq_hash_node * volatile struniq_hash_table[STRUNIQ_HASH_TABLE
_SIZE]
/* = { NULL, ..., NULL } */; /* = { NULL, ..., NULL } */;
/* This lock protects the struniq_hash_table against multiple simultaneous /* This lock protects the struniq_hash_table against multiple simultaneous
insertions. */ insertions. */
gl_lock_define_initialized(static, struniq_lock) gl_lock_define_initialized(static, struniq_lock)
/* Store a copy of the given string in a string pool with indefinite extent. /* Store a copy of the given string in a string pool with indefinite extent.
Return a pointer to this copy. */ Return a pointer to this copy. */
static const char * static const char *
struniq (const char *string) struniq (const char *string)
{ {
size_t hashcode = string_hash (string); size_t hashcode = string_hash (string);
size_t slot = hashcode % HASH_TABLE_SIZE; size_t slot = hashcode % STRUNIQ_HASH_TABLE_SIZE;
size_t size; size_t size;
struct hash_node *new_node; struct struniq_hash_node *new_node;
struct hash_node *p; struct struniq_hash_node *p;
for (p = struniq_hash_table[slot]; p != NULL; p = p->next) for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
if (strcmp (p->contents, string) == 0) if (strcmp (p->contents, string) == 0)
return p->contents; return p->contents;
size = strlen (string) + 1; size = strlen (string) + 1;
new_node = new_node =
(struct hash_node *) (struct struniq_hash_node *)
malloc (FLEXSIZEOF (struct hash_node, contents, size)); malloc (FLEXSIZEOF (struct struniq_hash_node, contents, size));
if (new_node == NULL) if (new_node == NULL)
/* Out of memory. Return a statically allocated string. */ /* Out of memory. Return a statically allocated string. */
return "C"; return "C";
memcpy (new_node->contents, string, size); memcpy (new_node->contents, string, size);
/* Lock while inserting new_node. */ /* Lock while inserting new_node. */
gl_lock_lock (struniq_lock); gl_lock_lock (struniq_lock);
/* Check whether another thread already added the string while we were /* Check whether another thread already added the string while we were
waiting on the lock. */ waiting on the lock. */
for (p = struniq_hash_table[slot]; p != NULL; p = p->next) for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
if (strcmp (p->contents, string) == 0) if (strcmp (p->contents, string) == 0)
skipping to change at line 2676 skipping to change at line 2714
new_node->next = struniq_hash_table[slot]; new_node->next = struniq_hash_table[slot];
struniq_hash_table[slot] = new_node; struniq_hash_table[slot] = new_node;
done: done:
/* Unlock after new_node is inserted. */ /* Unlock after new_node is inserted. */
gl_lock_unlock (struniq_lock); gl_lock_unlock (struniq_lock);
return new_node->contents; return new_node->contents;
} }
#endif #endif
#if defined IN_LIBINTL || HAVE_USELOCALE #if HAVE_GOOD_USELOCALE && HAVE_NAMELESS_LOCALES
/* The 'locale_t' object does not contain the names of the locale categories.
We have to associate them with the object through a hash table.
The hash table is defined in localename-table.[hc]. */
/* Returns the name of a given locale category in a given locale_t object,
allocated as a string with indefinite extent. */
static const char *
get_locale_t_name (int category, locale_t locale)
{
if (locale == LC_GLOBAL_LOCALE)
{
/* Query the global locale. */
const char *name = setlocale (category, NULL);
if (name != NULL)
return struniq (name);
else
/* Should normally not happen. */
return "";
}
else
{
/* Look up the names in the hash table. */
size_t hashcode = locale_hash_function (locale);
size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
/* If the locale was not found in the table, return "". This can
happen if the application uses the original newlocale()/duplocale()
functions instead of the overridden ones. */
const char *name = "";
struct locale_hash_node *p;
/* Lock while looking up the hash node. */
gl_rwlock_rdlock (locale_lock);
for (p = locale_hash_table[slot]; p != NULL; p = p->next)
if (p->locale == locale)
{
name = p->names.category_name[category];
break;
}
gl_rwlock_unlock (locale_lock);
return name;
}
}
# if !(defined newlocale && defined duplocale && defined freelocale)
# error "newlocale, duplocale, freelocale not being replaced as expected!"
# endif
/* newlocale() override. */
locale_t
newlocale (int category_mask, const char *name, locale_t base)
#undef newlocale
{
struct locale_categories_names names;
struct locale_hash_node *node;
locale_t result;
/* Make sure name has indefinite extent. */
if (((LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK
| LC_MONETARY_MASK | LC_MESSAGES_MASK)
& category_mask) != 0)
name = struniq (name);
/* Determine the category names of the result. */
if (((LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK
| LC_MONETARY_MASK | LC_MESSAGES_MASK)
& ~category_mask) == 0)
{
/* Use name, ignore base. */
int category;
name = struniq (name);
for (category = 0; category < 6; category++)
names.category_name[category] = name;
}
else
{
/* Use base, possibly also name. */
if (base == NULL)
{
int category;
for (category = 0; category < 6; category++)
{
int mask;
switch (category)
{
case LC_CTYPE:
mask = LC_CTYPE_MASK;
break;
case LC_NUMERIC:
mask = LC_NUMERIC_MASK;
break;
case LC_TIME:
mask = LC_TIME_MASK;
break;
case LC_COLLATE:
mask = LC_COLLATE_MASK;
break;
case LC_MONETARY:
mask = LC_MONETARY_MASK;
break;
case LC_MESSAGES:
mask = LC_MESSAGES_MASK;
break;
default:
abort ();
}
names.category_name[category] =
((mask & category_mask) != 0 ? name : "C");
}
}
else if (base == LC_GLOBAL_LOCALE)
{
int category;
for (category = 0; category < 6; category++)
{
int mask;
switch (category)
{
case LC_CTYPE:
mask = LC_CTYPE_MASK;
break;
case LC_NUMERIC:
mask = LC_NUMERIC_MASK;
break;
case LC_TIME:
mask = LC_TIME_MASK;
break;
case LC_COLLATE:
mask = LC_COLLATE_MASK;
break;
case LC_MONETARY:
mask = LC_MONETARY_MASK;
break;
case LC_MESSAGES:
mask = LC_MESSAGES_MASK;
break;
default:
abort ();
}
names.category_name[category] =
((mask & category_mask) != 0
? name
: get_locale_t_name (category, LC_GLOBAL_LOCALE));
}
}
else
{
/* Look up the names of base in the hash table. Like multiple calls
of get_locale_t_name, but locking only once. */
struct locale_hash_node *p;
int category;
/* Lock while looking up the hash node. */
gl_rwlock_rdlock (locale_lock);
for (p = locale_hash_table[locale_hash_function (base) % LOCALE_HASH_T
ABLE_SIZE];
p != NULL;
p = p->next)
if (p->locale == base)
break;
for (category = 0; category < 6; category++)
{
int mask;
switch (category)
{
case LC_CTYPE:
mask = LC_CTYPE_MASK;
break;
case LC_NUMERIC:
mask = LC_NUMERIC_MASK;
break;
case LC_TIME:
mask = LC_TIME_MASK;
break;
case LC_COLLATE:
mask = LC_COLLATE_MASK;
break;
case LC_MONETARY:
mask = LC_MONETARY_MASK;
break;
case LC_MESSAGES:
mask = LC_MESSAGES_MASK;
break;
default:
abort ();
}
names.category_name[category] =
((mask & category_mask) != 0
? name
: (p != NULL ? p->names.category_name[category] : ""));
}
gl_rwlock_unlock (locale_lock);
}
}
node = (struct locale_hash_node *) malloc (sizeof (struct locale_hash_node));
if (node == NULL)
/* errno is set to ENOMEM. */
return NULL;
result = newlocale (category_mask, name, base);
if (result == NULL)
{
int saved_errno = errno;
free (node);
errno = saved_errno;
return NULL;
}
/* Fill the hash node. */
node->locale = result;
node->names = names;
/* Insert it in the hash table. */
{
size_t hashcode = locale_hash_function (result);
size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
struct locale_hash_node *p;
/* Lock while inserting the new node. */
gl_rwlock_wrlock (locale_lock);
for (p = locale_hash_table[slot]; p != NULL; p = p->next)
if (p->locale == result)
{
/* This can happen if the application uses the original freelocale()
function instead of the overridden one. */
p->names = node->names;
break;
}
if (p == NULL)
{
node->next = locale_hash_table[slot];
locale_hash_table[slot] = node;
}
gl_rwlock_unlock (locale_lock);
if (p != NULL)
free (node);
}
return result;
}
/* duplocale() override. */
locale_t
duplocale (locale_t locale)
#undef duplocale
{
struct locale_hash_node *node;
locale_t result;
if (locale == NULL)
/* Invalid argument. */
abort ();
node = (struct locale_hash_node *) malloc (sizeof (struct locale_hash_node));
if (node == NULL)
/* errno is set to ENOMEM. */
return NULL;
result = duplocale (locale);
if (result == NULL)
{
int saved_errno = errno;
free (node);
errno = saved_errno;
return NULL;
}
/* Fill the hash node. */
node->locale = result;
if (locale == LC_GLOBAL_LOCALE)
{
int category;
for (category = 0; category < 6; category++)
node->names.category_name[category] =
get_locale_t_name (category, LC_GLOBAL_LOCALE);
/* Lock before inserting the new node. */
gl_rwlock_wrlock (locale_lock);
}
else
{
struct locale_hash_node *p;
/* Lock once, for the lookup and the insertion. */
gl_rwlock_wrlock (locale_lock);
for (p = locale_hash_table[locale_hash_function (locale) % LOCALE_HASH_TAB
LE_SIZE];
p != NULL;
p = p->next)
if (p->locale == locale)
break;
if (p != NULL)
node->names = p->names;
else
{
/* This can happen if the application uses the original
newlocale()/duplocale() functions instead of the overridden
ones. */
int category;
for (category = 0; category < 6; category++)
node->names.category_name[category] = "";
}
}
/* Insert it in the hash table. */
{
size_t hashcode = locale_hash_function (result);
size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
struct locale_hash_node *p;
for (p = locale_hash_table[slot]; p != NULL; p = p->next)
if (p->locale == result)
{
/* This can happen if the application uses the original freelocale()
function instead of the overridden one. */
p->names = node->names;
break;
}
if (p == NULL)
{
node->next = locale_hash_table[slot];
locale_hash_table[slot] = node;
}
gl_rwlock_unlock (locale_lock);
if (p != NULL)
free (node);
}
return result;
}
/* freelocale() override. */
void
freelocale (locale_t locale)
#undef freelocale
{
if (locale == NULL || locale == LC_GLOBAL_LOCALE)
/* Invalid argument. */
abort ();
{
size_t hashcode = locale_hash_function (locale);
size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
struct locale_hash_node *found;
struct locale_hash_node **p;
found = NULL;
/* Lock while removing the hash node. */
gl_rwlock_wrlock (locale_lock);
for (p = &locale_hash_table[slot]; *p != NULL; p = &(*p)->next)
if ((*p)->locale == locale)
{
found = *p;
*p = (*p)->next;
break;
}
gl_rwlock_unlock (locale_lock);
free (found);
}
freelocale (locale);
}
#endif
#if defined IN_LIBINTL || HAVE_GOOD_USELOCALE
/* Like gl_locale_name_thread, except that the result is not in storage of /* Like gl_locale_name_thread, except that the result is not in storage of
indefinite extent. */ indefinite extent. */
# if !defined IN_LIBINTL # if !defined IN_LIBINTL
static static
# endif # endif
const char * const char *
gl_locale_name_thread_unsafe (int category, const char *categoryname) gl_locale_name_thread_unsafe (int category, const char *categoryname)
{ {
# if HAVE_USELOCALE # if HAVE_GOOD_USELOCALE
{ {
locale_t thread_locale = uselocale (NULL); locale_t thread_locale = uselocale (NULL);
if (thread_locale != LC_GLOBAL_LOCALE) if (thread_locale != LC_GLOBAL_LOCALE)
{ {
# if __GLIBC__ >= 2 && !defined __UCLIBC__ # if __GLIBC__ >= 2 && !defined __UCLIBC__
/* Work around an incorrect definition of the _NL_LOCALE_NAME macro in /* Work around an incorrect definition of the _NL_LOCALE_NAME macro in
glibc < 2.12. glibc < 2.12.
See <https://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */ See <https://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */
const char *name = const char *name =
nl_langinfo (_NL_ITEM ((category), _NL_ITEM_INDEX (-1))); nl_langinfo (_NL_ITEM ((category), _NL_ITEM_INDEX (-1)));
skipping to change at line 2737 skipping to change at line 3154
mask = LC_MESSAGES_MASK; mask = LC_MESSAGES_MASK;
break; break;
default: /* We shouldn't get here. */ default: /* We shouldn't get here. */
return ""; return "";
} }
return querylocale (mask, thread_locale); return querylocale (mask, thread_locale);
# elif defined __sun # elif defined __sun
# if HAVE_GETLOCALENAME_L # if HAVE_GETLOCALENAME_L
/* Solaris >= 12. */ /* Solaris >= 12. */
return getlocalename_l (category, thread_locale); return getlocalename_l (category, thread_locale);
# elif HAVE_SOLARIS114_LOCALES
/* Solaris >= 11.4. */
void *lcp = (*thread_locale)->core.data->lcp;
if (lcp != NULL)
switch (category)
{
case LC_CTYPE:
case LC_NUMERIC:
case LC_TIME:
case LC_COLLATE:
case LC_MONETARY:
case LC_MESSAGES:
return ((const char * const *) lcp)[category];
default: /* We shouldn't get here. */
return "";
}
# elif HAVE_NAMELESS_LOCALES
return get_locale_t_name (category, thread_locale);
# else # else
/* Solaris 11 OpenIndiana. /* Solaris 11 OpenIndiana.
For the internal structure of locale objects, see For the internal structure of locale objects, see
https://github.com/OpenIndiana/illumos-gate/blob/master/usr/src/lib/l ibc/port/locale/localeimpl.h */ https://github.com/OpenIndiana/illumos-gate/blob/master/usr/src/lib/l ibc/port/locale/localeimpl.h */
switch (category) switch (category)
{ {
case LC_CTYPE: case LC_CTYPE:
case LC_NUMERIC: case LC_NUMERIC:
case LC_TIME: case LC_TIME:
case LC_COLLATE: case LC_COLLATE:
skipping to change at line 2781 skipping to change at line 3216
} }
# endif # endif
return NULL; return NULL;
} }
#endif #endif
const char * const char *
gl_locale_name_thread (int category, const char *categoryname) gl_locale_name_thread (int category, const char *categoryname)
{ {
#if HAVE_USELOCALE #if HAVE_GOOD_USELOCALE
const char *name = gl_locale_name_thread_unsafe (category, categoryname); const char *name = gl_locale_name_thread_unsafe (category, categoryname);
if (name != NULL) if (name != NULL)
return struniq (name); return struniq (name);
#endif #endif
/* On WINDOWS_NATIVE, don't use GetThreadLocale() here, because when /* On WINDOWS_NATIVE, don't use GetThreadLocale() here, because when
SetThreadLocale has not been called - which is a very frequent case - SetThreadLocale has not been called - which is a very frequent case -
the value of GetThreadLocale() ignores past calls to 'setlocale'. */ the value of GetThreadLocale() ignores past calls to 'setlocale'. */
return NULL; return NULL;
} }
skipping to change at line 2808 skipping to change at line 3243
#if defined _LIBC || ((defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC __) #if defined _LIBC || ((defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC __)
# define HAVE_LOCALE_NULL # define HAVE_LOCALE_NULL
#endif #endif
const char * const char *
gl_locale_name_posix (int category, const char *categoryname) gl_locale_name_posix (int category, const char *categoryname)
{ {
#if defined WINDOWS_NATIVE #if defined WINDOWS_NATIVE
if (LC_MIN <= category && category <= LC_MAX) if (LC_MIN <= category && category <= LC_MAX)
{ {
char *locname = setlocale (category, NULL); const char *locname = setlocale (category, NULL);
LCID lcid = 0; LCID lcid;
/* If CATEGORY is LC_ALL, the result might be a semi-colon /* If CATEGORY is LC_ALL, the result might be a semi-colon
separated list of locales. We need only one, so we take the separated list of locales. We need only one, so we take the
one corresponding to LC_CTYPE, as the most important for one corresponding to LC_CTYPE, as the most important for
character translations. */ character translations. */
if (category == LC_ALL && strchr (locname, ';')) if (category == LC_ALL && strchr (locname, ';'))
locname = setlocale (LC_CTYPE, NULL); locname = setlocale (LC_CTYPE, NULL);
/* Convert locale name to LCID. We don't want to use /* Convert locale name to LCID. We don't want to use
LocaleNameToLCID because (a) it is only available since Vista, LocaleNameToLCID because (a) it is only available since Vista,
and (b) it doesn't accept locale names returned by 'setlocale'. */ and (b) it doesn't accept locale names returned by 'setlocale'. */
lcid = get_lcid (locname); lcid = get_lcid (locname);
if (lcid > 0) if (lcid > 0)
return gl_locale_name_from_win32_LCID (lcid); return gl_locale_name_from_win32_LCID (lcid);
} }
#endif #endif
/* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'. {
On some systems this can be done by the 'setlocale' function itself. */ const char *locname;
/* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
On some systems this can be done by the 'setlocale' function itself. */
#if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NU LL #if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NU LL
return setlocale (category, NULL); locname = setlocale (category, NULL);
#else #else
/* On other systems we ignore what setlocale reports and instead look at the /* On other systems we ignore what setlocale reports and instead look at the
environment variables directly. This is necessary environment variables directly. This is necessary
1. on systems which have a facility for customizing the default locale 1. on systems which have a facility for customizing the default locale
(Mac OS X, native Windows, Cygwin) and where the system's setlocale() (Mac OS X, native Windows, Cygwin) and where the system's setlocale(
function ignores this default locale (Mac OS X, Cygwin), in two cases: )
a. when the user missed to use the setlocale() override from libintl function ignores this default locale (Mac OS X, Cygwin), in two case
(for example by not including <libintl.h>), s:
b. when setlocale supports only the "C" locale, such as on Cygwin a. when the user missed to use the setlocale() override from libintl
1.5.x. In this case even the override from libintl cannot help. (for example by not including <libintl.h>),
2. on all systems where setlocale supports only the "C" locale. */ b. when setlocale supports only the "C" locale, such as on Cygwin
/* Strictly speaking, it is a POSIX violation to look at the environment 1.5.x. In this case even the override from libintl cannot help.
variables regardless whether setlocale has been called or not. POSIX 2. on all systems where setlocale supports only the "C" locale. */
says: /* Strictly speaking, it is a POSIX violation to look at the environment
"For C-language programs, the POSIX locale shall be the variables regardless whether setlocale has been called or not. POSIX
default locale when the setlocale() function is not called." says:
But we assume that all programs that use internationalized APIs call "For C-language programs, the POSIX locale shall be the
setlocale (LC_ALL, ""). */ default locale when the setlocale() function is not called."
return gl_locale_name_environ (category, categoryname); But we assume that all programs that use internationalized APIs call
setlocale (LC_ALL, ""). */
locname = gl_locale_name_environ (category, categoryname);
#endif #endif
/* Convert the locale name from the format returned by setlocale() or found
in the environment variables to the XPG syntax. */
#if defined WINDOWS_NATIVE
{
/* Convert locale name to LCID. We don't want to use
LocaleNameToLCID because (a) it is only available since Vista,
and (b) it doesn't accept locale names returned by 'setlocale'. */
LCID lcid = get_lcid (locname);
if (lcid > 0)
return gl_locale_name_from_win32_LCID (lcid);
}
#endif
return locname;
}
} }
const char * const char *
gl_locale_name_environ (int category, const char *categoryname) gl_locale_name_environ (int category, const char *categoryname)
{ {
const char *retval; const char *retval;
/* Setting of LC_ALL overrides all other. */ /* Setting of LC_ALL overrides all other. */
retval = getenv ("LC_ALL"); retval = getenv ("LC_ALL");
if (retval != NULL && retval[0] != '\0') if (retval != NULL && retval[0] != '\0')
skipping to change at line 2931 skipping to change at line 3384
return "C"; return "C";
#else #else
/* Return an XPG style locale name language[_territory][@modifier]. /* Return an XPG style locale name language[_territory][@modifier].
Don't even bother determining the codeset; it's not useful in this Don't even bother determining the codeset; it's not useful in this
context, because message catalogs are not specific to a single context, because message catalogs are not specific to a single
codeset. */ codeset. */
# if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE # if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
/* Mac OS X 10.2 or newer */ /* Mac OS X 10.4 or newer */
{ {
/* Cache the locale name, since CoreFoundation calls are expensive. */ /* Cache the locale name, since CoreFoundation calls are expensive. */
static const char *cached_localename; static const char *cached_localename;
if (cached_localename == NULL) if (cached_localename == NULL)
{ {
char namebuf[256]; char namebuf[256];
# if HAVE_CFLOCALECOPYCURRENT /* Mac OS X 10.3 or newer */ # if HAVE_CFLOCALECOPYCURRENT /* Mac OS X 10.5 or newer */
CFLocaleRef locale = CFLocaleCopyCurrent (); CFLocaleRef locale = CFLocaleCopyCurrent ();
CFStringRef name = CFLocaleGetIdentifier (locale); CFStringRef name = CFLocaleGetIdentifier (locale);
# elif HAVE_CFPREFERENCESCOPYAPPVALUE /* Mac OS X 10.4 or newer */
if (CFStringGetCString (name, namebuf, sizeof (namebuf),
kCFStringEncodingASCII))
{
gl_locale_name_canonicalize (namebuf);
cached_localename = strdup (namebuf);
}
CFRelease (locale);
# elif HAVE_CFPREFERENCESCOPYAPPVALUE /* Mac OS X 10.2 or newer */
CFTypeRef value = CFTypeRef value =
CFPreferencesCopyAppValue (CFSTR ("AppleLocale"), CFPreferencesCopyAppValue (CFSTR ("AppleLocale"),
kCFPreferencesCurrentApplication); kCFPreferencesCurrentApplication);
if (value != NULL if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
&& CFGetTypeID (value) == CFStringGetTypeID ()
&& CFStringGetCString ((CFStringRef)value,
namebuf, sizeof (namebuf),
kCFStringEncodingASCII))
{ {
gl_locale_name_canonicalize (namebuf); CFStringRef name = (CFStringRef)value;
cached_localename = strdup (namebuf); # endif
if (CFStringGetCString (name, namebuf, sizeof (namebuf),
kCFStringEncodingASCII))
{
gl_locale_name_canonicalize (namebuf);
cached_localename = strdup (namebuf);
}
# if HAVE_CFLOCALECOPYCURRENT /* Mac OS X 10.5 or newer */
CFRelease (locale);
# elif HAVE_CFPREFERENCESCOPYAPPVALUE /* Mac OS X 10.4 or newer */
} }
# endif # endif
if (cached_localename == NULL) if (cached_localename == NULL)
cached_localename = "C"; cached_localename = "C";
} }
return cached_localename; return cached_localename;
} }
# endif # endif
 End of changes. 31 change blocks. 
59 lines changed or deleted 516 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)