home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lyx-0.13.2.tar.gz / lyx-0.13.2.tar / lyx-0.13.2 / intl / l10nflist.c < prev    next >
C/C++ Source or Header  |  1998-04-23  |  10KB  |  410 lines

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