home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / share / gettext / intl / dcigettext.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-18  |  34.1 KB  |  1,259 lines

  1. /* Implementation of the internal dcigettext function.
  2.    Copyright (C) 1995-1999, 2000-2005 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify it
  5.    under the terms of the GNU Library General Public License as published
  6.    by the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12.    Library General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU Library General Public
  15.    License along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
  17.    USA.  */
  18.  
  19. /* Tell glibc's <string.h> to provide a prototype for mempcpy().
  20.    This must come before <config.h> because <config.h> may include
  21.    <features.h>, and once <features.h> has been included, it's too late.  */
  22. #ifndef _GNU_SOURCE
  23. # define _GNU_SOURCE    1
  24. #endif
  25.  
  26. #ifdef HAVE_CONFIG_H
  27. # include <config.h>
  28. #endif
  29.  
  30. #include <sys/types.h>
  31.  
  32. #ifdef __GNUC__
  33. # define alloca __builtin_alloca
  34. # define HAVE_ALLOCA 1
  35. #else
  36. # ifdef _MSC_VER
  37. #  include <malloc.h>
  38. #  define alloca _alloca
  39. # else
  40. #  if defined HAVE_ALLOCA_H || defined _LIBC
  41. #   include <alloca.h>
  42. #  else
  43. #   ifdef _AIX
  44.  #pragma alloca
  45. #   else
  46. #    ifndef alloca
  47. char *alloca ();
  48. #    endif
  49. #   endif
  50. #  endif
  51. # endif
  52. #endif
  53.  
  54. #include <errno.h>
  55. #ifndef errno
  56. extern int errno;
  57. #endif
  58. #ifndef __set_errno
  59. # define __set_errno(val) errno = (val)
  60. #endif
  61.  
  62. #include <stddef.h>
  63. #include <stdlib.h>
  64. #include <string.h>
  65.  
  66. #if defined HAVE_UNISTD_H || defined _LIBC
  67. # include <unistd.h>
  68. #endif
  69.  
  70. #include <locale.h>
  71.  
  72. #ifdef _LIBC
  73.   /* Guess whether integer division by zero raises signal SIGFPE.
  74.      Set to 1 only if you know for sure.  In case of doubt, set to 0.  */
  75. # if defined __alpha__ || defined __arm__ || defined __i386__ \
  76.      || defined __m68k__ || defined __s390__
  77. #  define INTDIV0_RAISES_SIGFPE 1
  78. # else
  79. #  define INTDIV0_RAISES_SIGFPE 0
  80. # endif
  81. #endif
  82. #if !INTDIV0_RAISES_SIGFPE
  83. # include <signal.h>
  84. #endif
  85.  
  86. #if defined HAVE_SYS_PARAM_H || defined _LIBC
  87. # include <sys/param.h>
  88. #endif
  89.  
  90. #include "gettextP.h"
  91. #include "plural-exp.h"
  92. #ifdef _LIBC
  93. # include <libintl.h>
  94. #else
  95. # include "libgnuintl.h"
  96. #endif
  97. #include "hash-string.h"
  98.  
  99. /* Thread safetyness.  */
  100. #ifdef _LIBC
  101. # include <bits/libc-lock.h>
  102. #else
  103. /* Provide dummy implementation if this is outside glibc.  */
  104. # define __libc_lock_define_initialized(CLASS, NAME)
  105. # define __libc_lock_lock(NAME)
  106. # define __libc_lock_unlock(NAME)
  107. # define __libc_rwlock_define_initialized(CLASS, NAME)
  108. # define __libc_rwlock_rdlock(NAME)
  109. # define __libc_rwlock_unlock(NAME)
  110. #endif
  111.  
  112. /* Alignment of types.  */
  113. #if defined __GNUC__ && __GNUC__ >= 2
  114. # define alignof(TYPE) __alignof__ (TYPE)
  115. #else
  116. # define alignof(TYPE) \
  117.     ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
  118. #endif
  119.  
  120. /* The internal variables in the standalone libintl.a must have different
  121.    names than the internal variables in GNU libc, otherwise programs
  122.    using libintl.a cannot be linked statically.  */
  123. #if !defined _LIBC
  124. # define _nl_default_default_domain libintl_nl_default_default_domain
  125. # define _nl_current_default_domain libintl_nl_current_default_domain
  126. # define _nl_default_dirname libintl_nl_default_dirname
  127. # define _nl_domain_bindings libintl_nl_domain_bindings
  128. #endif
  129.  
  130. /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
  131. #ifndef offsetof
  132. # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
  133. #endif
  134.  
  135. /* @@ end of prolog @@ */
  136.  
  137. #ifdef _LIBC
  138. /* Rename the non ANSI C functions.  This is required by the standard
  139.    because some ANSI C functions will require linking with this object
  140.    file and the name space must not be polluted.  */
  141. # define getcwd __getcwd
  142. # ifndef stpcpy
  143. #  define stpcpy __stpcpy
  144. # endif
  145. # define tfind __tfind
  146. #else
  147. # if !defined HAVE_GETCWD
  148. char *getwd ();
  149. #  define getcwd(buf, max) getwd (buf)
  150. # else
  151. #  if VMS
  152. #   define getcwd(buf, max) (getcwd) (buf, max, 0)
  153. #  else
  154. char *getcwd ();
  155. #  endif
  156. # endif
  157. # ifndef HAVE_STPCPY
  158. static char *stpcpy (char *dest, const char *src);
  159. # endif
  160. # ifndef HAVE_MEMPCPY
  161. static void *mempcpy (void *dest, const void *src, size_t n);
  162. # endif
  163. #endif
  164.  
  165. /* Amount to increase buffer size by in each try.  */
  166. #define PATH_INCR 32
  167.  
  168. /* The following is from pathmax.h.  */
  169. /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
  170.    PATH_MAX but might cause redefinition warnings when sys/param.h is
  171.    later included (as on MORE/BSD 4.3).  */
  172. #if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
  173. # include <limits.h>
  174. #endif
  175.  
  176. #ifndef _POSIX_PATH_MAX
  177. # define _POSIX_PATH_MAX 255
  178. #endif
  179.  
  180. #if !defined PATH_MAX && defined _PC_PATH_MAX
  181. # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
  182. #endif
  183.  
  184. /* Don't include sys/param.h if it already has been.  */
  185. #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
  186. # include <sys/param.h>
  187. #endif
  188.  
  189. #if !defined PATH_MAX && defined MAXPATHLEN
  190. # define PATH_MAX MAXPATHLEN
  191. #endif
  192.  
  193. #ifndef PATH_MAX
  194. # define PATH_MAX _POSIX_PATH_MAX
  195. #endif
  196.  
  197. /* Pathname support.
  198.    ISSLASH(C)           tests whether C is a directory separator character.
  199.    IS_ABSOLUTE_PATH(P)  tests whether P is an absolute path.  If it is not,
  200.                         it may be concatenated to a directory pathname.
  201.    IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
  202.  */
  203. #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
  204.   /* Win32, Cygwin, OS/2, DOS */
  205. # define ISSLASH(C) ((C) == '/' || (C) == '\\')
  206. # define HAS_DEVICE(P) \
  207.     ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
  208.      && (P)[1] == ':')
  209. # define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
  210. # define IS_PATH_WITH_DIR(P) \
  211.     (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
  212. #else
  213.   /* Unix */
  214. # define ISSLASH(C) ((C) == '/')
  215. # define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
  216. # define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
  217. #endif
  218.  
  219. /* This is the type used for the search tree where known translations
  220.    are stored.  */
  221. struct known_translation_t
  222. {
  223.   /* Domain in which to search.  */
  224.   char *domainname;
  225.  
  226.   /* The category.  */
  227.   int category;
  228.  
  229.   /* State of the catalog counter at the point the string was found.  */
  230.   int counter;
  231.  
  232.   /* Catalog where the string was found.  */
  233.   struct loaded_l10nfile *domain;
  234.  
  235.   /* And finally the translation.  */
  236.   const char *translation;
  237.   size_t translation_length;
  238.  
  239.   /* Pointer to the string in question.  */
  240.   char msgid[ZERO];
  241. };
  242.  
  243. /* Root of the search tree with known translations.  We can use this
  244.    only if the system provides the `tsearch' function family.  */
  245. #if defined HAVE_TSEARCH || defined _LIBC
  246. # include <search.h>
  247.  
  248. static void *root;
  249.  
  250. # ifdef _LIBC
  251. #  define tsearch __tsearch
  252. # endif
  253.  
  254. /* Function to compare two entries in the table of known translations.  */
  255. static int
  256. transcmp (const void *p1, const void *p2)
  257. {
  258.   const struct known_translation_t *s1;
  259.   const struct known_translation_t *s2;
  260.   int result;
  261.  
  262.   s1 = (const struct known_translation_t *) p1;
  263.   s2 = (const struct known_translation_t *) p2;
  264.  
  265.   result = strcmp (s1->msgid, s2->msgid);
  266.   if (result == 0)
  267.     {
  268.       result = strcmp (s1->domainname, s2->domainname);
  269.       if (result == 0)
  270.     /* We compare the category last (though this is the cheapest
  271.        operation) since it is hopefully always the same (namely
  272.        LC_MESSAGES).  */
  273.     result = s1->category - s2->category;
  274.     }
  275.  
  276.   return result;
  277. }
  278. #endif
  279.  
  280. #ifndef INTVARDEF
  281. # define INTVARDEF(name)
  282. #endif
  283. #ifndef INTUSE
  284. # define INTUSE(name) name
  285. #endif
  286.  
  287. /* Name of the default domain used for gettext(3) prior any call to
  288.    textdomain(3).  The default value for this is "messages".  */
  289. const char _nl_default_default_domain[] attribute_hidden = "messages";
  290.  
  291. /* Value used as the default domain for gettext(3).  */
  292. const char *_nl_current_default_domain attribute_hidden
  293.      = _nl_default_default_domain;
  294.  
  295. /* Contains the default location of the message catalogs.  */
  296. #if defined __EMX__
  297. extern const char _nl_default_dirname[];
  298. #else
  299. const char _nl_default_dirname[] = LOCALEDIR;
  300. INTVARDEF (_nl_default_dirname)
  301. #endif
  302.  
  303. /* List with bindings of specific domains created by bindtextdomain()
  304.    calls.  */
  305. struct binding *_nl_domain_bindings;
  306.  
  307. /* Prototypes for local functions.  */
  308. static char *plural_lookup (struct loaded_l10nfile *domain,
  309.                 unsigned long int n,
  310.                 const char *translation, size_t translation_len)
  311.      internal_function;
  312. static const char *guess_category_value (int category,
  313.                      const char *categoryname)
  314.      internal_function;
  315. #ifdef _LIBC
  316. # include "../locale/localeinfo.h"
  317. # define category_to_name(category)    _nl_category_names[category]
  318. #else
  319. static const char *category_to_name (int category) internal_function;
  320. #endif
  321.  
  322.  
  323. /* For those loosing systems which don't have `alloca' we have to add
  324.    some additional code emulating it.  */
  325. #ifdef HAVE_ALLOCA
  326. /* Nothing has to be done.  */
  327. # define freea(p) /* nothing */
  328. # define ADD_BLOCK(list, address) /* nothing */
  329. # define FREE_BLOCKS(list) /* nothing */
  330. #else
  331. struct block_list
  332. {
  333.   void *address;
  334.   struct block_list *next;
  335. };
  336. # define ADD_BLOCK(list, addr)                              \
  337.   do {                                          \
  338.     struct block_list *newp = (struct block_list *) malloc (sizeof (*newp));  \
  339.     /* If we cannot get a free block we cannot add the new element to          \
  340.        the list.  */                                  \
  341.     if (newp != NULL) {                                  \
  342.       newp->address = (addr);                              \
  343.       newp->next = (list);                              \
  344.       (list) = newp;                                  \
  345.     }                                          \
  346.   } while (0)
  347. # define FREE_BLOCKS(list)                              \
  348.   do {                                          \
  349.     while (list != NULL) {                              \
  350.       struct block_list *old = list;                          \
  351.       list = list->next;                              \
  352.       free (old->address);                              \
  353.       free (old);                                  \
  354.     }                                          \
  355.   } while (0)
  356. # undef alloca
  357. # define alloca(size) (malloc (size))
  358. # define freea(p) free (p)
  359. #endif    /* have alloca */
  360.  
  361.  
  362. #ifdef _LIBC
  363. /* List of blocks allocated for translations.  */
  364. typedef struct transmem_list
  365. {
  366.   struct transmem_list *next;
  367.   char data[ZERO];
  368. } transmem_block_t;
  369. static struct transmem_list *transmem_list;
  370. #else
  371. typedef unsigned char transmem_block_t;
  372. #endif
  373.  
  374.  
  375. /* Names for the libintl functions are a problem.  They must not clash
  376.    with existing names and they should follow ANSI C.  But this source
  377.    code is also used in GNU C Library where the names have a __
  378.    prefix.  So we have to make a difference here.  */
  379. #ifdef _LIBC
  380. # define DCIGETTEXT __dcigettext
  381. #else
  382. # define DCIGETTEXT libintl_dcigettext
  383. #endif
  384.  
  385. /* Lock variable to protect the global data in the gettext implementation.  */
  386. #ifdef _LIBC
  387. __libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
  388. #endif
  389.  
  390. /* Checking whether the binaries runs SUID must be done and glibc provides
  391.    easier methods therefore we make a difference here.  */
  392. #ifdef _LIBC
  393. # define ENABLE_SECURE __libc_enable_secure
  394. # define DETERMINE_SECURE
  395. #else
  396. # ifndef HAVE_GETUID
  397. #  define getuid() 0
  398. # endif
  399. # ifndef HAVE_GETGID
  400. #  define getgid() 0
  401. # endif
  402. # ifndef HAVE_GETEUID
  403. #  define geteuid() getuid()
  404. # endif
  405. # ifndef HAVE_GETEGID
  406. #  define getegid() getgid()
  407. # endif
  408. static int enable_secure;
  409. # define ENABLE_SECURE (enable_secure == 1)
  410. # define DETERMINE_SECURE \
  411.   if (enable_secure == 0)                              \
  412.     {                                          \
  413.       if (getuid () != geteuid () || getgid () != getegid ())              \
  414.     enable_secure = 1;                              \
  415.       else                                      \
  416.     enable_secure = -1;                              \
  417.     }
  418. #endif
  419.  
  420. /* Get the function to evaluate the plural expression.  */
  421. #include "eval-plural.h"
  422.  
  423. /* Look up MSGID in the DOMAINNAME message catalog for the current
  424.    CATEGORY locale and, if PLURAL is nonzero, search over string
  425.    depending on the plural form determined by N.  */
  426. char *
  427. DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
  428.         int plural, unsigned long int n, int category)
  429. {
  430. #ifndef HAVE_ALLOCA
  431.   struct block_list *block_list = NULL;
  432. #endif
  433.   struct loaded_l10nfile *domain;
  434.   struct binding *binding;
  435.   const char *categoryname;
  436.   const char *categoryvalue;
  437.   char *dirname, *xdomainname;
  438.   char *single_locale;
  439.   char *retval;
  440.   size_t retlen;
  441.   int saved_errno;
  442. #if defined HAVE_TSEARCH || defined _LIBC
  443.   struct known_translation_t *search;
  444.   struct known_translation_t **foundp = NULL;
  445.   size_t msgid_len;
  446. #endif
  447.   size_t domainname_len;
  448.  
  449.   /* If no real MSGID is given return NULL.  */
  450.   if (msgid1 == NULL)
  451.     return NULL;
  452.  
  453. #ifdef _LIBC
  454.   if (category < 0 || category >= __LC_LAST || category == LC_ALL)
  455.     /* Bogus.  */
  456.     return (plural == 0
  457.         ? (char *) msgid1
  458.         /* Use the Germanic plural rule.  */
  459.         : n == 1 ? (char *) msgid1 : (char *) msgid2);
  460. #endif
  461.  
  462.   __libc_rwlock_rdlock (_nl_state_lock);
  463.  
  464.   /* If DOMAINNAME is NULL, we are interested in the default domain.  If
  465.      CATEGORY is not LC_MESSAGES this might not make much sense but the
  466.      definition left this undefined.  */
  467.   if (domainname == NULL)
  468.     domainname = _nl_current_default_domain;
  469.  
  470.   /* OS/2 specific: backward compatibility with older libintl versions  */
  471. #ifdef LC_MESSAGES_COMPAT
  472.   if (category == LC_MESSAGES_COMPAT)
  473.     category = LC_MESSAGES;
  474. #endif
  475.  
  476. #if defined HAVE_TSEARCH || defined _LIBC
  477.   msgid_len = strlen (msgid1) + 1;
  478.  
  479.   /* Try to find the translation among those which we found at
  480.      some time.  */
  481.   search = (struct known_translation_t *)
  482.        alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
  483.   memcpy (search->msgid, msgid1, msgid_len);
  484.   search->domainname = (char *) domainname;
  485.   search->category = category;
  486.  
  487.   foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
  488.   freea (search);
  489.   if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
  490.     {
  491.       /* Now deal with plural.  */
  492.       if (plural)
  493.     retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
  494.                 (*foundp)->translation_length);
  495.       else
  496.     retval = (char *) (*foundp)->translation;
  497.  
  498.       __libc_rwlock_unlock (_nl_state_lock);
  499.       return retval;
  500.     }
  501. #endif
  502.  
  503.   /* Preserve the `errno' value.  */
  504.   saved_errno = errno;
  505.  
  506.   /* See whether this is a SUID binary or not.  */
  507.   DETERMINE_SECURE;
  508.  
  509.   /* First find matching binding.  */
  510.   for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
  511.     {
  512.       int compare = strcmp (domainname, binding->domainname);
  513.       if (compare == 0)
  514.     /* We found it!  */
  515.     break;
  516.       if (compare < 0)
  517.     {
  518.       /* It is not in the list.  */
  519.       binding = NULL;
  520.       break;
  521.     }
  522.     }
  523.  
  524.   if (binding == NULL)
  525.     dirname = (char *) INTUSE(_nl_default_dirname);
  526.   else if (IS_ABSOLUTE_PATH (binding->dirname))
  527.     dirname = binding->dirname;
  528.   else
  529.     {
  530.       /* We have a relative path.  Make it absolute now.  */
  531.       size_t dirname_len = strlen (binding->dirname) + 1;
  532.       size_t path_max;
  533.       char *ret;
  534.  
  535.       path_max = (unsigned int) PATH_MAX;
  536.       path_max += 2;        /* The getcwd docs say to do this.  */
  537.  
  538.       for (;;)
  539.     {
  540.       dirname = (char *) alloca (path_max + dirname_len);
  541.       ADD_BLOCK (block_list, dirname);
  542.  
  543.       __set_errno (0);
  544.       ret = getcwd (dirname, path_max);
  545.       if (ret != NULL || errno != ERANGE)
  546.         break;
  547.  
  548.       path_max += path_max / 2;
  549.       path_max += PATH_INCR;
  550.     }
  551.  
  552.       if (ret == NULL)
  553.     /* We cannot get the current working directory.  Don't signal an
  554.        error but simply return the default string.  */
  555.     goto return_untranslated;
  556.  
  557.       stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
  558.     }
  559.  
  560.   /* Now determine the symbolic name of CATEGORY and its value.  */
  561.   categoryname = category_to_name (category);
  562.   categoryvalue = guess_category_value (category, categoryname);
  563.  
  564.   domainname_len = strlen (domainname);
  565.   xdomainname = (char *) alloca (strlen (categoryname)
  566.                  + domainname_len + 5);
  567.   ADD_BLOCK (block_list, xdomainname);
  568.  
  569.   stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
  570.           domainname, domainname_len),
  571.       ".mo");
  572.  
  573.   /* Creating working area.  */
  574.   single_locale = (char *) alloca (strlen (categoryvalue) + 1);
  575.   ADD_BLOCK (block_list, single_locale);
  576.  
  577.  
  578.   /* Search for the given string.  This is a loop because we perhaps
  579.      got an ordered list of languages to consider for the translation.  */
  580.   while (1)
  581.     {
  582.       /* Make CATEGORYVALUE point to the next element of the list.  */
  583.       while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
  584.     ++categoryvalue;
  585.       if (categoryvalue[0] == '\0')
  586.     {
  587.       /* The whole contents of CATEGORYVALUE has been searched but
  588.          no valid entry has been found.  We solve this situation
  589.          by implicitly appending a "C" entry, i.e. no translation
  590.          will take place.  */
  591.       single_locale[0] = 'C';
  592.       single_locale[1] = '\0';
  593.     }
  594.       else
  595.     {
  596.       char *cp = single_locale;
  597.       while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
  598.         *cp++ = *categoryvalue++;
  599.       *cp = '\0';
  600.  
  601.       /* When this is a SUID binary we must not allow accessing files
  602.          outside the dedicated directories.  */
  603.       if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale))
  604.         /* Ingore this entry.  */
  605.         continue;
  606.     }
  607.  
  608.       /* If the current locale value is C (or POSIX) we don't load a
  609.      domain.  Return the MSGID.  */
  610.       if (strcmp (single_locale, "C") == 0
  611.       || strcmp (single_locale, "POSIX") == 0)
  612.     break;
  613.  
  614.       /* Find structure describing the message catalog matching the
  615.      DOMAINNAME and CATEGORY.  */
  616.       domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
  617.  
  618.       if (domain != NULL)
  619.     {
  620.       retval = _nl_find_msg (domain, binding, msgid1, &retlen);
  621.  
  622.       if (retval == NULL)
  623.         {
  624.           int cnt;
  625.  
  626.           for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
  627.         {
  628.           retval = _nl_find_msg (domain->successor[cnt], binding,
  629.                      msgid1, &retlen);
  630.  
  631.           if (retval != NULL)
  632.             {
  633.               domain = domain->successor[cnt];
  634.               break;
  635.             }
  636.         }
  637.         }
  638.  
  639.       if (retval != NULL)
  640.         {
  641.           /* Found the translation of MSGID1 in domain DOMAIN:
  642.          starting at RETVAL, RETLEN bytes.  */
  643.           FREE_BLOCKS (block_list);
  644. #if defined HAVE_TSEARCH || defined _LIBC
  645.           if (foundp == NULL)
  646.         {
  647.           /* Create a new entry and add it to the search tree.  */
  648.           struct known_translation_t *newp;
  649.  
  650.           newp = (struct known_translation_t *)
  651.             malloc (offsetof (struct known_translation_t, msgid)
  652.                 + msgid_len + domainname_len + 1);
  653.           if (newp != NULL)
  654.             {
  655.               newp->domainname =
  656.             mempcpy (newp->msgid, msgid1, msgid_len);
  657.               memcpy (newp->domainname, domainname, domainname_len + 1);
  658.               newp->category = category;
  659.               newp->counter = _nl_msg_cat_cntr;
  660.               newp->domain = domain;
  661.               newp->translation = retval;
  662.               newp->translation_length = retlen;
  663.  
  664.               /* Insert the entry in the search tree.  */
  665.               foundp = (struct known_translation_t **)
  666.             tsearch (newp, &root, transcmp);
  667.               if (foundp == NULL
  668.               || __builtin_expect (*foundp != newp, 0))
  669.             /* The insert failed.  */
  670.             free (newp);
  671.             }
  672.         }
  673.           else
  674.         {
  675.           /* We can update the existing entry.  */
  676.           (*foundp)->counter = _nl_msg_cat_cntr;
  677.           (*foundp)->domain = domain;
  678.           (*foundp)->translation = retval;
  679.           (*foundp)->translation_length = retlen;
  680.         }
  681. #endif
  682.           __set_errno (saved_errno);
  683.  
  684.           /* Now deal with plural.  */
  685.           if (plural)
  686.         retval = plural_lookup (domain, n, retval, retlen);
  687.  
  688.           __libc_rwlock_unlock (_nl_state_lock);
  689.           return retval;
  690.         }
  691.     }
  692.     }
  693.  
  694.  return_untranslated:
  695.   /* Return the untranslated MSGID.  */
  696.   FREE_BLOCKS (block_list);
  697.   __libc_rwlock_unlock (_nl_state_lock);
  698. #ifndef _LIBC
  699.   if (!ENABLE_SECURE)
  700.     {
  701.       extern void _nl_log_untranslated (const char *logfilename,
  702.                     const char *domainname,
  703.                     const char *msgid1, const char *msgid2,
  704.                     int plural);
  705.       const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED");
  706.  
  707.       if (logfilename != NULL && logfilename[0] != '\0')
  708.     _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural);
  709.     }
  710. #endif
  711.   __set_errno (saved_errno);
  712.   return (plural == 0
  713.       ? (char *) msgid1
  714.       /* Use the Germanic plural rule.  */
  715.       : n == 1 ? (char *) msgid1 : (char *) msgid2);
  716. }
  717.  
  718.  
  719. char *
  720. internal_function
  721. _nl_find_msg (struct loaded_l10nfile *domain_file,
  722.           struct binding *domainbinding, const char *msgid,
  723.           size_t *lengthp)
  724. {
  725.   struct loaded_domain *domain;
  726.   nls_uint32 nstrings;
  727.   size_t act;
  728.   char *result;
  729.   size_t resultlen;
  730.  
  731.   if (domain_file->decided == 0)
  732.     _nl_load_domain (domain_file, domainbinding);
  733.  
  734.   if (domain_file->data == NULL)
  735.     return NULL;
  736.  
  737.   domain = (struct loaded_domain *) domain_file->data;
  738.  
  739.   nstrings = domain->nstrings;
  740.  
  741.   /* Locate the MSGID and its translation.  */
  742.   if (domain->hash_tab != NULL)
  743.     {
  744.       /* Use the hashing table.  */
  745.       nls_uint32 len = strlen (msgid);
  746.       nls_uint32 hash_val = hash_string (msgid);
  747.       nls_uint32 idx = hash_val % domain->hash_size;
  748.       nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
  749.  
  750.       while (1)
  751.     {
  752.       nls_uint32 nstr =
  753.         W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
  754.  
  755.       if (nstr == 0)
  756.         /* Hash table entry is empty.  */
  757.         return NULL;
  758.  
  759.       nstr--;
  760.  
  761.       /* Compare msgid with the original string at index nstr.
  762.          We compare the lengths with >=, not ==, because plural entries
  763.          are represented by strings with an embedded NUL.  */
  764.       if (nstr < nstrings
  765.           ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
  766.         && (strcmp (msgid,
  767.                 domain->data + W (domain->must_swap,
  768.                           domain->orig_tab[nstr].offset))
  769.             == 0)
  770.           : domain->orig_sysdep_tab[nstr - nstrings].length > len
  771.         && (strcmp (msgid,
  772.                 domain->orig_sysdep_tab[nstr - nstrings].pointer)
  773.             == 0))
  774.         {
  775.           act = nstr;
  776.           goto found;
  777.         }
  778.  
  779.       if (idx >= domain->hash_size - incr)
  780.         idx -= domain->hash_size - incr;
  781.       else
  782.         idx += incr;
  783.     }
  784.       /* NOTREACHED */
  785.     }
  786.   else
  787.     {
  788.       /* Try the default method:  binary search in the sorted array of
  789.      messages.  */
  790.       size_t top, bottom;
  791.  
  792.       bottom = 0;
  793.       top = nstrings;
  794.       while (bottom < top)
  795.     {
  796.       int cmp_val;
  797.  
  798.       act = (bottom + top) / 2;
  799.       cmp_val = strcmp (msgid, (domain->data
  800.                     + W (domain->must_swap,
  801.                      domain->orig_tab[act].offset)));
  802.       if (cmp_val < 0)
  803.         top = act;
  804.       else if (cmp_val > 0)
  805.         bottom = act + 1;
  806.       else
  807.         goto found;
  808.     }
  809.       /* No translation was found.  */
  810.       return NULL;
  811.     }
  812.  
  813.  found:
  814.   /* The translation was found at index ACT.  If we have to convert the
  815.      string to use a different character set, this is the time.  */
  816.   if (act < nstrings)
  817.     {
  818.       result = (char *)
  819.     (domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
  820.       resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
  821.     }
  822.   else
  823.     {
  824.       result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
  825.       resultlen = domain->trans_sysdep_tab[act - nstrings].length;
  826.     }
  827.  
  828. #if defined _LIBC || HAVE_ICONV
  829.   if (domain->codeset_cntr
  830.       != (domainbinding != NULL ? domainbinding->codeset_cntr : 0))
  831.     {
  832.       /* The domain's codeset has changed through bind_textdomain_codeset()
  833.      since the message catalog was initialized or last accessed.  We
  834.      have to reinitialize the converter.  */
  835.       _nl_free_domain_conv (domain);
  836.       _nl_init_domain_conv (domain_file, domain, domainbinding);
  837.     }
  838.  
  839.   if (
  840. # ifdef _LIBC
  841.       domain->conv != (__gconv_t) -1
  842. # else
  843. #  if HAVE_ICONV
  844.       domain->conv != (iconv_t) -1
  845. #  endif
  846. # endif
  847.       )
  848.     {
  849.       /* We are supposed to do a conversion.  First allocate an
  850.      appropriate table with the same structure as the table
  851.      of translations in the file, where we can put the pointers
  852.      to the converted strings in.
  853.      There is a slight complication with plural entries.  They
  854.      are represented by consecutive NUL terminated strings.  We
  855.      handle this case by converting RESULTLEN bytes, including
  856.      NULs.  */
  857.  
  858.       if (domain->conv_tab == NULL
  859.       && ((domain->conv_tab =
  860.          (char **) calloc (nstrings + domain->n_sysdep_strings,
  861.                    sizeof (char *)))
  862.           == NULL))
  863.     /* Mark that we didn't succeed allocating a table.  */
  864.     domain->conv_tab = (char **) -1;
  865.  
  866.       if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
  867.     /* Nothing we can do, no more memory.  */
  868.     goto converted;
  869.  
  870.       if (domain->conv_tab[act] == NULL)
  871.     {
  872.       /* We haven't used this string so far, so it is not
  873.          translated yet.  Do this now.  */
  874.       /* We use a bit more efficient memory handling.
  875.          We allocate always larger blocks which get used over
  876.          time.  This is faster than many small allocations.   */
  877.       __libc_lock_define_initialized (static, lock)
  878. # define INITIAL_BLOCK_SIZE    4080
  879.       static unsigned char *freemem;
  880.       static size_t freemem_size;
  881.  
  882.       const unsigned char *inbuf;
  883.       unsigned char *outbuf;
  884.       int malloc_count;
  885. # ifndef _LIBC
  886.       transmem_block_t *transmem_list = NULL;
  887. # endif
  888.  
  889.       __libc_lock_lock (lock);
  890.  
  891.       inbuf = (const unsigned char *) result;
  892.       outbuf = freemem + sizeof (size_t);
  893.  
  894.       malloc_count = 0;
  895.       while (1)
  896.         {
  897.           transmem_block_t *newmem;
  898. # ifdef _LIBC
  899.           size_t non_reversible;
  900.           int res;
  901.  
  902.           if (freemem_size < sizeof (size_t))
  903.         goto resize_freemem;
  904.  
  905.           res = __gconv (domain->conv,
  906.                  &inbuf, inbuf + resultlen,
  907.                  &outbuf,
  908.                  outbuf + freemem_size - sizeof (size_t),
  909.                  &non_reversible);
  910.  
  911.           if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
  912.         break;
  913.  
  914.           if (res != __GCONV_FULL_OUTPUT)
  915.         {
  916.           __libc_lock_unlock (lock);
  917.           goto converted;
  918.         }
  919.  
  920.           inbuf = result;
  921. # else
  922. #  if HAVE_ICONV
  923.           const char *inptr = (const char *) inbuf;
  924.           size_t inleft = resultlen;
  925.           char *outptr = (char *) outbuf;
  926.           size_t outleft;
  927.  
  928.           if (freemem_size < sizeof (size_t))
  929.         goto resize_freemem;
  930.  
  931.           outleft = freemem_size - sizeof (size_t);
  932.           if (iconv (domain->conv,
  933.              (ICONV_CONST char **) &inptr, &inleft,
  934.              &outptr, &outleft)
  935.           != (size_t) (-1))
  936.         {
  937.           outbuf = (unsigned char *) outptr;
  938.           break;
  939.         }
  940.           if (errno != E2BIG)
  941.         {
  942.           __libc_lock_unlock (lock);
  943.           goto converted;
  944.         }
  945. #  endif
  946. # endif
  947.  
  948.         resize_freemem:
  949.           /* We must allocate a new buffer or resize the old one.  */
  950.           if (malloc_count > 0)
  951.         {
  952.           ++malloc_count;
  953.           freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
  954.           newmem = (transmem_block_t *) realloc (transmem_list,
  955.                              freemem_size);
  956. # ifdef _LIBC
  957.           if (newmem != NULL)
  958.             transmem_list = transmem_list->next;
  959.           else
  960.             {
  961.               struct transmem_list *old = transmem_list;
  962.  
  963.               transmem_list = transmem_list->next;
  964.               free (old);
  965.             }
  966. # endif
  967.         }
  968.           else
  969.         {
  970.           malloc_count = 1;
  971.           freemem_size = INITIAL_BLOCK_SIZE;
  972.           newmem = (transmem_block_t *) malloc (freemem_size);
  973.         }
  974.           if (__builtin_expect (newmem == NULL, 0))
  975.         {
  976.           freemem = NULL;
  977.           freemem_size = 0;
  978.           __libc_lock_unlock (lock);
  979.           goto converted;
  980.         }
  981.  
  982. # ifdef _LIBC
  983.           /* Add the block to the list of blocks we have to free
  984.                  at some point.  */
  985.           newmem->next = transmem_list;
  986.           transmem_list = newmem;
  987.  
  988.           freemem = newmem->data;
  989.           freemem_size -= offsetof (struct transmem_list, data);
  990. # else
  991.           transmem_list = newmem;
  992.           freemem = newmem;
  993. # endif
  994.  
  995.           outbuf = freemem + sizeof (size_t);
  996.         }
  997.  
  998.       /* We have now in our buffer a converted string.  Put this
  999.          into the table of conversions.  */
  1000.       *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
  1001.       domain->conv_tab[act] = (char *) freemem;
  1002.       /* Shrink freemem, but keep it aligned.  */
  1003.       freemem_size -= outbuf - freemem;
  1004.       freemem = outbuf;
  1005.       freemem += freemem_size & (alignof (size_t) - 1);
  1006.       freemem_size = freemem_size & ~ (alignof (size_t) - 1);
  1007.  
  1008.       __libc_lock_unlock (lock);
  1009.     }
  1010.  
  1011.       /* Now domain->conv_tab[act] contains the translation of all
  1012.      the plural variants.  */
  1013.       result = domain->conv_tab[act] + sizeof (size_t);
  1014.       resultlen = *(size_t *) domain->conv_tab[act];
  1015.     }
  1016.  
  1017.  converted:
  1018.   /* The result string is converted.  */
  1019.  
  1020. #endif /* _LIBC || HAVE_ICONV */
  1021.  
  1022.   *lengthp = resultlen;
  1023.   return result;
  1024. }
  1025.  
  1026.  
  1027. /* Look up a plural variant.  */
  1028. static char *
  1029. internal_function
  1030. plural_lookup (struct loaded_l10nfile *domain, unsigned long int n,
  1031.            const char *translation, size_t translation_len)
  1032. {
  1033.   struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
  1034.   unsigned long int index;
  1035.   const char *p;
  1036.  
  1037.   index = plural_eval (domaindata->plural, n);
  1038.   if (index >= domaindata->nplurals)
  1039.     /* This should never happen.  It means the plural expression and the
  1040.        given maximum value do not match.  */
  1041.     index = 0;
  1042.  
  1043.   /* Skip INDEX strings at TRANSLATION.  */
  1044.   p = translation;
  1045.   while (index-- > 0)
  1046.     {
  1047. #ifdef _LIBC
  1048.       p = __rawmemchr (p, '\0');
  1049. #else
  1050.       p = strchr (p, '\0');
  1051. #endif
  1052.       /* And skip over the NUL byte.  */
  1053.       p++;
  1054.  
  1055.       if (p >= translation + translation_len)
  1056.     /* This should never happen.  It means the plural expression
  1057.        evaluated to a value larger than the number of variants
  1058.        available for MSGID1.  */
  1059.     return (char *) translation;
  1060.     }
  1061.   return (char *) p;
  1062. }
  1063.  
  1064. #ifndef _LIBC
  1065. /* Return string representation of locale CATEGORY.  */
  1066. static const char *
  1067. internal_function
  1068. category_to_name (int category)
  1069. {
  1070.   const char *retval;
  1071.  
  1072.   switch (category)
  1073.   {
  1074. #ifdef LC_COLLATE
  1075.   case LC_COLLATE:
  1076.     retval = "LC_COLLATE";
  1077.     break;
  1078. #endif
  1079. #ifdef LC_CTYPE
  1080.   case LC_CTYPE:
  1081.     retval = "LC_CTYPE";
  1082.     break;
  1083. #endif
  1084. #ifdef LC_MONETARY
  1085.   case LC_MONETARY:
  1086.     retval = "LC_MONETARY";
  1087.     break;
  1088. #endif
  1089. #ifdef LC_NUMERIC
  1090.   case LC_NUMERIC:
  1091.     retval = "LC_NUMERIC";
  1092.     break;
  1093. #endif
  1094. #ifdef LC_TIME
  1095.   case LC_TIME:
  1096.     retval = "LC_TIME";
  1097.     break;
  1098. #endif
  1099. #ifdef LC_MESSAGES
  1100.   case LC_MESSAGES:
  1101.     retval = "LC_MESSAGES";
  1102.     break;
  1103. #endif
  1104. #ifdef LC_RESPONSE
  1105.   case LC_RESPONSE:
  1106.     retval = "LC_RESPONSE";
  1107.     break;
  1108. #endif
  1109. #ifdef LC_ALL
  1110.   case LC_ALL:
  1111.     /* This might not make sense but is perhaps better than any other
  1112.        value.  */
  1113.     retval = "LC_ALL";
  1114.     break;
  1115. #endif
  1116.   default:
  1117.     /* If you have a better idea for a default value let me know.  */
  1118.     retval = "LC_XXX";
  1119.   }
  1120.  
  1121.   return retval;
  1122. }
  1123. #endif
  1124.  
  1125. /* Guess value of current locale from value of the environment variables
  1126.    or system-dependent defaults.  */
  1127. static const char *
  1128. internal_function
  1129. guess_category_value (int category, const char *categoryname)
  1130. {
  1131.   const char *language;
  1132.   const char *locale;
  1133. #ifndef _LIBC
  1134.   const char *language_default;
  1135.   int locale_defaulted;
  1136. #endif
  1137.  
  1138.   /* We use the settings in the following order:
  1139.      1. The value of the environment variable 'LANGUAGE'.  This is a GNU
  1140.         extension.  Its value can be a colon-separated list of locale names.
  1141.      2. The value of the environment variable 'LC_ALL', 'LC_xxx', or 'LANG'.
  1142.         More precisely, the first among these that is set to a non-empty value.
  1143.         This is how POSIX specifies it.  The value is a single locale name.
  1144.      3. A system-dependent preference list of languages.  Its value can be a
  1145.         colon-separated list of locale names.
  1146.      4. A system-dependent default locale name.
  1147.      This way:
  1148.        - System-dependent settings can be overridden by environment variables.
  1149.        - If the system provides both a list of languages and a default locale,
  1150.          the former is used.  */
  1151.  
  1152.   /* Fetch the locale name, through the POSIX method of looking to `LC_ALL',
  1153.      `LC_xxx', and `LANG'.  On some systems this can be done by the
  1154.      `setlocale' function itself.  */
  1155. #ifdef _LIBC
  1156.   locale = __current_locale_name (category);
  1157. #else
  1158.   locale = _nl_locale_name_posix (category, categoryname);
  1159.   locale_defaulted = 0;
  1160.   if (locale == NULL)
  1161.     {
  1162.       locale = _nl_locale_name_default ();
  1163.       locale_defaulted = 1;
  1164.     }
  1165. #endif
  1166.  
  1167.   /* Ignore LANGUAGE and its system-dependent analogon if the locale is set
  1168.      to "C" because
  1169.      1. "C" locale usually uses the ASCII encoding, and most international
  1170.     messages use non-ASCII characters. These characters get displayed
  1171.     as question marks (if using glibc's iconv()) or as invalid 8-bit
  1172.     characters (because other iconv()s refuse to convert most non-ASCII
  1173.     characters to ASCII). In any case, the output is ugly.
  1174.      2. The precise output of some programs in the "C" locale is specified
  1175.     by POSIX and should not depend on environment variables like
  1176.     "LANGUAGE" or system-dependent information.  We allow such programs
  1177.         to use gettext().  */
  1178.   if (strcmp (locale, "C") == 0)
  1179.     return locale;
  1180.  
  1181.   /* The highest priority value is the value of the 'LANGUAGE' environment
  1182.      variable.  */
  1183.   language = getenv ("LANGUAGE");
  1184.   if (language != NULL && language[0] != '\0')
  1185.     return language;
  1186. #ifndef _LIBC
  1187.   /* The next priority value is the locale name, if not defaulted.  */
  1188.   if (locale_defaulted)
  1189.     {
  1190.       /* The next priority value is the default language preferences list. */
  1191.       language_default = _nl_language_preferences_default ();
  1192.       if (language_default != NULL)
  1193.         return language_default;
  1194.     }
  1195.   /* The least priority value is the locale name, if defaulted.  */
  1196. #endif
  1197.   return locale;
  1198. }
  1199.  
  1200. /* @@ begin of epilog @@ */
  1201.  
  1202. /* We don't want libintl.a to depend on any other library.  So we
  1203.    avoid the non-standard function stpcpy.  In GNU C Library this
  1204.    function is available, though.  Also allow the symbol HAVE_STPCPY
  1205.    to be defined.  */
  1206. #if !_LIBC && !HAVE_STPCPY
  1207. static char *
  1208. stpcpy (char *dest, const char *src)
  1209. {
  1210.   while ((*dest++ = *src++) != '\0')
  1211.     /* Do nothing. */ ;
  1212.   return dest - 1;
  1213. }
  1214. #endif
  1215.  
  1216. #if !_LIBC && !HAVE_MEMPCPY
  1217. static void *
  1218. mempcpy (void *dest, const void *src, size_t n)
  1219. {
  1220.   return (void *) ((char *) memcpy (dest, src, n) + n);
  1221. }
  1222. #endif
  1223.  
  1224.  
  1225. #ifdef _LIBC
  1226. /* If we want to free all resources we have to do some work at
  1227.    program's end.  */
  1228. libc_freeres_fn (free_mem)
  1229. {
  1230.   void *old;
  1231.  
  1232.   while (_nl_domain_bindings != NULL)
  1233.     {
  1234.       struct binding *oldp = _nl_domain_bindings;
  1235.       _nl_domain_bindings = _nl_domain_bindings->next;
  1236.       if (oldp->dirname != INTUSE(_nl_default_dirname))
  1237.     /* Yes, this is a pointer comparison.  */
  1238.     free (oldp->dirname);
  1239.       free (oldp->codeset);
  1240.       free (oldp);
  1241.     }
  1242.  
  1243.   if (_nl_current_default_domain != _nl_default_default_domain)
  1244.     /* Yes, again a pointer comparison.  */
  1245.     free ((char *) _nl_current_default_domain);
  1246.  
  1247.   /* Remove the search tree with the known translations.  */
  1248.   __tdestroy (root, free);
  1249.   root = NULL;
  1250.  
  1251.   while (transmem_list != NULL)
  1252.     {
  1253.       old = transmem_list;
  1254.       transmem_list = transmem_list->next;
  1255.       free (old);
  1256.     }
  1257. }
  1258. #endif
  1259.