l10nflist.c
上传用户:xxcykj
上传日期:2007-01-04
资源大小:727k
文件大小:10k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. /* Handle list of needed message catalogs
  2.    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
  3.    Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.    You should have received a copy of the GNU General Public License
  13.    along with this program; if not, write to the Free Software Foundation,
  14.    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  15. #ifdef HAVE_CONFIG_H
  16. # include <config.h>
  17. #endif
  18. #if defined HAVE_STRING_H || defined _LIBC
  19. # ifndef _GNU_SOURCE
  20. #  define _GNU_SOURCE 1
  21. # endif
  22. # include <string.h>
  23. #else
  24. # include <strings.h>
  25. # ifndef memcpy
  26. #  define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
  27. # endif
  28. #endif
  29. #if !HAVE_STRCHR && !defined _LIBC
  30. # ifndef strchr
  31. #  define strchr index
  32. # endif
  33. #endif
  34. #if defined _LIBC || defined HAVE_ARGZ_H
  35. # include <argz.h>
  36. #endif
  37. #include <ctype.h>
  38. #include <sys/types.h>
  39. #if defined STDC_HEADERS || defined _LIBC
  40. # include <stdlib.h>
  41. #endif
  42. #include "loadinfo.h"
  43. /* On some strange systems still no definition of NULL is found.  Sigh!  */
  44. #ifndef NULL
  45. # if defined __STDC__ && __STDC__
  46. #  define NULL ((void *) 0)
  47. # else
  48. #  define NULL 0
  49. # endif
  50. #endif
  51. /* @@ end of prolog @@ */
  52. #ifdef _LIBC
  53. /* Rename the non ANSI C functions.  This is required by the standard
  54.    because some ANSI C functions will require linking with this object
  55.    file and the name space must not be polluted.  */
  56. # ifndef stpcpy
  57. #  define stpcpy(dest, src) __stpcpy(dest, src)
  58. # endif
  59. #else
  60. # ifndef HAVE_STPCPY
  61. static char *stpcpy PARAMS ((char *dest, const char *src));
  62. # endif
  63. #endif
  64. /* Define function which are usually not available.  */
  65. #if !defined _LIBC && !defined HAVE___ARGZ_COUNT
  66. /* Returns the number of strings in ARGZ.  */
  67. static size_t argz_count__ PARAMS ((const char *argz, size_t len));
  68. static size_t
  69. argz_count__ (argz, len)
  70.      const char *argz;
  71.      size_t len;
  72. {
  73.   size_t count = 0;
  74.   while (len > 0)
  75.     {
  76.       size_t part_len = strlen (argz);
  77.       argz += part_len + 1;
  78.       len -= part_len + 1;
  79.       count++;
  80.     }
  81.   return count;
  82. }
  83. # undef __argz_count
  84. # define __argz_count(argz, len) argz_count__ (argz, len)
  85. #endif /* !_LIBC && !HAVE___ARGZ_COUNT */
  86. #if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
  87. /* Make '' separated arg vector ARGZ printable by converting all the ''s
  88.    except the last into the character SEP.  */
  89. static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep));
  90. static void
  91. argz_stringify__ (argz, len, sep)
  92.      char *argz;
  93.      size_t len;
  94.      int sep;
  95. {
  96.   while (len > 0)
  97.     {
  98.       size_t part_len = strlen (argz);
  99.       argz += part_len;
  100.       len -= part_len + 1;
  101.       if (len > 0)
  102. *argz++ = sep;
  103.     }
  104. }
  105. # undef __argz_stringify
  106. # define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
  107. #endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */
  108. #if !defined _LIBC && !defined HAVE___ARGZ_NEXT
  109. static char *argz_next__ PARAMS ((char *argz, size_t argz_len,
  110.   const char *entry));
  111. static char *
  112. argz_next__ (argz, argz_len, entry)
  113.      char *argz;
  114.      size_t argz_len;
  115.      const char *entry;
  116. {
  117.   if (entry)
  118.     {
  119.       if (entry < argz + argz_len)
  120.         entry = strchr (entry, '') + 1;
  121.       return entry >= argz + argz_len ? NULL : (char *) entry;
  122.     }
  123.   else
  124.     if (argz_len > 0)
  125.       return argz;
  126.     else
  127.       return 0;
  128. }
  129. # undef __argz_next
  130. # define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
  131. #endif /* !_LIBC && !HAVE___ARGZ_NEXT */
  132. /* Return number of bits set in X.  */
  133. static int pop PARAMS ((int x));
  134. static inline int
  135. pop (x)
  136.      int x;
  137. {
  138.   /* We assume that no more than 16 bits are used.  */
  139.   x = ((x & ~0x5555) >> 1) + (x & 0x5555);
  140.   x = ((x & ~0x3333) >> 2) + (x & 0x3333);
  141.   x = ((x >> 4) + x) & 0x0f0f;
  142.   x = ((x >> 8) + x) & 0xff;
  143.   return x;
  144. }
  145. struct loaded_l10nfile *
  146. _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
  147.     territory, codeset, normalized_codeset, modifier, special,
  148.     sponsor, revision, filename, do_allocate)
  149.      struct loaded_l10nfile **l10nfile_list;
  150.      const char *dirlist;
  151.      size_t dirlist_len;
  152.      int mask;
  153.      const char *language;
  154.      const char *territory;
  155.      const char *codeset;
  156.      const char *normalized_codeset;
  157.      const char *modifier;
  158.      const char *special;
  159.      const char *sponsor;
  160.      const char *revision;
  161.      const char *filename;
  162.      int do_allocate;
  163. {
  164.   char *abs_filename;
  165.   struct loaded_l10nfile *last = NULL;
  166.   struct loaded_l10nfile *retval;
  167.   char *cp;
  168.   size_t entries;
  169.   int cnt;
  170.   /* Allocate room for the full file name.  */
  171.   abs_filename = (char *) malloc (dirlist_len
  172.   + strlen (language)
  173.   + ((mask & TERRITORY) != 0
  174.      ? strlen (territory) + 1 : 0)
  175.   + ((mask & XPG_CODESET) != 0
  176.      ? strlen (codeset) + 1 : 0)
  177.   + ((mask & XPG_NORM_CODESET) != 0
  178.      ? strlen (normalized_codeset) + 1 : 0)
  179.   + (((mask & XPG_MODIFIER) != 0
  180.       || (mask & CEN_AUDIENCE) != 0)
  181.      ? strlen (modifier) + 1 : 0)
  182.   + ((mask & CEN_SPECIAL) != 0
  183.      ? strlen (special) + 1 : 0)
  184.   + (((mask & CEN_SPONSOR) != 0
  185.       || (mask & CEN_REVISION) != 0)
  186.      ? (1 + ((mask & CEN_SPONSOR) != 0
  187.      ? strlen (sponsor) + 1 : 0)
  188. + ((mask & CEN_REVISION) != 0
  189.    ? strlen (revision) + 1 : 0)) : 0)
  190.   + 1 + strlen (filename) + 1);
  191.   if (abs_filename == NULL)
  192.     return NULL;
  193.   retval = NULL;
  194.   last = NULL;
  195.   /* Construct file name.  */
  196.   memcpy (abs_filename, dirlist, dirlist_len);
  197.   __argz_stringify (abs_filename, dirlist_len, ':');
  198.   cp = abs_filename + (dirlist_len - 1);
  199.   *cp++ = '/';
  200.   cp = stpcpy (cp, language);
  201.   if ((mask & TERRITORY) != 0)
  202.     {
  203.       *cp++ = '_';
  204.       cp = stpcpy (cp, territory);
  205.     }
  206.   if ((mask & XPG_CODESET) != 0)
  207.     {
  208.       *cp++ = '.';
  209.       cp = stpcpy (cp, codeset);
  210.     }
  211.   if ((mask & XPG_NORM_CODESET) != 0)
  212.     {
  213.       *cp++ = '.';
  214.       cp = stpcpy (cp, normalized_codeset);
  215.     }
  216.   if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
  217.     {
  218.       /* This component can be part of both syntaces but has different
  219.  leading characters.  For CEN we use `+', else `@'.  */
  220.       *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
  221.       cp = stpcpy (cp, modifier);
  222.     }
  223.   if ((mask & CEN_SPECIAL) != 0)
  224.     {
  225.       *cp++ = '+';
  226.       cp = stpcpy (cp, special);
  227.     }
  228.   if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0)
  229.     {
  230.       *cp++ = ',';
  231.       if ((mask & CEN_SPONSOR) != 0)
  232. cp = stpcpy (cp, sponsor);
  233.       if ((mask & CEN_REVISION) != 0)
  234. {
  235.   *cp++ = '_';
  236.   cp = stpcpy (cp, revision);
  237. }
  238.     }
  239.   *cp++ = '/';
  240.   stpcpy (cp, filename);
  241.   /* Look in list of already loaded domains whether it is already
  242.      available.  */
  243.   last = NULL;
  244.   for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
  245.     if (retval->filename != NULL)
  246.       {
  247. int compare = strcmp (retval->filename, abs_filename);
  248. if (compare == 0)
  249.   /* We found it!  */
  250.   break;
  251. if (compare < 0)
  252.   {
  253.     /* It's not in the list.  */
  254.     retval = NULL;
  255.     break;
  256.   }
  257. last = retval;
  258.       }
  259.   if (retval != NULL || do_allocate == 0)
  260.     {
  261.       free (abs_filename);
  262.       return retval;
  263.     }
  264.   retval = (struct loaded_l10nfile *)
  265.     malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len)
  266. * (1 << pop (mask))
  267. * sizeof (struct loaded_l10nfile *)));
  268.   if (retval == NULL)
  269.     return NULL;
  270.   retval->filename = abs_filename;
  271.   retval->decided = (__argz_count (dirlist, dirlist_len) != 1
  272.      || ((mask & XPG_CODESET) != 0
  273.  && (mask & XPG_NORM_CODESET) != 0));
  274.   retval->data = NULL;
  275.   if (last == NULL)
  276.     {
  277.       retval->next = *l10nfile_list;
  278.       *l10nfile_list = retval;
  279.     }
  280.   else
  281.     {
  282.       retval->next = last->next;
  283.       last->next = retval;
  284.     }
  285.   entries = 0;
  286.   /* If the DIRLIST is a real list the RETVAL entry corresponds not to
  287.      a real file.  So we have to use the DIRLIST separation mechanism
  288.      of the inner loop.  */
  289.   cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask;
  290.   for (; cnt >= 0; --cnt)
  291.     if ((cnt & ~mask) == 0
  292. && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0)
  293. && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0))
  294.       {
  295. /* Iterate over all elements of the DIRLIST.  */
  296. char *dir = NULL;
  297. while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
  298.        != NULL)
  299.   retval->successor[entries++]
  300.     = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
  301.   language, territory, codeset,
  302.   normalized_codeset, modifier, special,
  303.   sponsor, revision, filename, 1);
  304.       }
  305.   retval->successor[entries] = NULL;
  306.   return retval;
  307. }
  308. /* Normalize codeset name.  There is no standard for the codeset
  309.    names.  Normalization allows the user to use any of the common
  310.    names.  */
  311. const char *
  312. _nl_normalize_codeset (codeset, name_len)
  313.      const unsigned char *codeset;
  314.      size_t name_len;
  315. {
  316.   int len = 0;
  317.   int only_digit = 1;
  318.   char *retval;
  319.   char *wp;
  320.   size_t cnt;
  321.   for (cnt = 0; cnt < name_len; ++cnt)
  322.     if (isalnum (codeset[cnt]))
  323.       {
  324. ++len;
  325. if (isalpha (codeset[cnt]))
  326.   only_digit = 0;
  327.       }
  328.   retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
  329.   if (retval != NULL)
  330.     {
  331.       if (only_digit)
  332. wp = stpcpy (retval, "iso");
  333.       else
  334. wp = retval;
  335.       for (cnt = 0; cnt < name_len; ++cnt)
  336. if (isalpha (codeset[cnt]))
  337.   *wp++ = tolower (codeset[cnt]);
  338. else if (isdigit (codeset[cnt]))
  339.   *wp++ = codeset[cnt];
  340.       *wp = '';
  341.     }
  342.   return (const char *) retval;
  343. }
  344. /* @@ begin of epilog @@ */
  345. /* We don't want libintl.a to depend on any other library.  So we
  346.    avoid the non-standard function stpcpy.  In GNU C Library this
  347.    function is available, though.  Also allow the symbol HAVE_STPCPY
  348.    to be defined.  */
  349. #if !_LIBC && !HAVE_STPCPY
  350. static char *
  351. stpcpy (dest, src)
  352.      char *dest;
  353.      const char *src;
  354. {
  355.   while ((*dest++ = *src++) != '')
  356.     /* Do nothing. */ ;
  357.   return dest - 1;
  358. }
  359. #endif