about summary refs log tree commit diff
path: root/locale/setlocale.c
diff options
context:
space:
mode:
Diffstat (limited to 'locale/setlocale.c')
-rw-r--r--locale/setlocale.c147
1 files changed, 81 insertions, 66 deletions
diff --git a/locale/setlocale.c b/locale/setlocale.c
index 1482465f43..f053895573 100644
--- a/locale/setlocale.c
+++ b/locale/setlocale.c
@@ -34,16 +34,17 @@
    This contains the built-in "C"/"POSIX" locale's data for CATEGORY.
    Both are weak references; if &_nl_current_CATEGORY is zero,
    then nothing is using the locale data.  */
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
 extern struct locale_data *_nl_current_##category;			      \
 extern struct locale_data _nl_C_##category;
 #include "categories.def"
 #undef	DEFINE_CATEGORY
 
-/* Array indexed by category of pointers to _nl_current_CATEGORY slots.  */
+/* Array indexed by category of pointers to _nl_current_CATEGORY slots.
+   Elements are zero for categories whose data is never used.  */
 struct locale_data * *const _nl_current[] =
   {
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
     [category] = &_nl_current_##category,
 #include "categories.def"
 #undef	DEFINE_CATEGORY
@@ -56,7 +57,7 @@ struct locale_data * *const _nl_current[] =
    Elements are zero for categories whose data is never used.  */
 struct locale_data *const _nl_C[] =
   {
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
     [category] = &_nl_C_##category,
 #include "categories.def"
 #undef	DEFINE_CATEGORY
@@ -64,14 +65,10 @@ struct locale_data *const _nl_C[] =
 
 
 /* Define an array of category names (also the environment variable names),
-   indexed by integral category.
-
-   We have entries of fixed width (16 for now) do avoid an array of
-   pointers.  Update the size of the outer array if new, longer locale
-   names are introduced.  */
-const char _nl_category_names[][16] =
+   indexed by integral category.  */
+const char *const _nl_category_names[] =
   {
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
     [category] = category_name,
 #include "categories.def"
 #undef	DEFINE_CATEGORY
@@ -80,7 +77,7 @@ const char _nl_category_names[][16] =
 /* An array of their lengths, for convenience.  */
 const size_t _nl_category_name_sizes[] =
   {
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
     [category] = sizeof (category_name) - 1,
 #include "categories.def"
 #undef	DEFINE_CATEGORY
@@ -91,7 +88,7 @@ const size_t _nl_category_name_sizes[] =
 /* Declare the postload functions used below.  */
 #undef	NO_POSTLOAD
 #define NO_POSTLOAD _nl_postload_ctype /* Harmless thing known to exist.  */
-#define DEFINE_CATEGORY(category, category_name, items, postload, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, postload) \
 extern void postload (void);
 #include "categories.def"
 #undef	DEFINE_CATEGORY
@@ -101,7 +98,7 @@ extern void postload (void);
    loading and installing that category's data.  */
 static void (*const _nl_category_postload[]) (void) =
   {
-#define DEFINE_CATEGORY(category, category_name, items, postload, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, postload) \
     [category] = postload,
 #include "categories.def"
 #undef	DEFINE_CATEGORY
@@ -112,7 +109,7 @@ static void (*const _nl_category_postload[]) (void) =
    Each is malloc'd unless it is nl_C_name.  */
 static const char *_nl_current_names[] =
   {
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
     [category] = _nl_C_name,
 #include "categories.def"
 #undef	DEFINE_CATEGORY
@@ -134,7 +131,7 @@ __libc_lock_define_initialized (, __libc_setlocale_lock)
 
 /* Construct a new composite name.  */
 static inline char *
-new_composite_name (int category, const char *newnames[LC_ALL])
+new_composite_name (int category, const char *newnames[__LC_LAST])
 {
   size_t last_len = 0;
   size_t cumlen = 0;
@@ -142,22 +139,23 @@ new_composite_name (int category, const char *newnames[LC_ALL])
   char *new, *p;
   int same = 1;
 
-  for (i = 0; i < LC_ALL; ++i)
-    {
-      const char *name = (category == LC_ALL ? newnames[i] :
-			  category == i ? newnames[0] :
-			  _nl_current_names[i]);
-      last_len = strlen (name);
-      cumlen += _nl_category_name_sizes[i] + 1 + last_len + 1;
-      if (same && strcmp (name, newnames[0]) != 0)
-	same = 0;
-    }
+  for (i = 0; i < __LC_LAST; ++i)
+    if (i != LC_ALL)
+      {
+	const char *name = (category == LC_ALL ? newnames[i] :
+			    category == i ? newnames[0] :
+			    _nl_current_names[i]);
+	last_len = strlen (name);
+	cumlen += _nl_category_name_sizes[i] + 1 + last_len + 1;
+	if (i > 0 && same && strcmp (name, newnames[0]) != 0)
+	  same = 0;
+      }
 
   if (same)
     {
       /* All the categories use the same name.  */
-      if (strcmp (newnames[0], _nl_C_name) == 0
-	  || strcmp (newnames[0], _nl_POSIX_name) == 0)
+      if (strcmp (newnames[0], "C") == 0
+	  || strcmp (newnames[0], "POSIX") == 0)
 	return (char *) _nl_C_name;
 
       new = malloc (last_len + 1);
@@ -169,17 +167,18 @@ new_composite_name (int category, const char *newnames[LC_ALL])
   if (new == NULL)
     return NULL;
   p = new;
-  for (i = 0; i < LC_ALL; ++i)
-    {
-      /* Add "CATEGORY=NAME;" to the string.  */
-      const char *name = (category == LC_ALL ? newnames[i] :
-			  category == i ? newnames[0] :
-			  _nl_current_names[i]);
-      p = __stpcpy (p, _nl_category_names[i]);
-      *p++ = '=';
-      p = __stpcpy (p, name);
-      *p++ = ';';
-    }
+  for (i = 0; i < __LC_LAST; ++i)
+    if (i != LC_ALL)
+      {
+	/* Add "CATEGORY=NAME;" to the string.  */
+	const char *name = (category == LC_ALL ? newnames[i] :
+			    category == i ? newnames[0] :
+			    _nl_current_names[i]);
+	p = __stpcpy (p, _nl_category_names[i]);
+	*p++ = '=';
+	p = __stpcpy (p, name);
+	*p++ = ';';
+      }
   p[-1] = '\0';		/* Clobber the last ';'.  */
   return new;
 }
@@ -221,7 +220,7 @@ setlocale (int category, const char *locale)
   char *composite;
 
   /* Sanity check for CATEGORY argument.  */
-  if (category < 0 || category > LC_ALL)
+  if (category < 0 || category >= __LC_LAST)
     ERROR_RETURN;
 
   /* Does user want name of current locale?  */
@@ -254,12 +253,13 @@ setlocale (int category, const char *locale)
 	 for the individual categories can be selected by using a
 	 composite locale name.  This is a semi-colon separated list
 	 of entries of the form `CATEGORY=VALUE'.  */
-      const char *newnames[LC_ALL];
-      struct locale_data *newdata[LC_ALL];
+      const char *newnames[__LC_LAST];
+      struct locale_data *newdata[__LC_LAST];
 
       /* Set all name pointers to the argument name.  */
-      for (category = 0; category < LC_ALL; ++category)
-	newnames[category] = (char *) locale;
+      for (category = 0; category < __LC_LAST; ++category)
+	if (category != LC_ALL)
+	  newnames[category] = (char *) locale;
 
       if (strchr (locale, ';') != NULL)
 	{
@@ -270,12 +270,13 @@ setlocale (int category, const char *locale)
 
 	  while ((cp = strchr (np, '=')) != NULL)
 	    {
-	      for (cnt = 0; cnt < LC_ALL; ++cnt)
-		if ((size_t) (cp - np) == _nl_category_name_sizes[cnt]
+	      for (cnt = 0; cnt < __LC_LAST; ++cnt)
+		if (cnt != LC_ALL
+		    && (size_t) (cp - np) == _nl_category_name_sizes[cnt]
 		    && memcmp (np, _nl_category_names[cnt], cp - np) == 0)
 		  break;
 
-	      if (cnt == LC_ALL)
+	      if (cnt == __LC_LAST)
 		/* Bogus category name.  */
 		ERROR_RETURN;
 
@@ -293,8 +294,8 @@ setlocale (int category, const char *locale)
 		break;
 	    }
 
-	  for (cnt = 0; cnt < LC_ALL; ++cnt)
-	    if (newnames[cnt] == locale)
+	  for (cnt = 0; cnt < __LC_LAST; ++cnt)
+	    if (cnt != LC_ALL && newnames[cnt] == locale)
 	      /* The composite name did not specify all categories.  */
 	      ERROR_RETURN;
 	}
@@ -305,6 +306,13 @@ setlocale (int category, const char *locale)
       /* Load the new data for each category.  */
       while (category-- > 0)
 	{
+	  /* XXX hack.  Remove when collation works.  */
+	  if (category == LC_COLLATE)
+	    {
+	      newdata[category] = NULL;
+	      continue;
+	    }
+
 	  newdata[category] = _nl_find_locale (locale_path, locale_path_len,
 					       category,
 					       &newnames[category]);
@@ -327,11 +335,12 @@ setlocale (int category, const char *locale)
       else
 	{
 	  /* Now we have loaded all the new data.  Put it in place.  */
-	  for (category = 0; category < LC_ALL; ++category)
-	    {
-	      setdata (category, newdata[category]);
-	      setname (category, newnames[category]);
-	    }
+	  for (category = 0; category < __LC_LAST; ++category)
+	    if (category != LC_ALL)
+	      {
+		setdata (category, newdata[category]);
+		setname (category, newnames[category]);
+	      }
 	  setname (LC_ALL, composite);
 	}
 
@@ -343,6 +352,11 @@ setlocale (int category, const char *locale)
 
       return composite;
     }
+  else if (category == LC_COLLATE)
+    {
+      /* XXX Remove when LC_COLLATE works.  */
+      return NULL;
+    }
   else
     {
       struct locale_data *newdata = NULL;
@@ -401,21 +415,22 @@ free_mem (void)
 {
   int category;
 
-  for (category = 0; category < LC_ALL; ++category)
-    {
-      struct locale_data *here = *_nl_current[category];
+  for (category = 0; category < __LC_LAST; ++category)
+    if (category != LC_ALL)
+      {
+	struct locale_data *here = *_nl_current[category];
 
-      /* If this category is already "C" don't do anything.  */
-      if (here == _nl_C[category])
-	continue;
+	/* If this category is already "C" don't do anything.  */
+	if (here == _nl_C[category])
+	  continue;
 
-      /* We have to be prepared that sometime later me still might
-	 need the locale information.  */
-      setdata (category, _nl_C[category]);
-      setname (category, _nl_C_name);
+	/* We have to be prepared that sometime later me still might
+	   need the locale information.  */
+	setdata (category, _nl_C[category]);
+	setname (category, _nl_C_name);
 
-      _nl_unload_locale (here);
-    }
+	_nl_unload_locale (here);
+      }
 
   setname (LC_ALL, _nl_C_name);
 }