summary refs log tree commit diff
path: root/intl/dcgettext.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-12-18 19:45:25 +0000
committerUlrich Drepper <drepper@redhat.com>1999-12-18 19:45:25 +0000
commitb85697f61d8aeeaeb8b91d50ab2c668b7fcbbd8a (patch)
tree6aec765390be55804ecbe7c1bde6c79dda2e1dc2 /intl/dcgettext.c
parent440a52ea7b427b7a5668c77283825cae20d7fc3c (diff)
downloadglibc-b85697f61d8aeeaeb8b91d50ab2c668b7fcbbd8a.tar.gz
glibc-b85697f61d8aeeaeb8b91d50ab2c668b7fcbbd8a.tar.xz
glibc-b85697f61d8aeeaeb8b91d50ab2c668b7fcbbd8a.zip
Update.
1999-12-17  Ulrich Drepper  <drepper@cygnus.com>

	* string/bits/string2.h (__strtok_r_1c): Help gcc optimizing string
	access.

	* locale/programs/ld-collate.c: Implement handling of absolute
	ellipsis.  Parsing of file and constructing the internal data
	structures should now be complete.
	(collate_finish): Start adding support to generate the data
	structures which are written out to the file.

	* intl/dcgettext.c: Rewrite to handle caching of previous results here
	instead of in the dcgettext macro.
	* intl/libintl.h (dcgettext): Don't define for systems using this
	glibc or systems with tsearch.

	* sysdeps/generic/mathdef.h: Protect definitions for math.h
	against double inclusion.
	* sysdeps/alpha/fpu/bits/mathdef.h: Likewise.
	* sysdeps/i386/fpu/bits/mathdef.h: Likewise.
	* sysdeps/m68k/fpu/bits/mathdef.h: Likewise.
	* sysdeps/powerpc/fpu/bits/mathdef.h: Likewise.

	* sysdeps/i386/fpu/libm-test-ulps: Add more deltas (are mobile PIIs
	that different?).

1999-12-17  Andreas Jaeger  <aj@suse.de>

	* rt/aio.h (struct aiocb64): Add member __next_prio to sync the
	struct with aiocb.

	* rt/Makefile (tests): Added tst-aio64.
	Added dependency rules for tst-aio64.

	* rt/tst-aio64.c: New file, copied from tst-aio.c and changed for
	64bit tests.

1999-12-15  Thorsten Kukuk  <kukuk@suse.de>

	* sysdeps/unix/sysv/linux/alpha/oldgetrlimit64.c: Removed.
	* sysdeps/unix/sysv/linux/alpha/oldsetrlimit64.c: Removed.
	* sysdeps/unix/sysv/linux/bits/resource.h: Change RLIM_INFINITY back to
	old value (signed long).
	* sysdeps/unix/sysv/linux/i386/bits/resource.h: New, with unsigned
	long RLIM_INFINITY.
	* sysdeps/unix/sysv/linux/getrlimit.c: Moved from here to ...
	* sysdeps/unix/sysv/linux/i386/getrlimit.c: ... here.
	* sysdeps/unix/sysv/linux/getrlimit64.c: Moved from here to ...
	* sysdeps/unix/sysv/linux/i386/getrlimit64.c: ... here.
	* sysdeps/unix/sysv/linux/oldgetrlimit64.c: Moved from here to ...
	* sysdeps/unix/sysv/linux/i386/oldgetrlimit64.c: ... here.
	* sysdeps/unix/sysv/linux/oldsetrlimit64.c: Moved from here to ...
	* sysdeps/unix/sysv/linux/i386/oldsetrlimit64.c: ... here.
	* sysdeps/unix/sysv/linux/setrlimit.c: Moved from here to ...
	* sysdeps/unix/sysv/linux/i386/setrlimit.c: ... here.
	* sysdeps/unix/sysv/linux/setrlimit64.c: Moved from here to ...
	* sysdeps/unix/sysv/linux/i386/setrlimit64.c: ... here.
	* sysdeps/unix/sysv/linux/sparc/bits/resource.h: New.
	* sysdeps/unix/sysv/linux/sparc/sparc64/oldgetrlimit64.c: Removed.
	* sysdeps/unix/sysv/linux/sparc/sparc64/oldsetrlimit64.c: Removed.

1999-12-17  Andreas Jaeger  <aj@suse.de>

	* elf/ldconfig.c: Add new option -l to manualy link shared
	libraries.
	(options): Added option.
	(parse_opt): Set option.
	(main): Handle option.
	(manual_link): New function.

1999-12-17  Thorsten Kukuk  <kukuk@suse.de>

	* string/bits/string2.h: Fix patch from 1999-12-07.

1999-12-16  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/generic/strsep.c: If delim string has only one character
	don't run over end of string.

	* locale/programs/ld-collate.c (insert_weights): Also update next
	pointer of last cursor element.
	(insert_value): Return nonzero value if nothing got inserted.
	(handle_ellipsis): Don't do anything if to-value cannot be inserted.

1999-12-10  Jakub Jelinek  <jakub@redhat.com>

	* stdlib/longlong.h (__sparc_v9__): Use %rDIGIT instead of %DIGIT
	where appropriate.

1999-12-10  Jakub Jelinek  <jakub@redhat.com>

	* sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c (__sigaction):
	Copy sa_flags into kernel sigaction structure.

1999-12-14  Andreas Jaeger  <aj@suse.de>

	* string/tester.c (test_strsep): More tests for access beyond
	the final NUL.  The first two tests come from PR libc/1486 by
	martinea@iro.umontreal.ca.

1999-12-14  Thorsten Kukuk  <kukuk@suse.de>

	* nis/ypclnt.c: Correct handling of cached client handles.
	(__xdr_ypresp_all): Call callback function for errors, too,
	like Solaris does.
	* nis/nss_compat/compat-grp.c: Make sure errno is always set correct.
	* nis/nss_compat/compat-initgroups.c: Likewise.
	* nis/nss_compat/compat-spwd.c: Likewise.
	* nis/nss_nis/nis-alias.c: Likewise.
	* nis/nss_nis/nis-ethers.c: Likewise.
	* nis/nss_nis/nis-grp.c: Likewise.
	* nis/nss_nis/nis-hosts.c: Likewise.
	* nis/nss_nis/nis-netgrp.c: Likewise.
	* nis/nss_nis/nis-publickey.c: Likewise.
	* nis/nss_nis/nis-service.c: Likewise. Also use services.byservicename
	Map if available, optimize query if name/port and protocol is known.
Diffstat (limited to 'intl/dcgettext.c')
-rw-r--r--intl/dcgettext.c175
1 files changed, 155 insertions, 20 deletions
diff --git a/intl/dcgettext.c b/intl/dcgettext.c
index d482da39b8..8e51970495 100644
--- a/intl/dcgettext.c
+++ b/intl/dcgettext.c
@@ -121,6 +121,9 @@ char *getcwd ();
 # ifndef HAVE_STPCPY
 static char *stpcpy PARAMS ((char *dest, const char *src));
 # endif
+# ifndef HAVE_MEMPCPY
+static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
+# endif
 #endif
 
 /* Amount to increase buffer size by in each try.  */
@@ -130,7 +133,7 @@ static char *stpcpy PARAMS ((char *dest, const char *src));
 /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
    PATH_MAX but might cause redefinition warnings when sys/param.h is
    later included (as on MORE/BSD 4.3).  */
-#if defined(_POSIX_VERSION) || (defined(HAVE_LIMITS_H) && !defined(__GNUC__))
+#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
 # include <limits.h>
 #endif
 
@@ -138,16 +141,16 @@ static char *stpcpy PARAMS ((char *dest, const char *src));
 # define _POSIX_PATH_MAX 255
 #endif
 
-#if !defined(PATH_MAX) && defined(_PC_PATH_MAX)
+#if !defined PATH_MAX && defined _PC_PATH_MAX
 # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
 #endif
 
 /* Don't include sys/param.h if it already has been.  */
-#if defined(HAVE_SYS_PARAM_H) && !defined(PATH_MAX) && !defined(MAXPATHLEN)
+#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
 # include <sys/param.h>
 #endif
 
-#if !defined(PATH_MAX) && defined(MAXPATHLEN)
+#if !defined PATH_MAX && defined MAXPATHLEN
 # define PATH_MAX MAXPATHLEN
 #endif
 
@@ -165,6 +168,68 @@ static char *stpcpy PARAMS ((char *dest, const char *src));
 # 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
+{
+  /* Domain in which to search.  */
+  char *domain;
+
+  /* The category.  */
+  int category;
+
+  /* State of the catalog counter at the point the string was found.  */
+  int counter;
+
+  /* And finally the translation.  */
+  const char *translation;
+
+  /* Pointer to the string in question.  */
+  char msgid[ZERO];
+};
+
+/* Root of the search tree with known translations.  We can use this
+   only if the system provides the `tsearch' function family.  */
+#if defined HAVE_TSEARCH || defined _LIBC
+# include <search.h>
+
+static void *root;
+
+# ifdef _LIBC
+#  define tsearch __tsearch
+# endif
+
+/* Function to compare two entries in the table of known translations.  */
+static int
+transcmp (const void *p1, const void *p2)
+{
+  struct known_translation_t *s1 = (struct known_translation_t *) p1;
+  struct known_translation_t *s2 = (struct known_translation_t *) p2;
+  int result;
+
+  result = strcmp (s1->msgid, s2->msgid);
+  if (result == 0)
+    {
+      result = strcmp (s1->msgid, s2->msgid);
+      if (result == 0)
+	/* We compare the category last (though this is the cheapest
+	   operation) since it is hopefully always the same (namely
+	   LC_MESSAGES).  */
+	result = s1->category - s2->category;
+    }
+
+  return result;
+}
+#endif
+
 /* Name of the default domain used for gettext(3) prior any call to
    textdomain(3).  The default value for this is "messages".  */
 const char _nl_default_default_domain[] = "messages";
@@ -268,12 +333,34 @@ DCGETTEXT (domainname, msgid, category)
   char *dirname, *xdomainname;
   char *single_locale;
   char *retval;
-  int saved_errno = errno;
+  int saved_errno;
+#if defined HAVE_TSEARCH || defined _LIBC
+  struct known_translation_t *search;
+  struct known_translation_t **foundp;
+  size_t msgid_len = strlen (msgid) + 1;
+#endif
+  size_t domainname_len;
 
   /* If no real MSGID is given return NULL.  */
   if (msgid == NULL)
     return NULL;
 
+#if defined HAVE_TSEARCH || defined _LIBC
+  /* Try to find the translation among those which we found at some time.  */
+  search = (struct known_translation_t *) alloca (sizeof (*search)
+						  + msgid_len);
+  memcpy (search->msgid, msgid, msgid_len);
+  search->domain = (char *) domainname;
+  search->category = category;
+
+  foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
+  if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
+    return (char *) (*foundp)->translation;
+#endif
+
+  /* Preserve the `errno' value.  */
+  saved_errno = errno;
+
   /* See whether this is a SUID binary or not.  */
   DETERMINE_SECURE;
 
@@ -340,12 +427,13 @@ DCGETTEXT (domainname, msgid, category)
   categoryname = category_to_name (category);
   categoryvalue = guess_category_value (category, categoryname);
 
+  domainname_len = strlen (domainname);
   xdomainname = (char *) alloca (strlen (categoryname)
-				 + strlen (domainname) + 5);
+				 + domainname_len + 5);
   ADD_BLOCK (block_list, xdomainname);
 
-  stpcpy (stpcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
-		  domainname),
+  stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
+		  domainname, domainname_len),
 	  ".mo");
 
   /* Creating working area.  */
@@ -422,6 +510,38 @@ DCGETTEXT (domainname, msgid, category)
 	    {
 	      FREE_BLOCKS (block_list);
 	      __set_errno (saved_errno);
+#if defined HAVE_TSEARCH || defined _LIBC
+	      if (foundp == NULL)
+		{
+		  /* Create a new entry and add it to the search tree.  */
+		  struct known_translation_t *newp;
+
+		  newp = (struct known_translation_t *)
+		    malloc (sizeof (*newp) + msgid_len
+			    + domainname_len + 1 - ZERO);
+		  if (newp != NULL)
+		    {
+		      newp->domain = mempcpy (newp->msgid, msgid, msgid_len);
+		      memcpy (newp->domain, domainname, domainname_len + 1);
+		      newp->category = category;
+		      newp->counter = _nl_msg_cat_cntr;
+		      newp->translation = retval;
+
+		      /* Insert the entry in the search tree.  */
+		      foundp = (struct known_translation_t **)
+			tsearch (newp, &root, transcmp);
+		      if (&newp != foundp)
+			/* The insert failed.  */
+			free (newp);
+		    }
+		}
+	      else
+		{
+		  /* We can update the existing entry.  */
+		  (*foundp)->counter = _nl_msg_cat_cntr;
+		  (*foundp)->translation = retval;
+		}
+#endif
 	      return retval;
 	    }
 	}
@@ -571,12 +691,13 @@ _nl_find_msg (domain_file, msgid)
 	    return NULL;
 
 	  if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
-	      && strcmp (msgid,
-			 domain->data + W (domain->must_swap,
-					   domain->orig_tab[nstr - 1].offset))
-	         == 0)
-	    return (char *) domain->data
-	      + W (domain->must_swap, domain->trans_tab[nstr - 1].offset);
+	      && (strcmp (msgid,
+			  domain->data + W (domain->must_swap,
+					    domain->orig_tab[nstr - 1].offset))
+		  == 0))
+	    return ((char *) domain->data
+		    + W (domain->must_swap,
+			 domain->trans_tab[nstr - 1].offset));
 	}
       /* NOTREACHED */
     }
@@ -590,9 +711,9 @@ _nl_find_msg (domain_file, msgid)
       int cmp_val;
 
       act = (bottom + top) / 2;
-      cmp_val = strcmp (msgid, domain->data
-			       + W (domain->must_swap,
-				    domain->orig_tab[act].offset));
+      cmp_val = strcmp (msgid, (domain->data
+				+ W (domain->must_swap,
+				     domain->orig_tab[act].offset)));
       if (cmp_val < 0)
 	top = act;
       else if (cmp_val > 0)
@@ -602,9 +723,9 @@ _nl_find_msg (domain_file, msgid)
     }
 
   /* If an translation is found return this.  */
-  return bottom >= top ? NULL : (char *) domain->data
-                                + W (domain->must_swap,
-				     domain->trans_tab[act].offset);
+  return bottom >= top ? NULL : ((char *) domain->data
+				 + W (domain->must_swap,
+				      domain->trans_tab[act].offset));
 }
 
 
@@ -728,6 +849,17 @@ stpcpy (dest, src)
 }
 #endif
 
+#if !_LIBC && !HAVE_MEMPCPY
+static void *
+mempcpy (dest, src, n)
+     void *dest;
+     const void *src;
+     size_t n;
+{
+  return (void *) ((char *) memcpy (dst, src, n) + n);
+}
+#endif
+
 
 #ifdef _LIBC
 /* If we want to free all resources we have to do some work at
@@ -748,6 +880,9 @@ free_mem (void)
   if (_nl_current_default_domain != _nl_default_default_domain)
     /* Yes, again a pointer comparison.  */
     free ((char *) _nl_current_default_domain);
+
+  /* Remove the search tree with the know translations.  */
+  __tdestroy (root, free);
 }
 
 text_set_element (__libc_subfreeres, free_mem);