about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog90
-rw-r--r--intl/Makefile4
-rw-r--r--intl/bindtextdom.c21
-rw-r--r--intl/dcigettext.c166
-rw-r--r--intl/dgettext.c4
-rw-r--r--intl/dngettext.c4
-rw-r--r--intl/explodename.c11
-rw-r--r--intl/finddomain.c21
-rw-r--r--intl/gettext.c10
-rw-r--r--intl/gettext.h4
-rw-r--r--intl/gettextP.h55
-rw-r--r--intl/l10nflist.c30
-rw-r--r--intl/loadmsgcat.c151
-rw-r--r--intl/localealias.c33
-rw-r--r--intl/ngettext.c10
-rw-r--r--intl/plural-eval.c101
-rw-r--r--intl/plural-exp.c157
-rw-r--r--intl/plural-exp.h118
-rw-r--r--intl/plural.c86
-rw-r--r--intl/plural.y25
-rw-r--r--intl/textdomain.c14
21 files changed, 579 insertions, 536 deletions
diff --git a/ChangeLog b/ChangeLog
index ca18691b56..00084ffab2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,93 @@
+2001-03-04  Bruno Haible  <bruno@clisp.org>
+
+	* intl/dcigettext.c (DCIGETTEXT): Increment path_max proportionally.
+
+2001-10-31  Bruno Haible  <bruno@clisp.org>
+
+	* intl/plural.y: Include <stddef.h>, needed for NULL with SunOS 4 cc.
+
+2001-03-21  Bruno Haible  <bruno@clisp.org>
+
+	* intl/dcigettext.c (_nl_state_lock): Mark as #ifdef _LIBC. AIX 3 xlc
+	chokes on empty macro arguments.
+	* intl/plural.y: Add #pragma for alloca on AIX 3.
+
+2001-11-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* intl/dcigettext.c (guess_category_value): Only implement for
+	glibc.  Otherwise rely on function _nl_locale_name which isn't
+	present in the glibc sources.
+
+2001-09-24  Bruno Haible  <bruno@clisp.org>
+
+	* intl/loadmsgcat.c (_nl_init_domain_conv): Also enable
+	transliteration when building on a glibc system but outside glibc.
+
+2001-09-22  Bruno Haible  <bruno@clisp.org>
+
+	* intl/plural-eval.c: New file, extracted from dcigettext.c.
+	* intl/dcigettext.c (plural_eval): Remove function, moved to
+	intl/plural-eval.c.
+	(plural_lookup): Call PLURAL_EVAL instead of plural_eval.
+	Include plural-eval.c.
+
+2001-09-22  Bruno Haible  <bruno@clisp.org>
+
+	* intl/plural-exp.c (EXTRACT_PLURAL_EXPRESSION): Reject numbers that
+	don't start with a digit; nplurals must be positive.
+
+2001-09-02  Bruno Haible  <bruno@clisp.org>
+
+	* intl/plural-exp.h: New file, extracted from gettextP.h.
+	* intl/plural-exp.c: New file, extracted from loadmsgcat.c.
+	* intl/gettextP.h (struct expression, struct parse_args,
+	__gettext_free_exp, __gettextparse): Move to plural-exp.h.
+	* intl/loadmsgcat.c: Include plural-exp.h.
+	(PLURAL_PARSE): Move macro to plural-exp.h.
+	(plvar, plone, germanic_plural, INIT_GERMANIC_PLURAL): Move to
+	plural-exp.c.
+	(_nl_load_domain): Move plural handling code to plural-exp.c.  Call
+	EXTRACT_PLURAL_EXPRESSION.
+	(_nl_unload_domain): Update.
+	* intl/dcigettext.c: Include plural-exp.h.
+	* intl/plural.y: Include plural-exp.h, not gettextP.h.
+	(FREE_EXPRESSION): Move macro to plural-exp.h.
+	* intl/Makefile (routines): Add plural-exp.
+	(distribute): Add plural-exp.h.
+
+2001-07-28  Bruno Haible  <bruno@clisp.org>
+
+	* intl/l10nflist.c (_nl_normalize_codeset): Cast isalnum, isalpha,
+	isdigit, tolower argument to 'unsigned char'.
+	* intl/loadmsgcat.c (_nl_load_domain): Cast isspace argument to
+	'unsigned char'.
+	* intl/localealias.c (read_alias_file): Cast isspace argument to
+	'unsigned char'.
+
+2001-10-20  Bruno Haible  <bruno@clisp.org>
+
+	Assume strchr() exists. (Without it, intl/explodename.c wouldn't link
+	anyway.)
+	* intl/dcigettext.c (strchr): Remove fallback definition; it conflicts
+	with the variable 'index' in plural_lookup.
+	* intl/l10nflist.c (strchr): Likewise.
+	* intl/localealias.c (strchr): Likewise.
+
+	Assume <stddef.h>, <stdlib.h>, <string.h>, <locale.h> exist.
+	* intl/bindtextdom.c: Likewise.
+	* intl/dcigettext.c: Likewise.
+	* intl/dgettext.c: Likewise.
+	* intl/dngettext.c: Likewise.
+	* intl/explodename.c: Likewise.
+	* intl/finddomain.c: Likewise.
+	* intl/gettext.c: Likewise.
+	* intl/l10nflist.c: Likewise.
+	* intl/loadmsgcat.c: Likewise.
+	* intl/localealias.c: Likewise.
+	* intl/ngettext.c: Likewise.
+	* intl/textdomain.c: Likewise.
+	* intl/gettext.h: Assume <limits.h> exists.
+
 2001-11-27  Ulrich Drepper  <drepper@redhat.com>
 
 	* stdio-common/Makefile (tests): Add scanf11.
diff --git a/intl/Makefile b/intl/Makefile
index 61acb309f6..3935e7942b 100644
--- a/intl/Makefile
+++ b/intl/Makefile
@@ -23,9 +23,9 @@ headers = libintl.h
 routines = bindtextdom dcgettext dgettext gettext	\
 	   dcigettext dcngettext dngettext ngettext \
 	   finddomain loadmsgcat localealias textdomain	\
-	   l10nflist explodename plural
+	   l10nflist explodename plural plural-exp
 distribute = gettext.h gettextP.h hash-string.h loadinfo.h locale.alias \
-	     plural.y po2test.sed tst-gettext.sh tst-translit.sh \
+	     plural.y plural-exp.h po2test.sed tst-gettext.sh tst-translit.sh \
 	     translit.po tst-gettext2.sh tstlang1.po tstlang2.po tstcodeset.po\
 	     tst-codeset.sh
 
diff --git a/intl/bindtextdom.c b/intl/bindtextdom.c
index e4830798bc..d051ac9f3a 100644
--- a/intl/bindtextdom.c
+++ b/intl/bindtextdom.c
@@ -21,24 +21,9 @@
 # include <config.h>
 #endif
 
-#if defined STDC_HEADERS || defined _LIBC
-# include <stdlib.h>
-#else
-# ifdef HAVE_MALLOC_H
-#  include <malloc.h>
-# else
-void free ();
-# endif
-#endif
-
-#if defined HAVE_STRING_H || defined _LIBC
-# include <string.h>
-#else
-# include <strings.h>
-# ifndef memcpy
-#  define memcpy(Dst, Src, Num) (bcopy (Src, Dst, Num), (Dst))
-# endif
-#endif
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
 
 #ifdef _LIBC
 # include <libintl.h>
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index d5208e41f8..f274de81d8 100644
--- a/intl/dcigettext.c
+++ b/intl/dcigettext.c
@@ -30,11 +30,11 @@
 
 #include <sys/types.h>
 
-#if defined __GNUC__ && !defined C_ALLOCA
+#ifdef __GNUC__
 # define alloca __builtin_alloca
 # define HAVE_ALLOCA 1
 #else
-# if (defined HAVE_ALLOCA_H || defined _LIBC) && !defined C_ALLOCA
+# if defined HAVE_ALLOCA_H || defined _LIBC
 #  include <alloca.h>
 # else
 #  ifdef _AIX
@@ -55,42 +55,22 @@ extern int errno;
 # define __set_errno(val) errno = (val)
 #endif
 
-#if defined STDC_HEADERS || defined _LIBC
-# include <stddef.h>
-# include <stdlib.h>
-#else
-char *getenv ();
-# ifdef HAVE_MALLOC_H
-#  include <malloc.h>
-# else
-void free ();
-# endif
-#endif
-
-#if defined HAVE_STRING_H || defined _LIBC
-# include <string.h>
-#else
-# include <strings.h>
-#endif
-#if !HAVE_STRCHR && !defined _LIBC
-# ifndef strchr
-#  define strchr index
-# endif
-#endif
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
 
 #if defined HAVE_UNISTD_H || defined _LIBC
 # include <unistd.h>
 #endif
 
-#if defined HAVE_LOCALE_H || defined _LIBC
-# include <locale.h>
-#endif
+#include <locale.h>
 
 #if defined HAVE_SYS_PARAM_H || defined _LIBC
 # include <sys/param.h>
 #endif
 
 #include "gettextP.h"
+#include "plural-exp.h"
 #ifdef _LIBC
 # include <libintl.h>
 #else
@@ -192,16 +172,6 @@ static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
 # define PATH_MAX _POSIX_PATH_MAX
 #endif
 
-/* XPG3 defines the result of `setlocale (category, NULL)' as:
-   ``Directs `setlocale()' to query `category' and return the current
-     setting of `local'.''
-   However it does not specify the exact format.  Neither do SUSV2 and
-   ISO C 99.  So we can use this feature only on selected systems (e.g.
-   those using GNU C Library).  */
-#ifdef _LIBC
-# define HAVE_LOCALE_NULL
-#endif
-
 /* This is the type used for the search tree where known translations
    are stored.  */
 struct known_translation_t
@@ -286,9 +256,6 @@ static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain,
 				    const char *translation,
 				    size_t translation_len))
      internal_function;
-static unsigned long int plural_eval PARAMS ((struct expression *pexp,
-					      unsigned long int n))
-     internal_function;
 static const char *category_to_name PARAMS ((int category)) internal_function;
 static const char *guess_category_value PARAMS ((int category,
 						 const char *categoryname))
@@ -355,7 +322,9 @@ typedef unsigned char transmem_block_t;
 #endif
 
 /* Lock variable to protect the global data in the gettext implementation.  */
+#ifdef _LIBC
 __libc_rwlock_define_initialized (, _nl_state_lock)
+#endif
 
 /* Checking whether the binaries runs SUID must be done and glibc provides
    easier methods therefore we make a difference here.  */
@@ -375,6 +344,9 @@ static int enable_secure;
     }
 #endif
 
+/* Get the function to evaluate the plural expression.  */
+#include "plural-eval.c"
+
 /* Look up MSGID in the DOMAINNAME message catalog for the current
    CATEGORY locale and, if PLURAL is nonzero, search over string
    depending on the plural form determined by N.  */
@@ -479,16 +451,18 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
       path_max = (unsigned int) PATH_MAX;
       path_max += 2;		/* The getcwd docs say to do this.  */
 
-      dirname = (char *) alloca (path_max + dirname_len);
-      ADD_BLOCK (block_list, dirname);
-
-      __set_errno (0);
-      while ((ret = getcwd (dirname, path_max)) == NULL && errno == ERANGE)
+      for (;;)
 	{
-	  path_max += PATH_INCR;
 	  dirname = (char *) alloca (path_max + dirname_len);
 	  ADD_BLOCK (block_list, dirname);
+
 	  __set_errno (0);
+	  ret = getcwd (dirname, path_max);
+	  if (ret != NULL || errno != ERANGE)
+	    break;
+
+	  path_max += path_max / 2;
+	  path_max += PATH_INCR;
 	}
 
       if (ret == NULL)
@@ -983,87 +957,6 @@ plural_lookup (domain, n, translation, translation_len)
 }
 
 
-/* Function to evaluate the plural expression and return an index value.  */
-static unsigned long int
-internal_function
-plural_eval (pexp, n)
-     struct expression *pexp;
-     unsigned long int n;
-{
-  switch (pexp->nargs)
-    {
-    case 0:
-      switch (pexp->operation)
-	{
-	case var:
-	  return n;
-	case num:
-	  return pexp->val.num;
-	default:
-	  break;
-	}
-      /* NOTREACHED */
-      break;
-    case 1:
-      {
-	/* pexp->operation must be lnot.  */
-	unsigned long int arg = plural_eval (pexp->val.args[0], n);
-	return ! arg;
-      }
-    case 2:
-      {
-	unsigned long int leftarg = plural_eval (pexp->val.args[0], n);
-	if (pexp->operation == lor)
-	  return leftarg || plural_eval (pexp->val.args[1], n);
-	else if (pexp->operation == land)
-	  return leftarg && plural_eval (pexp->val.args[1], n);
-	else
-	  {
-	    unsigned long int rightarg = plural_eval (pexp->val.args[1], n);
-
-	    switch (pexp->operation)
-	      {
-	      case mult:
-		return leftarg * rightarg;
-	      case divide:
-		return leftarg / rightarg;
-	      case module:
-		return leftarg % rightarg;
-	      case plus:
-		return leftarg + rightarg;
-	      case minus:
-		return leftarg - rightarg;
-	      case less_than:
-		return leftarg < rightarg;
-	      case greater_than:
-		return leftarg > rightarg;
-	      case less_or_equal:
-		return leftarg <= rightarg;
-	      case greater_or_equal:
-		return leftarg >= rightarg;
-	      case equal:
-		return leftarg == rightarg;
-	      case not_equal:
-		return leftarg != rightarg;
-	      default:
-		break;
-	      }
-	  }
-	/* NOTREACHED */
-	break;
-      }
-    case 3:
-      {
-	/* pexp->operation must be qmop.  */
-	unsigned long int boolarg = plural_eval (pexp->val.args[0], n);
-	return plural_eval (pexp->val.args[boolarg ? 1 : 2], n);
-      }
-    }
-  /* NOTREACHED */
-  return 0;
-}
-
-
 /* Return string representation of locale CATEGORY.  */
 static const char *
 internal_function
@@ -1144,25 +1037,10 @@ guess_category_value (category, categoryname)
   /* We have to proceed with 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 _LIBC || (defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL)
+#ifdef _LIBC
   retval = setlocale (category, NULL);
 #else
-  /* Setting of LC_ALL overwrites all other.  */
-  retval = getenv ("LC_ALL");
-  if (retval == NULL || retval[0] == '\0')
-    {
-      /* Next comes the name of the desired category.  */
-      retval = getenv (categoryname);
-      if (retval == NULL || retval[0] == '\0')
-	{
-	  /* Last possibility is the LANG environment variable.  */
-	  retval = getenv ("LANG");
-	  if (retval == NULL || retval[0] == '\0')
-	    /* We use C as the default domain.  POSIX says this is
-	       implementation defined.  */
-	    return "C";
-	}
-    }
+  retval = _nl_locale_name (category, categoryname);
 #endif
 
   return language != NULL && strcmp (retval, "C") != 0 ? language : retval;
diff --git a/intl/dgettext.c b/intl/dgettext.c
index d0e5ed2b2f..02ca2b1687 100644
--- a/intl/dgettext.c
+++ b/intl/dgettext.c
@@ -21,9 +21,7 @@
 # include <config.h>
 #endif
 
-#if defined HAVE_LOCALE_H || defined _LIBC
-# include <locale.h>
-#endif
+#include <locale.h>
 
 #include "gettextP.h"
 #ifdef _LIBC
diff --git a/intl/dngettext.c b/intl/dngettext.c
index a620024b6c..14f06c3779 100644
--- a/intl/dngettext.c
+++ b/intl/dngettext.c
@@ -21,9 +21,7 @@
 # include <config.h>
 #endif
 
-#if defined HAVE_LOCALE_H || defined _LIBC
-# include <locale.h>
-#endif
+#include <locale.h>
 
 #include "gettextP.h"
 #ifdef _LIBC
diff --git a/intl/explodename.c b/intl/explodename.c
index 5561017876..0b17776ec6 100644
--- a/intl/explodename.c
+++ b/intl/explodename.c
@@ -21,15 +21,8 @@
 # include <config.h>
 #endif
 
-#if defined STDC_HEADERS || defined _LIBC
-# include <stdlib.h>
-#endif
-
-#if defined HAVE_STRING_H || defined _LIBC
-# include <string.h>
-#else
-# include <strings.h>
-#endif
+#include <stdlib.h>
+#include <string.h>
 #include <sys/types.h>
 
 #include "loadinfo.h"
diff --git a/intl/finddomain.c b/intl/finddomain.c
index 7dd18633a9..d487bbdf42 100644
--- a/intl/finddomain.c
+++ b/intl/finddomain.c
@@ -24,25 +24,8 @@
 
 #include <stdio.h>
 #include <sys/types.h>
-
-#if defined STDC_HEADERS || defined _LIBC
-# include <stdlib.h>
-#else
-# ifdef HAVE_MALLOC_H
-#  include <malloc.h>
-# else
-void free ();
-# endif
-#endif
-
-#if defined HAVE_STRING_H || defined _LIBC
-# include <string.h>
-#else
-# include <strings.h>
-# ifndef memcpy
-#  define memcpy(Dst, Src, Num) (bcopy (Src, Dst, Num), (Dst))
-# endif
-#endif
+#include <stdlib.h>
+#include <string.h>
 
 #if defined HAVE_UNISTD_H || defined _LIBC
 # include <unistd.h>
diff --git a/intl/gettext.c b/intl/gettext.c
index 4b90f518c7..1f992c8e77 100644
--- a/intl/gettext.c
+++ b/intl/gettext.c
@@ -25,15 +25,7 @@
 # define __need_NULL
 # include <stddef.h>
 #else
-# ifdef STDC_HEADERS
-#  include <stdlib.h>		/* Just for NULL.  */
-# else
-#  ifdef HAVE_STRING_H
-#   include <string.h>
-#  else
-#   define NULL ((void *) 0)
-#  endif
-# endif
+# include <stdlib.h>		/* Just for NULL.  */
 #endif
 
 #include "gettextP.h"
diff --git a/intl/gettext.h b/intl/gettext.h
index c427d89d17..11a0236daf 100644
--- a/intl/gettext.h
+++ b/intl/gettext.h
@@ -20,9 +20,7 @@
 #ifndef _GETTEXT_H
 #define _GETTEXT_H 1
 
-#if HAVE_LIMITS_H || _LIBC
-# include <limits.h>
-#endif
+#include <limits.h>
 
 /* @@ end of prolog @@ */
 
diff --git a/intl/gettextP.h b/intl/gettextP.h
index 2788964954..98d16954f9 100644
--- a/intl/gettextP.h
+++ b/intl/gettextP.h
@@ -75,51 +75,6 @@ SWAP (i)
 #endif
 
 
-/* This is the representation of the expressions to determine the
-   plural form.  */
-struct expression
-{
-  int nargs;			/* Number of arguments.  */
-  enum operator
-  {
-    /* Without arguments:  */
-    var,			/* The variable "n".  */
-    num,			/* Decimal number.  */
-    /* Unary operators:  */
-    lnot,			/* Logical NOT.  */
-    /* Binary operators:  */
-    mult,			/* Multiplication.  */
-    divide,			/* Division.  */
-    module,			/* Module operation.  */
-    plus,			/* Addition.  */
-    minus,			/* Subtraction.  */
-    less_than,			/* Comparison.  */
-    greater_than,		/* Comparison.  */
-    less_or_equal,		/* Comparison.  */
-    greater_or_equal,		/* Comparison.  */
-    equal,			/* Comparision for equality.  */
-    not_equal,			/* Comparision for inequality.  */
-    land,			/* Logical AND.  */
-    lor,			/* Logical OR.  */
-    /* Ternary operators:  */
-    qmop			/* Question mark operator.  */
-  } operation;
-  union
-  {
-    unsigned long int num;	/* Number value for `num'.  */
-    struct expression *args[3];	/* Up to three arguments.  */
-  } val;
-};
-
-/* This is the data structure to pass information to the parser and get
-   the result in a thread-safe way.  */
-struct parse_args
-{
-  const char *cp;
-  struct expression *res;
-};
-
-
 /* The representation of an opened message catalog.  */
 struct loaded_domain
 {
@@ -240,16 +195,6 @@ extern char *bind_textdomain_codeset__ PARAMS ((const char *__domainname,
 						const char *__codeset));
 #endif
 
-#ifdef _LIBC
-extern void __gettext_free_exp PARAMS ((struct expression *exp))
-     internal_function;
-extern int __gettextparse PARAMS ((void *arg));
-#else
-extern void gettext_free_exp__ PARAMS ((struct expression *exp))
-     internal_function;
-extern int gettextparse__ PARAMS ((void *arg));
-#endif
-
 /* @@ begin of epilog @@ */
 
 #endif /* gettextP.h  */
diff --git a/intl/l10nflist.c b/intl/l10nflist.c
index 5e23d394bc..bb5900068c 100644
--- a/intl/l10nflist.c
+++ b/intl/l10nflist.c
@@ -28,30 +28,14 @@
 # include <config.h>
 #endif
 
-
-#if defined HAVE_STRING_H || defined _LIBC
-# include <string.h>
-#else
-# include <strings.h>
-# ifndef memcpy
-#  define memcpy(Dst, Src, Num) (bcopy (Src, Dst, Num), (Dst))
-# endif
-#endif
-#if !HAVE_STRCHR && !defined _LIBC
-# ifndef strchr
-#  define strchr index
-# endif
-#endif
+#include <string.h>
 
 #if defined _LIBC || defined HAVE_ARGZ_H
 # include <argz.h>
 #endif
 #include <ctype.h>
 #include <sys/types.h>
-
-#if defined STDC_HEADERS || defined _LIBC
-# include <stdlib.h>
-#endif
+#include <stdlib.h>
 
 #include "loadinfo.h"
 
@@ -368,11 +352,11 @@ _nl_normalize_codeset (codeset, name_len)
   size_t cnt;
 
   for (cnt = 0; cnt < name_len; ++cnt)
-    if (isalnum (codeset[cnt]))
+    if (isalnum ((unsigned char) codeset[cnt]))
       {
 	++len;
 
-	if (isalpha (codeset[cnt]))
+	if (isalpha ((unsigned char) codeset[cnt]))
 	  only_digit = 0;
       }
 
@@ -386,9 +370,9 @@ _nl_normalize_codeset (codeset, name_len)
 	wp = retval;
 
       for (cnt = 0; cnt < name_len; ++cnt)
-	if (isalpha (codeset[cnt]))
-	  *wp++ = tolower (codeset[cnt]);
-	else if (isdigit (codeset[cnt]))
+	if (isalpha ((unsigned char) codeset[cnt]))
+	  *wp++ = tolower ((unsigned char) codeset[cnt]);
+	else if (isdigit ((unsigned char) codeset[cnt]))
 	  *wp++ = codeset[cnt];
 
       *wp = '\0';
diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c
index 8520f7d20c..41f56500b8 100644
--- a/intl/loadmsgcat.c
+++ b/intl/loadmsgcat.c
@@ -51,15 +51,8 @@ char *alloca ();
 # endif
 #endif
 
-#if defined STDC_HEADERS || defined _LIBC
-# include <stdlib.h>
-#endif
-
-#if defined HAVE_STRING_H || defined _LIBC
-# include <string.h>
-#else
-# include <strings.h>
-#endif
+#include <stdlib.h>
+#include <string.h>
 
 #if defined HAVE_UNISTD_H || defined _LIBC
 # include <unistd.h>
@@ -81,6 +74,7 @@ char *alloca ();
 
 #include "gettext.h"
 #include "gettextP.h"
+#include "plural-exp.h"
 
 #ifdef _LIBC
 # include "../locale/localeinfo.h"
@@ -99,16 +93,6 @@ char *alloca ();
 # define munmap __munmap
 #endif
 
-/* Names for the libintl functions are a problem.  They must not clash
-   with existing names and they should follow ANSI C.  But this source
-   code is also used in GNU C Library where the names have a __
-   prefix.  So we have to make a difference here.  */
-#ifdef _LIBC
-# define PLURAL_PARSE __gettextparse
-#else
-# define PLURAL_PARSE gettextparse__
-#endif
-
 /* For those losing systems which don't have `alloca' we have to add
    some additional code emulating it.  */
 #ifdef HAVE_ALLOCA
@@ -123,73 +107,6 @@ char *alloca ();
    cached by one of GCC's features.  */
 int _nl_msg_cat_cntr;
 
-#if defined __GNUC__ \
-    || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
-
-/* These structs are the constant expression for the germanic plural
-   form determination.  It represents the expression  "n != 1".  */
-static const struct expression plvar =
-{
-  .nargs = 0,
-  .operation = var,
-};
-static const struct expression plone =
-{
-  .nargs = 0,
-  .operation = num,
-  .val =
-  {
-    .num = 1
-  }
-};
-static struct expression germanic_plural =
-{
-  .nargs = 2,
-  .operation = not_equal,
-  .val =
-  {
-    .args =
-    {
-      [0] = (struct expression *) &plvar,
-      [1] = (struct expression *) &plone
-    }
-  }
-};
-
-# define INIT_GERMANIC_PLURAL()
-
-#else
-
-/* For compilers without support for ISO C 99 struct/union initializers:
-   Initialization at run-time.  */
-
-static struct expression plvar;
-static struct expression plone;
-static struct expression germanic_plural;
-
-static void
-init_germanic_plural ()
-{
-  if (plone.val.num == 0)
-    {
-      plvar.nargs = 0;
-      plvar.operation = var;
-
-      plone.nargs = 0;
-      plone.operation = num;
-      plone.val.num = 1;
-
-      germanic_plural.nargs = 2;
-      germanic_plural.operation = not_equal;
-      germanic_plural.val.args[0] = &plvar;
-      germanic_plural.val.args[1] = &plone;
-    }
-}
-
-# define INIT_GERMANIC_PLURAL() init_germanic_plural ()
-
-#endif
-
 
 /* Initialize the codeset dependent parts of an opened message catalog.
    Return the header entry.  */
@@ -279,8 +196,10 @@ _nl_init_domain_conv (domain_file, domain, domainbinding)
 	    domain->conv = (__gconv_t) -1;
 # else
 #  if HAVE_ICONV
-	  /* When using GNU libiconv, we want to use transliteration.  */
-#   if _LIBICONV_VERSION
+	  /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
+	     we want to use transliteration.  */
+#   if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
+       || _LIBICONV_VERSION >= 0x0105
 	  len = strlen (outcharset);
 	  {
 	    char *tmp = (char *) alloca (len + 10 + 1);
@@ -290,7 +209,8 @@ _nl_init_domain_conv (domain_file, domain, domainbinding)
 	  }
 #   endif
 	  domain->conv = iconv_open (outcharset, charset);
-#   if _LIBICONV_VERSION
+#   if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
+       || _LIBICONV_VERSION >= 0x0105
 	  freea (outcharset);
 #   endif
 #  endif
@@ -482,56 +402,7 @@ _nl_load_domain (domain_file, domainbinding)
   nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding);
 
   /* Also look for a plural specification.  */
-  if (nullentry != NULL)
-    {
-      const char *plural;
-      const char *nplurals;
-
-      plural = strstr (nullentry, "plural=");
-      nplurals = strstr (nullentry, "nplurals=");
-      if (plural == NULL || nplurals == NULL)
-	goto no_plural;
-      else
-	{
-	  /* First get the number.  */
-	  char *endp;
-	  unsigned long int n;
-	  struct parse_args args;
-
-	  nplurals += 9;
-	  while (*nplurals != '\0' && isspace (*nplurals))
-	    ++nplurals;
-#if defined HAVE_STRTOUL || defined _LIBC
-	  n = strtoul (nplurals, &endp, 10);
-#else
-	  for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
-	    n = n * 10 + (*endp - '0');
-#endif
-	  domain->nplurals = n;
-	  if (nplurals == endp)
-	    goto no_plural;
-
-	  /* Due to the restrictions bison imposes onto the interface of the
-	     scanner function we have to put the input string and the result
-	     passed up from the parser into the same structure which address
-	     is passed down to the parser.  */
-	  plural += 7;
-	  args.cp = plural;
-	  if (PLURAL_PARSE (&args) != 0)
-	    goto no_plural;
-	  domain->plural = args.res;
-	}
-    }
-  else
-    {
-      /* By default we are using the Germanic form: singular form only
-         for `one', the plural form otherwise.  Yes, this is also what
-         English is using since English is a Germanic language.  */
-    no_plural:
-      INIT_GERMANIC_PLURAL ();
-      domain->plural = &germanic_plural;
-      domain->nplurals = 2;
-    }
+  EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
 }
 
 
@@ -541,7 +412,7 @@ internal_function
 _nl_unload_domain (domain)
      struct loaded_domain *domain;
 {
-  if (domain->plural != &germanic_plural)
+  if (domain->plural != &__gettext_germanic_plural)
     __gettext_free_exp (domain->plural);
 
   _nl_free_domain_conv (domain);
diff --git a/intl/localealias.c b/intl/localealias.c
index fa9396fe9a..2226897f58 100644
--- a/intl/localealias.c
+++ b/intl/localealias.c
@@ -52,29 +52,8 @@ char *alloca ();
 # endif
 #endif
 
-#if defined STDC_HEADERS || defined _LIBC
-# include <stdlib.h>
-#else
-# ifdef HAVE_MALLOC_H
-#  include <malloc.h>
-# else
-void free ();
-# endif
-#endif
-
-#if defined HAVE_STRING_H || defined _LIBC
-# include <string.h>
-#else
-# include <strings.h>
-# ifndef memcpy
-#  define memcpy(Dst, Src, Num) (bcopy (Src, Dst, Num), (Dst))
-# endif
-#endif
-#if !HAVE_STRCHR && !defined _LIBC
-# ifndef strchr
-#  define strchr index
-# endif
-#endif
+#include <stdlib.h>
+#include <string.h>
 
 #include "gettextP.h"
 
@@ -277,21 +256,21 @@ read_alias_file (fname, fname_len)
 
       cp = buf;
       /* Ignore leading white space.  */
-      while (isspace (cp[0]))
+      while (isspace ((unsigned char) cp[0]))
 	++cp;
 
       /* A leading '#' signals a comment line.  */
       if (cp[0] != '\0' && cp[0] != '#')
 	{
 	  alias = cp++;
-	  while (cp[0] != '\0' && !isspace (cp[0]))
+	  while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
 	    ++cp;
 	  /* Terminate alias name.  */
 	  if (cp[0] != '\0')
 	    *cp++ = '\0';
 
 	  /* Now look for the beginning of the value.  */
-	  while (isspace (cp[0]))
+	  while (isspace ((unsigned char) cp[0]))
 	    ++cp;
 
 	  if (cp[0] != '\0')
@@ -300,7 +279,7 @@ read_alias_file (fname, fname_len)
 	      size_t value_len;
 
 	      value = cp++;
-	      while (cp[0] != '\0' && !isspace (cp[0]))
+	      while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
 		++cp;
 	      /* Terminate value.  */
 	      if (cp[0] == '\n')
diff --git a/intl/ngettext.c b/intl/ngettext.c
index 70d43838b5..b58c564854 100644
--- a/intl/ngettext.c
+++ b/intl/ngettext.c
@@ -25,15 +25,7 @@
 # define __need_NULL
 # include <stddef.h>
 #else
-# ifdef STDC_HEADERS
-#  include <stdlib.h>		/* Just for NULL.  */
-# else
-#  ifdef HAVE_STRING_H
-#   include <string.h>
-#  else
-#   define NULL ((void *) 0)
-#  endif
-# endif
+# include <stdlib.h>		/* Just for NULL.  */
 #endif
 
 #include "gettextP.h"
diff --git a/intl/plural-eval.c b/intl/plural-eval.c
new file mode 100644
index 0000000000..ed29e201b2
--- /dev/null
+++ b/intl/plural-eval.c
@@ -0,0 +1,101 @@
+/* Plural expression evaluation.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+static unsigned long int plural_eval (struct expression *pexp,
+				      unsigned long int n)
+     internal_function;
+
+static unsigned long int
+internal_function
+plural_eval (pexp, n)
+     struct expression *pexp;
+     unsigned long int n;
+{
+  switch (pexp->nargs)
+    {
+    case 0:
+      switch (pexp->operation)
+	{
+	case var:
+	  return n;
+	case num:
+	  return pexp->val.num;
+	default:
+	  break;
+	}
+      /* NOTREACHED */
+      break;
+    case 1:
+      {
+	/* pexp->operation must be lnot.  */
+	unsigned long int arg = plural_eval (pexp->val.args[0], n);
+	return ! arg;
+      }
+    case 2:
+      {
+	unsigned long int leftarg = plural_eval (pexp->val.args[0], n);
+	if (pexp->operation == lor)
+	  return leftarg || plural_eval (pexp->val.args[1], n);
+	else if (pexp->operation == land)
+	  return leftarg && plural_eval (pexp->val.args[1], n);
+	else
+	  {
+	    unsigned long int rightarg = plural_eval (pexp->val.args[1], n);
+
+	    switch (pexp->operation)
+	      {
+	      case mult:
+		return leftarg * rightarg;
+	      case divide:
+		return leftarg / rightarg;
+	      case module:
+		return leftarg % rightarg;
+	      case plus:
+		return leftarg + rightarg;
+	      case minus:
+		return leftarg - rightarg;
+	      case less_than:
+		return leftarg < rightarg;
+	      case greater_than:
+		return leftarg > rightarg;
+	      case less_or_equal:
+		return leftarg <= rightarg;
+	      case greater_or_equal:
+		return leftarg >= rightarg;
+	      case equal:
+		return leftarg == rightarg;
+	      case not_equal:
+		return leftarg != rightarg;
+	      default:
+		break;
+	      }
+	  }
+	/* NOTREACHED */
+	break;
+      }
+    case 3:
+      {
+	/* pexp->operation must be qmop.  */
+	unsigned long int boolarg = plural_eval (pexp->val.args[0], n);
+	return plural_eval (pexp->val.args[boolarg ? 1 : 2], n);
+      }
+    }
+  /* NOTREACHED */
+  return 0;
+}
diff --git a/intl/plural-exp.c b/intl/plural-exp.c
new file mode 100644
index 0000000000..ba5d455cd5
--- /dev/null
+++ b/intl/plural-exp.c
@@ -0,0 +1,157 @@
+/* Expression parsing for plural form selection.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "plural-exp.h"
+
+#if (defined __GNUC__ && !defined __APPLE_CC__) \
+    || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
+
+/* These structs are the constant expression for the germanic plural
+   form determination.  It represents the expression  "n != 1".  */
+static const struct expression plvar =
+{
+  .nargs = 0,
+  .operation = var,
+};
+static const struct expression plone =
+{
+  .nargs = 0,
+  .operation = num,
+  .val =
+  {
+    .num = 1
+  }
+};
+struct expression GERMANIC_PLURAL =
+{
+  .nargs = 2,
+  .operation = not_equal,
+  .val =
+  {
+    .args =
+    {
+      [0] = (struct expression *) &plvar,
+      [1] = (struct expression *) &plone
+    }
+  }
+};
+
+# define INIT_GERMANIC_PLURAL()
+
+#else
+
+/* For compilers without support for ISO C 99 struct/union initializers:
+   Initialization at run-time.  */
+
+static struct expression plvar;
+static struct expression plone;
+struct expression GERMANIC_PLURAL;
+
+static void
+init_germanic_plural ()
+{
+  if (plone.val.num == 0)
+    {
+      plvar.nargs = 0;
+      plvar.operation = var;
+
+      plone.nargs = 0;
+      plone.operation = num;
+      plone.val.num = 1;
+
+      GERMANIC_PLURAL.nargs = 2;
+      GERMANIC_PLURAL.operation = not_equal;
+      GERMANIC_PLURAL.val.args[0] = &plvar;
+      GERMANIC_PLURAL.val.args[1] = &plone;
+    }
+}
+
+# define INIT_GERMANIC_PLURAL() init_germanic_plural ()
+
+#endif
+
+void
+internal_function
+EXTRACT_PLURAL_EXPRESSION (nullentry, pluralp, npluralsp)
+     const char *nullentry;
+     struct expression **pluralp;
+     unsigned long int *npluralsp;
+{
+  if (nullentry != NULL)
+    {
+      const char *plural;
+      const char *nplurals;
+
+      plural = strstr (nullentry, "plural=");
+      nplurals = strstr (nullentry, "nplurals=");
+      if (plural == NULL || nplurals == NULL)
+	goto no_plural;
+      else
+	{
+	  char *endp;
+	  unsigned long int n;
+	  struct parse_args args;
+
+	  /* First get the number.  */
+	  nplurals += 9;
+	  while (*nplurals != '\0' && isspace ((unsigned char) *nplurals))
+	    ++nplurals;
+	  if (!(*nplurals >= '0' && *nplurals <= '9'))
+	    goto no_plural;
+#if defined HAVE_STRTOUL || defined _LIBC
+	  n = strtoul (nplurals, &endp, 10);
+#else
+	  for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
+	    n = n * 10 + (*endp - '0');
+#endif
+	  if (nplurals == endp)
+	    goto no_plural;
+	  *npluralsp = n;
+
+	  /* Due to the restrictions bison imposes onto the interface of the
+	     scanner function we have to put the input string and the result
+	     passed up from the parser into the same structure which address
+	     is passed down to the parser.  */
+	  plural += 7;
+	  args.cp = plural;
+	  if (PLURAL_PARSE (&args) != 0)
+	    goto no_plural;
+	  *pluralp = args.res;
+	}
+    }
+  else
+    {
+      /* By default we are using the Germanic form: singular form only
+         for `one', the plural form otherwise.  Yes, this is also what
+         English is using since English is a Germanic language.  */
+    no_plural:
+      INIT_GERMANIC_PLURAL ();
+      *pluralp = &GERMANIC_PLURAL;
+      *npluralsp = 2;
+    }
+}
diff --git a/intl/plural-exp.h b/intl/plural-exp.h
new file mode 100644
index 0000000000..389a5c626e
--- /dev/null
+++ b/intl/plural-exp.h
@@ -0,0 +1,118 @@
+/* Expression parsing and evaluation for plural form selection.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _PLURAL_EXP_H
+#define _PLURAL_EXP_H
+
+#ifndef PARAMS
+# if __STDC__
+#  define PARAMS(args) args
+# else
+#  define PARAMS(args) ()
+# endif
+#endif
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+
+/* This is the representation of the expressions to determine the
+   plural form.  */
+struct expression
+{
+  int nargs;			/* Number of arguments.  */
+  enum operator
+  {
+    /* Without arguments:  */
+    var,			/* The variable "n".  */
+    num,			/* Decimal number.  */
+    /* Unary operators:  */
+    lnot,			/* Logical NOT.  */
+    /* Binary operators:  */
+    mult,			/* Multiplication.  */
+    divide,			/* Division.  */
+    module,			/* Modulo operation.  */
+    plus,			/* Addition.  */
+    minus,			/* Subtraction.  */
+    less_than,			/* Comparison.  */
+    greater_than,		/* Comparison.  */
+    less_or_equal,		/* Comparison.  */
+    greater_or_equal,		/* Comparison.  */
+    equal,			/* Comparison for equality.  */
+    not_equal,			/* Comparison for inequality.  */
+    land,			/* Logical AND.  */
+    lor,			/* Logical OR.  */
+    /* Ternary operators:  */
+    qmop			/* Question mark operator.  */
+  } operation;
+  union
+  {
+    unsigned long int num;	/* Number value for `num'.  */
+    struct expression *args[3];	/* Up to three arguments.  */
+  } val;
+};
+
+/* This is the data structure to pass information to the parser and get
+   the result in a thread-safe way.  */
+struct parse_args
+{
+  const char *cp;
+  struct expression *res;
+};
+
+
+/* Names for the libintl functions are a problem.  This source code is used
+   1. in the GNU C Library library,
+   2. in the GNU libintl library,
+   3. in the GNU gettext tools.
+   The function names in each situation must be different, to allow for
+   binary incompatible changes in 'struct expression'.  Furthermore,
+   1. in the GNU C Library library, the names have a __ prefix,
+   2.+3. in the GNU libintl library and in the GNU gettext tools, the names
+         must follow ANSI C and not start with __.
+   So we have to distinguish the three cases.  */
+#ifdef _LIBC
+# define FREE_EXPRESSION __gettext_free_exp
+# define PLURAL_PARSE __gettextparse
+# define GERMANIC_PLURAL __gettext_germanic_plural
+# define EXTRACT_PLURAL_EXPRESSION __gettext_extract_plural
+#elif defined (IN_LIBINTL)
+# define FREE_EXPRESSION gettext_free_exp__
+# define PLURAL_PARSE gettextparse__
+# define GERMANIC_PLURAL gettext_germanic_plural__
+# define EXTRACT_PLURAL_EXPRESSION gettext_extract_plural__
+#else
+# define FREE_EXPRESSION free_plural_expression
+# define PLURAL_PARSE parse_plural_expression
+# define GERMANIC_PLURAL germanic_plural
+# define EXTRACT_PLURAL_EXPRESSION extract_plural_expression
+#endif
+
+extern void FREE_EXPRESSION PARAMS ((struct expression *exp))
+     internal_function;
+extern int PLURAL_PARSE PARAMS ((void *arg));
+extern struct expression GERMANIC_PLURAL;
+extern void EXTRACT_PLURAL_EXPRESSION PARAMS ((const char *nullentry,
+					       struct expression **pluralp,
+					       unsigned long int *npluralsp))
+     internal_function;
+
+#endif /* _PLURAL_EXP_H */
diff --git a/intl/plural.c b/intl/plural.c
index f96eff2cda..92b192c7e8 100644
--- a/intl/plural.c
+++ b/intl/plural.c
@@ -39,34 +39,37 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+/* The bison generated parser uses alloca.  AIX 3 forces us to put this
+   declaration at the beginning of the file.  The declaration in bison's
+   skeleton file comes too late.  This must come before <config.h>
+   because <config.h> may include arbitrary system headers.  */
+#if defined _AIX && !defined __GNUC__
+ #pragma alloca
+#endif
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
+#include <stddef.h>
 #include <stdlib.h>
-#include "gettextP.h"
-
-/* Names for the libintl functions are a problem.  They must not clash
-   with existing names and they should follow ANSI C.  But this source
-   code is also used in GNU C Library where the names have a __
-   prefix.  So we have to make a difference here.  */
-#ifdef _LIBC
-# define FREE_EXPRESSION __gettext_free_exp
-#else
-# define FREE_EXPRESSION gettext_free_exp__
-# define __gettextparse gettextparse__
+#include "plural-exp.h"
+
+/* The main function generated by the parser is called __gettextparse,
+   but we want it to be called PLURAL_PARSE.  */
+#ifndef _LIBC
+# define __gettextparse PLURAL_PARSE
 #endif
 
 #define YYLEX_PARAM	&((struct parse_args *) arg)->cp
 #define YYPARSE_PARAM	arg
 
-#line 46 "plural.y"
+#line 49 "plural.y"
 typedef union {
   unsigned long int num;
   enum operator op;
   struct expression *exp;
 } YYSTYPE;
-#line 52 "plural.y"
+#line 55 "plural.y"
 
 /* Prototypes for local functions.  */
 static struct expression *new_exp PARAMS ((int nargs, enum operator op,
@@ -228,8 +231,8 @@ static const short yyrhs[] = {    17,
 
 #if YYDEBUG != 0
 static const short yyrline[] = { 0,
-   171,   179,   183,   187,   191,   195,   199,   203,   207,   211,
-   215,   220
+   174,   182,   186,   190,   194,   198,   202,   206,   210,   214,
+   218,   223
 };
 #endif
 
@@ -296,7 +299,7 @@ static const short yycheck[] = {     1,
 #define YYPURE 1
 
 /* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
-#line 3 "/usr/share/bison.simple"
+#line 3 "/usr/lib/bison.simple"
 /* This file comes from bison-1.28.  */
 
 /* Skeleton output parser for bison,
@@ -327,11 +330,6 @@ static const short yycheck[] = {     1,
   It was written by Richard Stallman by simplifying the hairy parser
   used when %semantic_parser is specified.  */
 
-#ifndef YYPARSE_RETURN_TYPE
-#define YYPARSE_RETURN_TYPE int
-#endif
-
-
 #ifndef YYSTACK_USE_ALLOCA
 #ifdef alloca
 #define YYSTACK_USE_ALLOCA
@@ -515,7 +513,7 @@ __yy_memcpy (char *to, char *from, unsigned int count)
 #endif
 #endif
 
-#line 222 "/usr/share/bison.simple"
+#line 217 "/usr/lib/bison.simple"
 
 /* The user can define YYPARSE_PARAM as the name of an argument to be passed
    into yyparse.  The argument should have type void *.
@@ -539,15 +537,13 @@ __yy_memcpy (char *to, char *from, unsigned int count)
 /* Prevent warning if -Wstrict-prototypes.  */
 #ifdef __GNUC__
 #ifdef YYPARSE_PARAM
-YYPARSE_RETURN_TYPE
-yyparse (void *);
+int yyparse (void *);
 #else
-YYPARSE_RETURN_TYPE
-yyparse (void);
+int yyparse (void);
 #endif
 #endif
 
-YYPARSE_RETURN_TYPE
+int
 yyparse(YYPARSE_PARAM_ARG)
      YYPARSE_PARAM_DECL
 {
@@ -575,9 +571,7 @@ yyparse(YYPARSE_PARAM_ARG)
 #endif
 
   int yystacksize = YYINITDEPTH;
-#ifndef YYSTACK_USE_ALLOCA
   int yyfree_stacks = 0;
-#endif
 
 #ifdef YYPURE
   int yychar;
@@ -662,7 +656,6 @@ yynewstate:
       if (yystacksize >= YYMAXDEPTH)
 	{
 	  yyerror("parser stack overflow");
-#ifndef YYSTACK_USE_ALLOCA
 	  if (yyfree_stacks)
 	    {
 	      free (yyss);
@@ -671,7 +664,6 @@ yynewstate:
 	      free (yyls);
 #endif
 	    }
-#endif	    
 	  return 2;
 	}
       yystacksize *= 2;
@@ -850,7 +842,7 @@ yyreduce:
   switch (yyn) {
 
 case 1:
-#line 172 "plural.y"
+#line 175 "plural.y"
 {
 	    if (yyvsp[0].exp == NULL)
 	      YYABORT;
@@ -858,75 +850,75 @@ case 1:
 	  ;
     break;}
 case 2:
-#line 180 "plural.y"
+#line 183 "plural.y"
 {
 	    yyval.exp = new_exp_3 (qmop, yyvsp[-4].exp, yyvsp[-2].exp, yyvsp[0].exp);
 	  ;
     break;}
 case 3:
-#line 184 "plural.y"
+#line 187 "plural.y"
 {
 	    yyval.exp = new_exp_2 (lor, yyvsp[-2].exp, yyvsp[0].exp);
 	  ;
     break;}
 case 4:
-#line 188 "plural.y"
+#line 191 "plural.y"
 {
 	    yyval.exp = new_exp_2 (land, yyvsp[-2].exp, yyvsp[0].exp);
 	  ;
     break;}
 case 5:
-#line 192 "plural.y"
+#line 195 "plural.y"
 {
 	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
 	  ;
     break;}
 case 6:
-#line 196 "plural.y"
+#line 199 "plural.y"
 {
 	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
 	  ;
     break;}
 case 7:
-#line 200 "plural.y"
+#line 203 "plural.y"
 {
 	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
 	  ;
     break;}
 case 8:
-#line 204 "plural.y"
+#line 207 "plural.y"
 {
 	    yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp);
 	  ;
     break;}
 case 9:
-#line 208 "plural.y"
+#line 211 "plural.y"
 {
 	    yyval.exp = new_exp_1 (lnot, yyvsp[0].exp);
 	  ;
     break;}
 case 10:
-#line 212 "plural.y"
+#line 215 "plural.y"
 {
 	    yyval.exp = new_exp_0 (var);
 	  ;
     break;}
 case 11:
-#line 216 "plural.y"
+#line 219 "plural.y"
 {
 	    if ((yyval.exp = new_exp_0 (num)) != NULL)
 	      yyval.exp->val.num = yyvsp[0].num;
 	  ;
     break;}
 case 12:
-#line 221 "plural.y"
+#line 224 "plural.y"
 {
 	    yyval.exp = yyvsp[-1].exp;
 	  ;
     break;}
 }
    /* the action file gets copied in in place of this dollarsign */
-#line 554 "/usr/share/bison.simple"
+#line 543 "/usr/lib/bison.simple"
 
   yyvsp -= yylen;
   yyssp -= yylen;
@@ -1124,7 +1116,6 @@ yyerrhandle:
 
  yyacceptlab:
   /* YYACCEPT comes here.  */
-#ifndef YYSTACK_USE_ALLOCA
   if (yyfree_stacks)
     {
       free (yyss);
@@ -1133,12 +1124,10 @@ yyerrhandle:
       free (yyls);
 #endif
     }
-#endif
   return 0;
 
  yyabortlab:
   /* YYABORT comes here.  */
-#ifndef YYSTACK_USE_ALLOCA
   if (yyfree_stacks)
     {
       free (yyss);
@@ -1147,10 +1136,9 @@ yyerrhandle:
       free (yyls);
 #endif
     }
-#endif    
   return 1;
 }
-#line 226 "plural.y"
+#line 229 "plural.y"
 
 
 void
diff --git a/intl/plural.y b/intl/plural.y
index 3345d15eeb..1ce3fd9604 100644
--- a/intl/plural.y
+++ b/intl/plural.y
@@ -19,22 +19,25 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+/* The bison generated parser uses alloca.  AIX 3 forces us to put this
+   declaration at the beginning of the file.  The declaration in bison's
+   skeleton file comes too late.  This must come before <config.h>
+   because <config.h> may include arbitrary system headers.  */
+#if defined _AIX && !defined __GNUC__
+ #pragma alloca
+#endif
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
+#include <stddef.h>
 #include <stdlib.h>
-#include "gettextP.h"
-
-/* Names for the libintl functions are a problem.  They must not clash
-   with existing names and they should follow ANSI C.  But this source
-   code is also used in GNU C Library where the names have a __
-   prefix.  So we have to make a difference here.  */
-#ifdef _LIBC
-# define FREE_EXPRESSION __gettext_free_exp
-#else
-# define FREE_EXPRESSION gettext_free_exp__
-# define __gettextparse gettextparse__
+#include "plural-exp.h"
+
+/* The main function generated by the parser is called __gettextparse,
+   but we want it to be called PLURAL_PARSE.  */
+#ifndef _LIBC
+# define __gettextparse PLURAL_PARSE
 #endif
 
 #define YYLEX_PARAM	&((struct parse_args *) arg)->cp
diff --git a/intl/textdomain.c b/intl/textdomain.c
index d19295d108..b5e6af597f 100644
--- a/intl/textdomain.c
+++ b/intl/textdomain.c
@@ -21,18 +21,8 @@
 # include <config.h>
 #endif
 
-#if defined STDC_HEADERS || defined _LIBC
-# include <stdlib.h>
-#endif
-
-#if defined STDC_HEADERS || defined HAVE_STRING_H || defined _LIBC
-# include <string.h>
-#else
-# include <strings.h>
-# ifndef memcpy
-#  define memcpy(Dst, Src, Num) (bcopy (Src, Dst, Num), (Dst))
-# endif
-#endif
+#include <stdlib.h>
+#include <string.h>
 
 #ifdef _LIBC
 # include <libintl.h>