about summary refs log tree commit diff
path: root/intl/dcigettext.c
diff options
context:
space:
mode:
Diffstat (limited to 'intl/dcigettext.c')
-rw-r--r--intl/dcigettext.c158
1 files changed, 92 insertions, 66 deletions
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index 75aa03a45f..cd3392128b 100644
--- a/intl/dcigettext.c
+++ b/intl/dcigettext.c
@@ -89,12 +89,11 @@ void free ();
 # include <sys/param.h>
 #endif
 
-#include "gettext.h"
 #include "gettextP.h"
 #ifdef _LIBC
 # include <libintl.h>
 #else
-# include "libgettext.h"
+# include "libgnuintl.h"
 #endif
 #include "hash-string.h"
 
@@ -129,6 +128,11 @@ void free ();
 # define _nl_domain_bindings _nl_domain_bindings__
 #endif
 
+/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
+#ifndef offsetof
+# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
+#endif
+
 /* @@ end of prolog @@ */
 
 #ifdef _LIBC
@@ -190,21 +194,13 @@ static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
 /* 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.  And even worse: POSIX
-   defines this not at all.  So we can use this feature only on selected
-   system (e.g. those using GNU C Library).  */
+   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
 
-/* We want to allocate a string at the end of the struct.  gcc makes
-   this easy.  */
-#ifdef __GNUC__
-# define ZERO 0
-#else
-# define ZERO 1
-#endif
-
 /* This is the type used for the search tree where known translations
    are stored.  */
 struct known_translation_t
@@ -241,8 +237,11 @@ static void *root;
 # endif
 
 /* Function to compare two entries in the table of known translations.  */
+static int transcmp PARAMS ((const void *p1, const void *p2));
 static int
-transcmp (const void *p1, const void *p2)
+transcmp (p1, p2)
+     const void *p1;
+     const void *p2;
 {
   const struct known_translation_t *s1;
   const struct known_translation_t *s2;
@@ -274,7 +273,7 @@ const char _nl_default_default_domain[] = "messages";
 const char *_nl_current_default_domain = _nl_default_default_domain;
 
 /* Contains the default location of the message catalogs.  */
-const char _nl_default_dirname[] = GNULOCALEDIR;
+const char _nl_default_dirname[] = LOCALEDIR;
 
 /* List with bindings of specific domains created by bindtextdomain()
    calls.  */
@@ -336,7 +335,7 @@ struct block_list
 typedef struct transmem_list
 {
   struct transmem_list *next;
-  char data[0];
+  char data[ZERO];
 } transmem_block_t;
 static struct transmem_list *transmem_list;
 #else
@@ -423,8 +422,8 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
 
   /* Try to find the translation among those which we found at
      some time.  */
-  search =
-    (struct known_translation_t *) alloca (sizeof (*search) + msgid_len);
+  search = (struct known_translation_t *)
+	   alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
   memcpy (search->msgid, msgid1, msgid_len);
   search->domainname = (char *) domainname;
   search->category = category;
@@ -607,8 +606,8 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
 		  struct known_translation_t *newp;
 
 		  newp = (struct known_translation_t *)
-		    malloc (sizeof (*newp) + msgid_len
-			    + domainname_len + 1 - ZERO);
+		    malloc (offsetof (struct known_translation_t, msgid)
+			    + msgid_len + domainname_len + 1);
 		  if (newp != NULL)
 		    {
 		      newp->domainname =
@@ -679,14 +678,15 @@ _nl_find_msg (domain_file, msgid, lengthp)
       nls_uint32 hash_val = hash_string (msgid);
       nls_uint32 idx = hash_val % domain->hash_size;
       nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
-      nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
-
-      if (nstr == 0)
-	/* Hash table entry is empty.  */
-	return NULL;
 
       while (1)
 	{
+	  nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
+
+	  if (nstr == 0)
+	    /* Hash table entry is empty.  */
+	    return NULL;
+
 	  /* Compare msgid with the original string at index nstr-1.
 	     We compare the lengths with >=, not ==, because plural entries
 	     are represented by strings with an embedded NUL.  */
@@ -704,11 +704,6 @@ _nl_find_msg (domain_file, msgid, lengthp)
 	    idx -= domain->hash_size - incr;
 	  else
 	    idx += incr;
-
-	  nstr = W (domain->must_swap, domain->hash_tab[idx]);
-	  if (nstr == 0)
-	    /* Hash table entry is empty.  */
-	    return NULL;
 	}
       /* NOTREACHED */
     }
@@ -980,43 +975,74 @@ plural_eval (pexp, n)
      struct expression *pexp;
      unsigned long int n;
 {
-  switch (pexp->operation)
+  switch (pexp->nargs)
     {
-    case var:
-      return n;
-    case num:
-      return pexp->val.num;
-    case mult:
-      return (plural_eval (pexp->val.args2.left, n)
-	      * plural_eval (pexp->val.args2.right, n));
-    case divide:
-      return (plural_eval (pexp->val.args2.left, n)
-	      / plural_eval (pexp->val.args2.right, n));
-    case module:
-      return (plural_eval (pexp->val.args2.left, n)
-	      % plural_eval (pexp->val.args2.right, n));
-    case plus:
-      return (plural_eval (pexp->val.args2.left, n)
-	      + plural_eval (pexp->val.args2.right, n));
-    case minus:
-      return (plural_eval (pexp->val.args2.left, n)
-	      - plural_eval (pexp->val.args2.right, n));
-    case equal:
-      return (plural_eval (pexp->val.args2.left, n)
-	      == plural_eval (pexp->val.args2.right, n));
-    case not_equal:
-      return (plural_eval (pexp->val.args2.left, n)
-	      != plural_eval (pexp->val.args2.right, n));
-    case land:
-      return (plural_eval (pexp->val.args2.left, n)
-	      && plural_eval (pexp->val.args2.right, n));
-    case lor:
-      return (plural_eval (pexp->val.args2.left, n)
-	      || plural_eval (pexp->val.args2.right, n));
-    case qmop:
-      return (plural_eval (pexp->val.args3.bexp, n)
-	      ? plural_eval (pexp->val.args3.tbranch, n)
-	      : plural_eval (pexp->val.args3.fbranch, n));
+    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;