about summary refs log tree commit diff
path: root/intl
diff options
context:
space:
mode:
Diffstat (limited to 'intl')
-rw-r--r--intl/Makefile15
-rw-r--r--intl/dcgettext.c15
-rw-r--r--intl/finddomain.c221
-rw-r--r--intl/gettext.c2
-rw-r--r--intl/libintl.h109
-rw-r--r--intl/loadmsgcat.c7
-rw-r--r--intl/localealias.c10
7 files changed, 268 insertions, 111 deletions
diff --git a/intl/Makefile b/intl/Makefile
index f7ef998fca..6e588fc88a 100644
--- a/intl/Makefile
+++ b/intl/Makefile
@@ -19,6 +19,7 @@
 # Cambridge, MA 02139, USA.
 
 subdir = intl
+headers = libintl.h
 routines = bindtextdom dcgettext dgettext gettext	\
 	   finddomain loadmsgcat localealias textdomain
 distribute = gettext.h gettextP.h hash-string.h
@@ -27,3 +28,17 @@ include ../Rules
 
 CPPFLAGS += -D'GNULOCALEDIR="$(localedir)"' \
 	    -D'LOCALE_ALIAS_PATH="$(localedir):$(nlsdir)"'
+
+ifdef gettext-srcdir
+
+%:: $(gettext-srcdir)/intl/%.glibc; $(copysrc)
+%:: $(gettext-srcdir)/intl/%; $(copysrc)
+
+define copysrc
+cp -f $< $@.new
+chmod a-w $@.new
+mv -f $@.new $@
+test ! -d CVS || cvs commit -m'Updated from $<' $@
+endef
+
+endif
diff --git a/intl/dcgettext.c b/intl/dcgettext.c
index 91025be89b..09e0443494 100644
--- a/intl/dcgettext.c
+++ b/intl/dcgettext.c
@@ -317,14 +317,13 @@ DCGETTEXT (domainname, msgid, category)
 	    {
 	      int cnt;
 
-	      for (cnt = 6; cnt >= 0 && retval == NULL; --cnt)
-		if (domain->successor[cnt] != NULL)
-		  {
-		    retval = find_msg (domain->successor[cnt], msgid);
-
- 		    if (domain->successor[cnt]->data == NULL)
-		      domain->successor[cnt] = NULL;
-		  }
+	      for (cnt = 0; domain->successor[cnt] != NULL; --cnt)
+		{
+		  retval = find_msg (domain->successor[cnt], msgid);
+
+		  if (retval != NULL)
+		    break;
+		}
 	    }
 
 	  if (retval != NULL)
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
diff --git a/intl/gettext.c b/intl/gettext.c
index 204d85ecd4..7bed6369b4 100644
--- a/intl/gettext.c
+++ b/intl/gettext.c
@@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #  ifdef HAVE_STRING_H
 #   include <string.h>
 #  else
-#   define NULL 0
+#   define NULL ((void *) 0)
 #  endif
 # endif
 #endif
diff --git a/intl/libintl.h b/intl/libintl.h
new file mode 100644
index 0000000000..f9a150d3df
--- /dev/null
+++ b/intl/libintl.h
@@ -0,0 +1,109 @@
+/* libgettext.h -- Message catalogs for internationalization.
+Copyright (C) 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper.
+This file is derived from the file libgettext.h in the GNU gettext package.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#ifndef _LIBINTL_H
+#define _LIBINTL_H	1
+#include <features.h>
+
+#include <locale.h>
+
+#define __need_NULL
+#include <stddef.h>
+
+/* We define an additional symbol to signal that we use the GNU
+   implementation of gettext.  */
+#define __USE_GNU_GETTEXT 1
+
+__BEGIN_DECLS
+
+/* Look up MSGID in the current default message catalog for the current
+   LC_MESSAGES locale.  If not found, returns MSGID itself (the default
+   text).  */
+extern char *gettext __P ((const char *__msgid));
+extern char *__gettext __P ((const char *__msgid));
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current
+   LC_MESSAGES locale.  */
+extern char *dgettext __P ((const char *__domainname, const char *__msgid));
+extern char *__dgettext __P ((const char *__domainname, const char *__msgid));
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
+   locale.  */
+extern char *dcgettext __P ((const char *__domainname, const char *__msgid,
+			     int __category));
+extern char *__dcgettext __P ((const char *__domainname, const char *__msgid,
+			       int __category));
+
+
+/* Set the current default message catalog to DOMAINNAME.
+   If DOMAINNAME is null, return the current default.
+   If DOMAINNAME is "", reset to the default of "messages".  */
+extern char *textdomain __P ((const char *__domainname));
+extern char *__textdomain __P ((const char *__domainname));
+
+/* Specify that the DOMAINNAME message catalog will be found
+   in DIRNAME rather than in the system locale data base.  */
+extern char *bindtextdomain __P ((const char *__domainname,
+				  const char *__dirname));
+extern char *__bindtextdomain __P ((const char *__domainname,
+				    const char *__dirname));
+
+
+/* Optimized version of the function above.  */
+#if defined __OPTIMIZED
+/* These must be a macro.  Inlined functions are useless because the
+   `__builtin_constant_p' predicate in dcgettext would always return
+   false.  */
+
+# define gettext (msgid) dgettext (NULL, msgid)
+
+# define dgettext (domainname, msgid)					      \
+  dcgettext (domainname, msgid, LC_MESSAGES)
+
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+#  define dcgettext(domainname, msgid, category)			      \
+  (__extension__							      \
+   ({									      \
+     char *result;							      \
+     if (__builtin_constant_p (msgid))					      \
+       {								      \
+	 extern int _nl_msg_cat_cntr;					      \
+	 static char *__translation__;					      \
+	 static int __catalog_counter__;				      \
+	 if (! __translation__ || __catalog_counter__ != _nl_msg_cat_cntr)    \
+	   {								      \
+	     __translation__ =						      \
+	       __dcgettext ((domainname), (msgid), (category));		      \
+	     __catalog_counter__ = _nl_msg_cat_cntr;			      \
+	   }								      \
+	 result = __translation__;					      \
+       }								      \
+     else								      \
+       result = __dcgettext ((domainname), (msgid), (category));	      \
+     result;								      \
+    }))
+# endif
+#endif /* Optimizing. */
+
+
+__END_DECLS
+
+#endif /* libintl.h */
diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c
index b05c630724..d98f365bf9 100644
--- a/intl/loadmsgcat.c
+++ b/intl/loadmsgcat.c
@@ -75,6 +75,13 @@ _nl_load_domain (domain)
   domain->decided = 1;
   domain->data = NULL;
 
+  /* If the record does not represent a valid locale the FILENAME
+     might be NULL.  This can happen when according to the given
+     specification the locale file name is different for XPG and CEN
+     syntax.  */
+  if (domain->filename == NULL)
+    return;
+
   /* Try to open the addressed file.  */
   fd = open (domain->filename, O_RDONLY);
   if (fd == -1)
diff --git a/intl/localealias.c b/intl/localealias.c
index fc3bc1238b..47f2cbffa8 100644
--- a/intl/localealias.c
+++ b/intl/localealias.c
@@ -1,5 +1,5 @@
 /* localealias.c -- handle aliases for locale names
-   Copyright (C) 1995 Software Foundation, Inc.
+   Copyright (C) 1995 Free Software Foundation, Inc.
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -125,7 +125,7 @@ _nl_expand_alias (name)
 	{
 	  const char *start;
 
-	  while (locale_alias_path[0] != '\0' && locale_alias_path[0] == ':')
+	  while (locale_alias_path[0] == ':')
 	    ++locale_alias_path;
 	  start = locale_alias_path;
 
@@ -239,7 +239,7 @@ read_alias_file (fname, fname_len)
 	    }
 	}
 
-      /* Possibily not the whole line fits into the buffer.  Ignore
+      /* Possibily not the whole line fitted into the buffer.  Ignore
 	 the rest of the line.  */
       while (strchr (cp, '\n') == NULL)
 	{
@@ -305,8 +305,8 @@ alias_compare (map1, map2)
     {
       /* I know this seems to be odd but the tolower() function in
 	 some systems libc cannot handle nonalpha characters.  */
-      c1 = isalpha (*p1) ? tolower (*p1) : *p1;
-      c2 = isalpha (*p2) ? tolower (*p2) : *p2;
+      c1 = isupper (*p1) ? tolower (*p1) : *p1;
+      c2 = isupper (*p2) ? tolower (*p2) : *p2;
       if (c1 == '\0')
 	break;
     }