about summary refs log tree commit diff
path: root/intl/dcgettext.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-01-22 05:50:49 +0000
committerUlrich Drepper <drepper@redhat.com>2000-01-22 05:50:49 +0000
commitabbffdf981c8bb03312024107715d58902914f11 (patch)
tree168a2fd362a2c159507b4ed0d2391b6ff3f1e575 /intl/dcgettext.c
parent0b9fbf003af00a2a22164333bbe709aa9abbcdc9 (diff)
downloadglibc-abbffdf981c8bb03312024107715d58902914f11.tar.gz
glibc-abbffdf981c8bb03312024107715d58902914f11.tar.xz
glibc-abbffdf981c8bb03312024107715d58902914f11.zip
Update.
2000-01-21  Ulrich Drepper  <drepper@cygnus.com>

	* intl/Makefile (routines): Add dcigettext, dcngettext, dngettxt,
	ngettext, and plural.
	(distribute): Add plural.y, po2test.sed, and tst-gettext.sh.
	(test-srcs): Add tst-gettext.
	(before-compile): Add $(objpfx)msgs.h.
	Add rules for plural.c and msgs.h generation and running tst-gettext.\
	* intl/Versions [GLIBC_2.2]: Add __dcngettext, dcngettext, dngettext,
	and ngettext.
	* intl/dcgettext.c: Move most code into dcigettext.c.  Add call
	dcigettext with appropriate parameters.
	* intl/dcigettext.c: New file.
	* intl/dcngettext.c: New file.
	* intl/dngettext.c: New file.
	* intl/ngettext.c: New file.
	* intl/gettextP.h (struct expression): Define.
	(struct loaded_domain): Add plural and nplurals members.
	Add prototypes for new internal functions.
	* intl/libintl.h: Declare new functions.  Add optimizations for them.
	* intl/loadinfo.h: Add new parameter to _nl_find_msg declaration.
	* intl/loadmsgcat.c (_nl_load_domain): Search for plural information in
	header entry and parse and store the expression.
	* intl/plural.y: New file.
	* intl/po2test.sed: New file.
	* intl/tst-gettext.c: New file.
	* intl/tst-gettext.sh: New file.

	* intl/gettext.c: Call __dcgettext directly.
Diffstat (limited to 'intl/dcgettext.c')
-rw-r--r--intl/dcgettext.c835
1 files changed, 4 insertions, 831 deletions
diff --git a/intl/dcgettext.c b/intl/dcgettext.c
index 8e51970495..5be8e4ff70 100644
--- a/intl/dcgettext.c
+++ b/intl/dcgettext.c
@@ -1,5 +1,5 @@
 /* Implementation of the dcgettext(3) function.
-   Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc.
 
    This file is part of the GNU C Library.  Its master source is NOT part of
    the C library, however.
@@ -23,70 +23,6 @@
 # include <config.h>
 #endif
 
-#include <sys/types.h>
-
-#if defined __GNUC__ && !defined C_ALLOCA
-# define alloca __builtin_alloca
-# define HAVE_ALLOCA 1
-#else
-# if (defined HAVE_ALLOCA_H || defined _LIBC) && !defined C_ALLOCA
-#  include <alloca.h>
-# else
-#  ifdef _AIX
- #pragma alloca
-#  else
-#   ifndef alloca
-char *alloca ();
-#   endif
-#  endif
-# endif
-#endif
-
-#include <errno.h>
-#ifndef errno
-extern int errno;
-#endif
-#ifndef __set_errno
-# define __set_errno(val) errno = (val)
-#endif
-
-#if defined STDC_HEADERS || defined _LIBC
-# 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
-# ifndef _GNU_SOURCE
-#  define _GNU_SOURCE	1
-# endif
-# include <string.h>
-#else
-# include <strings.h>
-#endif
-#if !HAVE_STRCHR && !defined _LIBC
-# ifndef strchr
-#  define strchr index
-# endif
-#endif
-
-#if defined HAVE_UNISTD_H || defined _LIBC
-# include <unistd.h>
-#endif
-
-#if defined HAVE_LOCALE_H || defined _LIBC
-# include <locale.h>
-#endif
-
-#if defined HAVE_SYS_PARAM_H || defined _LIBC
-# include <sys/param.h>
-#endif
-
 #include "gettext.h"
 #include "gettextP.h"
 #ifdef _LIBC
@@ -94,225 +30,19 @@ void free ();
 #else
 # include "libgettext.h"
 #endif
-#include "hash-string.h"
-
-/* Thread safetyness.  */
-#ifdef _LIBC
-# include <bits/libc-lock.h>
-#endif
 
 /* @@ end of prolog @@ */
 
-#ifdef _LIBC
-/* Rename the non ANSI C functions.  This is required by the standard
-   because some ANSI C functions will require linking with this object
-   file and the name space must not be polluted.  */
-# define getcwd __getcwd
-# ifndef stpcpy
-#  define stpcpy __stpcpy
-# endif
-#else
-# if !defined HAVE_GETCWD
-char *getwd ();
-#  define getcwd(buf, max) getwd (buf)
-# else
-char *getcwd ();
-# endif
-# 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.  */
-#define PATH_INCR 32
-
-/* The following is from pathmax.h.  */
-/* 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__)
-# include <limits.h>
-#endif
-
-#ifndef _POSIX_PATH_MAX
-# define _POSIX_PATH_MAX 255
-#endif
-
-#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
-# include <sys/param.h>
-#endif
-
-#if !defined PATH_MAX && defined MAXPATHLEN
-# define PATH_MAX MAXPATHLEN
-#endif
-
-#ifndef PATH_MAX
-# 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.  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).  */
-#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
-{
-  /* 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";
-
-/* Value used as the default domain for gettext(3).  */
-const char *_nl_current_default_domain = _nl_default_default_domain;
-
-/* Contains the default location of the message catalogs.  */
-const char _nl_default_dirname[] = GNULOCALEDIR;
-
-/* List with bindings of specific domains created by bindtextdomain()
-   calls.  */
-struct binding *_nl_domain_bindings;
-
-/* Prototypes for local functions.  */
-static const char *category_to_name PARAMS ((int category)) internal_function;
-static const char *guess_category_value PARAMS ((int category,
-						 const char *categoryname))
-     internal_function;
-
-
-/* For those loosing systems which don't have `alloca' we have to add
-   some additional code emulating it.  */
-#ifdef HAVE_ALLOCA
-/* Nothing has to be done.  */
-# define ADD_BLOCK(list, address) /* nothing */
-# define FREE_BLOCKS(list) /* nothing */
-#else
-struct block_list
-{
-  void *address;
-  struct block_list *next;
-};
-# define ADD_BLOCK(list, addr)						      \
-  do {									      \
-    struct block_list *newp = (struct block_list *) malloc (sizeof (*newp));  \
-    /* If we cannot get a free block we cannot add the new element to	      \
-       the list.  */							      \
-    if (newp != NULL) {							      \
-      newp->address = (addr);						      \
-      newp->next = (list);						      \
-      (list) = newp;							      \
-    }									      \
-  } while (0)
-# define FREE_BLOCKS(list)						      \
-  do {									      \
-    while (list != NULL) {						      \
-      struct block_list *old = list;					      \
-      list = list->next;						      \
-      free (old);							      \
-    }									      \
-  } while (0)
-# undef alloca
-# define alloca(size) (malloc (size))
-#endif	/* have alloca */
-
-
 /* 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 DCGETTEXT __dcgettext
+# define DCIGETTEXT __dcigettext
 #else
 # define DCGETTEXT dcgettext__
-#endif
-
-/* Checking whether the binaries runs SUID must be done and glibc provides
-   easier methods therefore we make a difference here.  */
-#ifdef _LIBC
-# define ENABLE_SECURE __libc_enable_secure
-# define DETERMINE_SECURE
-#else
-static int enable_secure;
-# define ENABLE_SECURE (enable_secure == 1)
-# define DETERMINE_SECURE \
-  if (enable_secure == 0)						      \
-    {									      \
-      if (getuid () != geteuid () || getgid () != getegid ())		      \
-	enable_secure = 1;						      \
-      else								      \
-	enable_secure = -1;						      \
-    }
+# define DCIGETTEXT dcigettext__
 #endif
 
 /* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
@@ -323,567 +53,10 @@ DCGETTEXT (domainname, msgid, category)
      const char *msgid;
      int category;
 {
-#ifndef HAVE_ALLOCA
-  struct block_list *block_list = NULL;
-#endif
-  struct loaded_l10nfile *domain;
-  struct binding *binding;
-  const char *categoryname;
-  const char *categoryvalue;
-  char *dirname, *xdomainname;
-  char *single_locale;
-  char *retval;
-  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;
-
-  /* If DOMAINNAME is NULL, we are interested in the default domain.  If
-     CATEGORY is not LC_MESSAGES this might not make much sense but the
-     definition left this undefined.  */
-  if (domainname == NULL)
-    domainname = _nl_current_default_domain;
-
-  /* First find matching binding.  */
-  for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
-    {
-      int compare = strcmp (domainname, binding->domainname);
-      if (compare == 0)
-	/* We found it!  */
-	break;
-      if (compare < 0)
-	{
-	  /* It is not in the list.  */
-	  binding = NULL;
-	  break;
-	}
-    }
-
-  if (binding == NULL)
-    dirname = (char *) _nl_default_dirname;
-  else if (binding->dirname[0] == '/')
-    dirname = binding->dirname;
-  else
-    {
-      /* We have a relative path.  Make it absolute now.  */
-      size_t dirname_len = strlen (binding->dirname) + 1;
-      size_t path_max;
-      char *ret;
-
-      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)
-	{
-	  path_max += PATH_INCR;
-	  dirname = (char *) alloca (path_max + dirname_len);
-	  ADD_BLOCK (block_list, dirname);
-	  __set_errno (0);
-	}
-
-      if (ret == NULL)
-	{
-	  /* We cannot get the current working directory.  Don't signal an
-	     error but simply return the default string.  */
-	  FREE_BLOCKS (block_list);
-	  __set_errno (saved_errno);
-	  return (char *) msgid;
-	}
-
-      stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
-    }
-
-  /* Now determine the symbolic name of CATEGORY and its value.  */
-  categoryname = category_to_name (category);
-  categoryvalue = guess_category_value (category, categoryname);
-
-  domainname_len = strlen (domainname);
-  xdomainname = (char *) alloca (strlen (categoryname)
-				 + domainname_len + 5);
-  ADD_BLOCK (block_list, xdomainname);
-
-  stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
-		  domainname, domainname_len),
-	  ".mo");
-
-  /* Creating working area.  */
-  single_locale = (char *) alloca (strlen (categoryvalue) + 1);
-  ADD_BLOCK (block_list, single_locale);
-
-
-  /* Search for the given string.  This is a loop because we perhaps
-     got an ordered list of languages to consider for the translation.  */
-  while (1)
-    {
-      /* Make CATEGORYVALUE point to the next element of the list.  */
-      while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
-	++categoryvalue;
-      if (categoryvalue[0] == '\0')
-	{
-	  /* The whole contents of CATEGORYVALUE has been searched but
-	     no valid entry has been found.  We solve this situation
-	     by implicitly appending a "C" entry, i.e. no translation
-	     will take place.  */
-	  single_locale[0] = 'C';
-	  single_locale[1] = '\0';
-	}
-      else
-	{
-	  char *cp = single_locale;
-	  while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
-	    *cp++ = *categoryvalue++;
-	  *cp = '\0';
-
-	  /* When this is a SUID binary we must not allow accessing files
-	     outside the dedicated directories.  */
-	  if (ENABLE_SECURE
-	      && (memchr (single_locale, '/',
-			  _nl_find_language (single_locale) - single_locale)
-		  != NULL))
-	    /* Ingore this entry.  */
-	    continue;
-	}
-
-      /* If the current locale value is C (or POSIX) we don't load a
-	 domain.  Return the MSGID.  */
-      if (strcmp (single_locale, "C") == 0
-	  || strcmp (single_locale, "POSIX") == 0)
-	{
-	  FREE_BLOCKS (block_list);
-	  __set_errno (saved_errno);
-	  return (char *) msgid;
-	}
-
-
-      /* Find structure describing the message catalog matching the
-	 DOMAINNAME and CATEGORY.  */
-      domain = _nl_find_domain (dirname, single_locale, xdomainname);
-
-      if (domain != NULL)
-	{
-	  retval = _nl_find_msg (domain, msgid);
-
-	  if (retval == NULL)
-	    {
-	      int cnt;
-
-	      for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
-		{
-		  retval = _nl_find_msg (domain->successor[cnt], msgid);
-
-		  if (retval != NULL)
-		    break;
-		}
-	    }
-
-	  if (retval != NULL)
-	    {
-	      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;
-	    }
-	}
-    }
-  /* NOTREACHED */
+  return DCIGETTEXT (domainname, msgid, NULL, 0, 0, category);
 }
 
 #ifdef _LIBC
 /* Alias for function name in GNU C Library.  */
 weak_alias (__dcgettext, dcgettext);
 #endif
-
-
-char *
-internal_function
-_nl_find_msg (domain_file, msgid)
-     struct loaded_l10nfile *domain_file;
-     const char *msgid;
-{
-  size_t act = 0;
-  size_t top, bottom;
-  struct loaded_domain *domain;
-
-  if (domain_file->decided == 0)
-    _nl_load_domain (domain_file);
-
-  if (domain_file->data == NULL)
-    return NULL;
-
-  domain = (struct loaded_domain *) domain_file->data;
-
-  /* Locate the MSGID and its translation.  */
-  if (domain->hash_size > 2 && domain->hash_tab != NULL)
-    {
-      /* Use the hashing table.  */
-      nls_uint32 len = strlen (msgid);
-      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;
-
-      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)
-	{
-	  /* We found an entry.  If we have to convert the string to use
-	     a different character set this is the time.  */
-	  char *result =
-	    (char *) domain->data + W (domain->must_swap,
-				       domain->trans_tab[nstr - 1].offset);
-
-	  if (
-#ifdef _LIBC
-	      domain->conv != (__gconv_t) -1
-#else
-# if HAVE_ICONV
-	      domain->conv != (iconv_t) -1
-# endif
-#endif
-	      )
-	    {
-	      /* We are supposed to do a conversion.  First allocate an
-		 appropriate table with the same structure as the hash
-		 table in the file where we can put the pointers to the
-		 converted strings in.  */
-	      if (domain->conv_tab == NULL
-		  && ((domain->conv_tab = (char **) calloc (domain->hash_size,
-							    sizeof (char *)))
-		      == NULL))
-		/* Mark that we didn't succeed allocating a table.  */
-		domain->conv_tab = (char **) -1;
-
-	      if (domain->conv_tab == (char **) -1)
-		/* Nothing we can do, no more memory.  */
-		return NULL;
-
-	      if (domain->conv_tab[idx] == NULL)
-		{
-		  /* We haven't used this string so far, so it is not
-		     translated yet.  Do this now.  */
-#ifdef _LIBC
-		  /* For glibc we use a bit more efficient memory handling.
-		     We allocate always larger blocks which get used over
-		     time.  This is faster than many small allocations.   */
-		  __libc_lock_define_initialized (static, lock)
-		  static unsigned char *freemem;
-		  static size_t freemem_size;
-		  /* Note that we include the NUL byte.  */
-		  size_t resultlen = strlen (result) + 1;
-		  const unsigned char *inbuf = result;
-		  unsigned char *outbuf = freemem;
-		  size_t written;
-		  int res;
-
-		  __libc_lock_lock (lock);
-
-		  while ((res = __gconv (domain->conv,
-					 &inbuf, inbuf + resultlen,
-					 &outbuf, outbuf + freemem_size,
-					 &written)) == __GCONV_OK)
-		    {
-		      if (res != __GCONV_FULL_OUTPUT)
-			goto out;
-
-		      /* We must resize the buffer.  */
-		      freemem_size = MAX (2 * freemem_size, 4064);
-		      freemem = (char *) malloc (freemem_size);
-		      if (freemem == NULL)
-			goto out;
-
-		      inbuf = result;
-		      outbuf = freemem;
-		    }
-
-		  /* We have now in our buffer a converted string.  Put this
-		     in the hash table  */
-		  domain->conv_tab[idx] = freemem;
-		  freemem_size -= outbuf - freemem;
-		  freemem = outbuf;
-
-		out:
-		  __libc_lock_unlock (lock);
-#endif
-		}
-
-	      result = domain->conv_tab[idx];
-	    }
-
-	  return result;
-	}
-
-      while (1)
-	{
-	  if (idx >= domain->hash_size - incr)
-	    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;
-
-	  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));
-	}
-      /* NOTREACHED */
-    }
-
-  /* Now we try the default method:  binary search in the sorted
-     array of messages.  */
-  bottom = 0;
-  top = domain->nstrings;
-  while (bottom < top)
-    {
-      int cmp_val;
-
-      act = (bottom + top) / 2;
-      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)
-	bottom = act + 1;
-      else
-	break;
-    }
-
-  /* If an translation is found return this.  */
-  return bottom >= top ? NULL : ((char *) domain->data
-				 + W (domain->must_swap,
-				      domain->trans_tab[act].offset));
-}
-
-
-/* Return string representation of locale CATEGORY.  */
-static const char *
-internal_function
-category_to_name (category)
-     int category;
-{
-  const char *retval;
-
-  switch (category)
-  {
-#ifdef LC_COLLATE
-  case LC_COLLATE:
-    retval = "LC_COLLATE";
-    break;
-#endif
-#ifdef LC_CTYPE
-  case LC_CTYPE:
-    retval = "LC_CTYPE";
-    break;
-#endif
-#ifdef LC_MONETARY
-  case LC_MONETARY:
-    retval = "LC_MONETARY";
-    break;
-#endif
-#ifdef LC_NUMERIC
-  case LC_NUMERIC:
-    retval = "LC_NUMERIC";
-    break;
-#endif
-#ifdef LC_TIME
-  case LC_TIME:
-    retval = "LC_TIME";
-    break;
-#endif
-#ifdef LC_MESSAGES
-  case LC_MESSAGES:
-    retval = "LC_MESSAGES";
-    break;
-#endif
-#ifdef LC_RESPONSE
-  case LC_RESPONSE:
-    retval = "LC_RESPONSE";
-    break;
-#endif
-#ifdef LC_ALL
-  case LC_ALL:
-    /* This might not make sense but is perhaps better than any other
-       value.  */
-    retval = "LC_ALL";
-    break;
-#endif
-  default:
-    /* If you have a better idea for a default value let me know.  */
-    retval = "LC_XXX";
-  }
-
-  return retval;
-}
-
-/* Guess value of current locale from value of the environment variables.  */
-static const char *
-internal_function
-guess_category_value (category, categoryname)
-     int category;
-     const char *categoryname;
-{
-  const char *retval;
-
-  /* The highest priority value is the `LANGUAGE' environment
-     variable.  This is a GNU extension.  */
-  retval = getenv ("LANGUAGE");
-  if (retval != NULL && retval[0] != '\0')
-    return retval;
-
-  /* `LANGUAGE' is not set.  So 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 HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
-  return setlocale (category, NULL);
-#else
-  /* Setting of LC_ALL overwrites all other.  */
-  retval = getenv ("LC_ALL");
-  if (retval != NULL && retval[0] != '\0')
-    return retval;
-
-  /* Next comes the name of the desired category.  */
-  retval = getenv (categoryname);
-  if (retval != NULL && retval[0] != '\0')
-    return retval;
-
-  /* Last possibility is the LANG environment variable.  */
-  retval = getenv ("LANG");
-  if (retval != NULL && retval[0] != '\0')
-    return retval;
-
-  /* We use C as the default domain.  POSIX says this is implementation
-     defined.  */
-  return "C";
-#endif
-}
-
-/* @@ 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
-
-#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
-   program's end.  */
-static void __attribute__ ((unused))
-free_mem (void)
-{
-  struct binding *runp;
-
-  for (runp = _nl_domain_bindings; runp != NULL; runp = runp->next)
-    {
-      free (runp->domainname);
-      if (runp->dirname != _nl_default_dirname)
-	/* Yes, this is a pointer comparison.  */
-	free (runp->dirname);
-    }
-
-  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);
-#endif