about summary refs log tree commit diff
path: root/intl/finddomain.c
diff options
context:
space:
mode:
Diffstat (limited to 'intl/finddomain.c')
-rw-r--r--intl/finddomain.c221
1 files changed, 124 insertions, 97 deletions
diff --git a/intl/finddomain.c b/intl/finddomain.c
index 19cf2d7581..007a87e075 100644
--- a/intl/finddomain.c
+++ b/intl/finddomain.c
@@ -95,6 +95,11 @@ static struct loaded_domain *make_entry_rec __P ((const char *dirname,
 						  const char *domainname,
 						  int do_allocate));
 
+/* Substitution for systems lacking this function in their C library.  */
+#if !_LIBC && !HAVE_STPCPY
+static char *stpcpy __P ((char *dest, const char *src));
+#endif
+
 
 /* Return a data structure describing the message catalog described by
    the DOMAINNAME and CATEGORY parameters with respect to the currently
@@ -155,9 +160,9 @@ _nl_find_domain (dirname, locale, domainname)
       if (retval->data != NULL)
 	return retval;
 
-      for (cnt = 6; cnt >= 0; --cnt)
+      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
 	{
-	  if (retval->successor[cnt] == 0)
+	  if (retval->successor[cnt]->decided == 0)
 	    _nl_load_domain (retval->successor[cnt]);
 
 	  if (retval->successor[cnt]->data != NULL)
@@ -279,13 +284,13 @@ _nl_find_domain (dirname, locale, domainname)
      separator character in the file name, not for XPG syntax.  */
   if (syntax == xpg)
     {
-      if (territory[0] == '\0')
+      if (territory != NULL && territory[0] == '\0')
 	mask &= ~TERRITORY;
 
-      if (codeset[0] == '\0')
+      if (codeset != NULL && codeset[0] == '\0')
 	mask &= ~XPG_CODESET;
 
-      if (modifier[0] == '\0')
+      if (modifier != NULL && modifier[0] == '\0')
 	mask &= ~XPG_MODIFIER;
     }
 
@@ -340,107 +345,110 @@ make_entry_rec (dirname, mask, language, territory, codeset, modifier,
      const char *domain;
      int do_allocate;
 {
-  struct loaded_domain *retval, *last;
-  char *filename, *cp;
+  char *filename = NULL;
+  struct loaded_domain *last = NULL;
+  struct loaded_domain *retval;
+  char *cp;
   size_t entries;
   int cnt;
 
-  /* Allocate room for the full file name.  */
-  filename = (char *) malloc (strlen (dirname) + 1
-			      + strlen (language)
-			      + ((mask & TERRITORY) != 0
-				 ? strlen (territory) : 0)
-			      + ((mask & XPG_CODESET) != 0
-				 ? strlen (codeset) : 0)
-			      + ((mask & XPG_MODIFIER) != 0 ?
-				 strlen (modifier) : 0)
-			      + ((mask & CEN_SPECIAL) != 0
-				 ? strlen (special) : 0)
-			      + ((mask & CEN_SPONSOR) != 0
-				 ? strlen (sponsor) : 0)
-			      + ((mask & CEN_REVISION) != 0
-				 ? strlen (revision) : 0) + 1
-			      + strlen (domain) + 1);
-
-  if (filename == NULL)
-    return NULL;
 
-  retval = NULL;
-  last = NULL;
+  /* Process the current entry described by the MASK only when it is
+     valid.  Because the mask can have in the first call bits from
+     both syntaces set this is necessary to prevent constructing
+     illegal local names.  */
+  /* FIXME: Rewrite because test is necessary only in first round.  */
+  if ((mask & CEN_SPECIFIC) == 0 || (mask & XPG_SPECIFIC) == 0)
+    {
+      /* Allocate room for the full file name.  */
+      filename = (char *) malloc (strlen (dirname) + 1
+				  + strlen (language)
+				  + ((mask & TERRITORY) != 0
+				     ? strlen (territory) : 0)
+				  + ((mask & XPG_CODESET) != 0
+				     ? strlen (codeset) : 0)
+				  + ((mask & XPG_MODIFIER) != 0 ?
+				     strlen (modifier) : 0)
+				  + ((mask & CEN_SPECIAL) != 0
+				     ? strlen (special) : 0)
+				  + ((mask & CEN_SPONSOR) != 0
+				     ? strlen (sponsor) : 0)
+				  + ((mask & CEN_REVISION) != 0
+				     ? strlen (revision) : 0) + 1
+				  + strlen (domain) + 1);
+
+      if (filename == NULL)
+	return NULL;
 
-  /* We don't want libintl.a to depend on any other library.  So we
-     avoid the non-standard function stpcpy.  In GNU C Library this
-     function is available, though.  Also allow the symbol HAVE_STPCPY
-     to be defined.  */
-#if !defined _LIBC && !defined HAVE_STPCPY
-# define stpcpy(p, s)							    \
-  (strcpy (p, s), strchr (p, '\0'))
-#endif
+      retval = NULL;
+      last = NULL;
 
-  /* Construct file name.  */
-  cp = stpcpy (filename, dirname);
-  *cp++ = '/';
-  cp = stpcpy (cp, language);
+      /* Construct file name.  */
+      cp = stpcpy (filename, dirname);
+      *cp++ = '/';
+      cp = stpcpy (cp, language);
 
-  if ((mask & TERRITORY) != 0)
-    {
-      *cp++ = '_';
-      cp = stpcpy (cp, territory);
-    }
-  if ((mask & XPG_CODESET) != 0)
-    {
-      *cp++ = '.';
+      if ((mask & TERRITORY) != 0)
+	{
+	  *cp++ = '_';
+	  cp = stpcpy (cp, territory);
+	}
+      if ((mask & XPG_CODESET) != 0)
+	{
+	  *cp++ = '.';
       cp = stpcpy (cp, codeset);
-    }
-  if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
-    {
-      /* This component can be part of both syntaces but has different
-	 leading characters.  For CEN we use `+', else `@'.  */
-      *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
-      cp = stpcpy (cp, modifier);
-    }
-  if ((mask & CEN_SPECIAL) != 0)
-    {
-      *cp++ = '+';
-      cp = stpcpy (cp, special);
-    }
-  if ((mask & CEN_SPONSOR) != 0)
-    {
-      *cp++ = ',';
-      cp = stpcpy (cp, sponsor);
-    }
-  if ((mask & CEN_REVISION) != 0)
-    {
-      *cp++ = '_';
-      cp = stpcpy (cp, revision);
-    }
-
-  *cp++ = '/';
-  stpcpy (cp, domain);
-
-  /* Look in list of already loaded domains whether it is already
-     available.  */
-  last = NULL;
-  for (retval = _nl_loaded_domains; retval != NULL; retval = retval->next)
-    {
-      int compare = strcmp (retval->filename, filename);
-      if (compare == 0)
-	/* We found it!  */
-	break;
-      if (compare < 0)
+	}
+      if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
 	{
-	  /* It's not in the list.  */
-	  retval = NULL;
-	  break;
+	  /* This component can be part of both syntaces but has different
+	     leading characters.  For CEN we use `+', else `@'.  */
+	  *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
+	  cp = stpcpy (cp, modifier);
+	}
+      if ((mask & CEN_SPECIAL) != 0)
+	{
+	  *cp++ = '+';
+	  cp = stpcpy (cp, special);
+	}
+      if ((mask & CEN_SPONSOR) != 0)
+	{
+	  *cp++ = ',';
+	  cp = stpcpy (cp, sponsor);
+	}
+      if ((mask & CEN_REVISION) != 0)
+	{
+	  *cp++ = '_';
+	  cp = stpcpy (cp, revision);
 	}
 
-      last = retval;
-    }
-
-  if (retval != NULL || do_allocate == 0)
-    {
-      free (filename);
-      return retval;
+      *cp++ = '/';
+      stpcpy (cp, domain);
+
+      /* Look in list of already loaded domains whether it is already
+	 available.  */
+      last = NULL;
+      for (retval = _nl_loaded_domains; retval != NULL; retval = retval->next)
+	if (retval->filename != NULL)
+	  {
+	    int compare = strcmp (retval->filename, filename);
+	    if (compare == 0)
+	      /* We found it!  */
+	      break;
+	    if (compare < 0)
+	      {
+		/* It's not in the list.  */
+		retval = NULL;
+		break;
+	      }
+
+	    last = retval;
+	  }
+
+      if (retval != NULL || do_allocate == 0)
+	{
+	  free (filename);
+	  return retval;
+	}
     }
 
   retval = (struct loaded_domain *) malloc (sizeof (*retval));
@@ -453,8 +461,8 @@ make_entry_rec (dirname, mask, language, territory, codeset, modifier,
   if (last == NULL)
     {
       retval->next = _nl_loaded_domains;
-     _nl_loaded_domains = retval;
-     }
+      _nl_loaded_domains = retval;
+    }
   else
     {
       retval->next = last->next;
@@ -474,3 +482,22 @@ make_entry_rec (dirname, mask, language, territory, codeset, modifier,
 
   return retval;
 }
+
+
+/* @@ begin of epilog @@ */
+
+/* We don't want libintl.a to depend on any other library.  So we
+   avoid the non-standard function stpcpy.  In GNU C Library this
+   function is available, though.  Also allow the symbol HAVE_STPCPY
+   to be defined.  */
+#if !_LIBC && !HAVE_STPCPY
+static char *
+stpcpy (dest, src)
+     char *dest;
+     const char *src;
+{
+  while ((*dest++ = *src++) != '\0')
+    /* Do nothing. */ ;
+  return dest - 1;
+}
+#endif