Back to Evolution Project page


Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Header Files   Sources   Compound Members   File Members  

l10nflist.c

00001 /* Handle list of needed message catalogs
00002    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
00003    Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 2, or (at your option)
00008    any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software Foundation,
00017    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
00018 
00019 #ifdef HAVE_CONFIG_H
00020 # include <config.h>
00021 #endif
00022 
00023 
00024 #if defined HAVE_STRING_H || defined _LIBC
00025 # ifndef _GNU_SOURCE
00026 #  define _GNU_SOURCE   1
00027 # endif
00028 # include <string.h>
00029 #else
00030 # include <strings.h>
00031 # ifndef memcpy
00032 #  define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
00033 # endif
00034 #endif
00035 #if !HAVE_STRCHR && !defined _LIBC
00036 # ifndef strchr
00037 #  define strchr index
00038 # endif
00039 #endif
00040 
00041 #if defined _LIBC || defined HAVE_ARGZ_H
00042 # include <argz.h>
00043 #endif
00044 #include <ctype.h>
00045 #include <sys/types.h>
00046 
00047 #if defined STDC_HEADERS || defined _LIBC
00048 # include <stdlib.h>
00049 #endif
00050 
00051 #include "loadinfo.h"
00052 
00053 /* On some strange systems still no definition of NULL is found.  Sigh!  */
00054 #ifndef NULL
00055 # if defined __STDC__ && __STDC__
00056 #  define NULL ((void *) 0)
00057 # else
00058 #  define NULL 0
00059 # endif
00060 #endif
00061 
00062 /* @@ end of prolog @@ */
00063 
00064 #ifdef _LIBC
00065 /* Rename the non ANSI C functions.  This is required by the standard
00066    because some ANSI C functions will require linking with this object
00067    file and the name space must not be polluted.  */
00068 # ifndef stpcpy
00069 #  define stpcpy(dest, src) __stpcpy(dest, src)
00070 # endif
00071 #else
00072 # ifndef HAVE_STPCPY
00073 static char *stpcpy PARAMS ((char *dest, const char *src));
00074 # endif
00075 #endif
00076 
00077 /* Define function which are usually not available.  */
00078 
00079 #if !defined _LIBC && !defined HAVE___ARGZ_COUNT
00080 /* Returns the number of strings in ARGZ.  */
00081 static size_t argz_count__ PARAMS ((const char *argz, size_t len));
00082 
00083 static size_t
00084 argz_count__ (argz, len)
00085      const char *argz;
00086      size_t len;
00087 {
00088   size_t count = 0;
00089   while (len > 0)
00090     {
00091       size_t part_len = strlen (argz);
00092       argz += part_len + 1;
00093       len -= part_len + 1;
00094       count++;
00095     }
00096   return count;
00097 }
00098 # undef __argz_count
00099 # define __argz_count(argz, len) argz_count__ (argz, len)
00100 #endif  /* !_LIBC && !HAVE___ARGZ_COUNT */
00101 
00102 #if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
00103 /* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
00104    except the last into the character SEP.  */
00105 static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep));
00106 
00107 static void
00108 argz_stringify__ (argz, len, sep)
00109      char *argz;
00110      size_t len;
00111      int sep;
00112 {
00113   while (len > 0)
00114     {
00115       size_t part_len = strlen (argz);
00116       argz += part_len;
00117       len -= part_len + 1;
00118       if (len > 0)
00119     *argz++ = sep;
00120     }
00121 }
00122 # undef __argz_stringify
00123 # define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
00124 #endif  /* !_LIBC && !HAVE___ARGZ_STRINGIFY */
00125 
00126 #if !defined _LIBC && !defined HAVE___ARGZ_NEXT
00127 static char *argz_next__ PARAMS ((char *argz, size_t argz_len,
00128                   const char *entry));
00129 
00130 static char *
00131 argz_next__ (argz, argz_len, entry)
00132      char *argz;
00133      size_t argz_len;
00134      const char *entry;
00135 {
00136   if (entry)
00137     {
00138       if (entry < argz + argz_len)
00139         entry = strchr (entry, '\0') + 1;
00140 
00141       return entry >= argz + argz_len ? NULL : (char *) entry;
00142     }
00143   else
00144     if (argz_len > 0)
00145       return argz;
00146     else
00147       return 0;
00148 }
00149 # undef __argz_next
00150 # define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
00151 #endif  /* !_LIBC && !HAVE___ARGZ_NEXT */
00152 
00153 
00154 /* Return number of bits set in X.  */
00155 static int pop PARAMS ((int x));
00156 
00157 static inline int
00158 pop (x)
00159      int x;
00160 {
00161   /* We assume that no more than 16 bits are used.  */
00162   x = ((x & ~0x5555) >> 1) + (x & 0x5555);
00163   x = ((x & ~0x3333) >> 2) + (x & 0x3333);
00164   x = ((x >> 4) + x) & 0x0f0f;
00165   x = ((x >> 8) + x) & 0xff;
00166 
00167   return x;
00168 }
00169 
00170 
00171 struct loaded_l10nfile *
00172 _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
00173             territory, codeset, normalized_codeset, modifier, special,
00174             sponsor, revision, filename, do_allocate)
00175      struct loaded_l10nfile **l10nfile_list;
00176      const char *dirlist;
00177      size_t dirlist_len;
00178      int mask;
00179      const char *language;
00180      const char *territory;
00181      const char *codeset;
00182      const char *normalized_codeset;
00183      const char *modifier;
00184      const char *special;
00185      const char *sponsor;
00186      const char *revision;
00187      const char *filename;
00188      int do_allocate;
00189 {
00190   char *abs_filename;
00191   struct loaded_l10nfile *last = NULL;
00192   struct loaded_l10nfile *retval;
00193   char *cp;
00194   size_t entries;
00195   int cnt;
00196 
00197   /* Allocate room for the full file name.  */
00198   abs_filename = (char *) malloc (dirlist_len
00199                   + strlen (language)
00200                   + ((mask & TERRITORY) != 0
00201                      ? strlen (territory) + 1 : 0)
00202                   + ((mask & XPG_CODESET) != 0
00203                      ? strlen (codeset) + 1 : 0)
00204                   + ((mask & XPG_NORM_CODESET) != 0
00205                      ? strlen (normalized_codeset) + 1 : 0)
00206                   + (((mask & XPG_MODIFIER) != 0
00207                       || (mask & CEN_AUDIENCE) != 0)
00208                      ? strlen (modifier) + 1 : 0)
00209                   + ((mask & CEN_SPECIAL) != 0
00210                      ? strlen (special) + 1 : 0)
00211                   + (((mask & CEN_SPONSOR) != 0
00212                       || (mask & CEN_REVISION) != 0)
00213                      ? (1 + ((mask & CEN_SPONSOR) != 0
00214                          ? strlen (sponsor) + 1 : 0)
00215                     + ((mask & CEN_REVISION) != 0
00216                        ? strlen (revision) + 1 : 0)) : 0)
00217                   + 1 + strlen (filename) + 1);
00218 
00219   if (abs_filename == NULL)
00220     return NULL;
00221 
00222   retval = NULL;
00223   last = NULL;
00224 
00225   /* Construct file name.  */
00226   memcpy (abs_filename, dirlist, dirlist_len);
00227   __argz_stringify (abs_filename, dirlist_len, ':');
00228   cp = abs_filename + (dirlist_len - 1);
00229   *cp++ = '/';
00230   cp = stpcpy (cp, language);
00231 
00232   if ((mask & TERRITORY) != 0)
00233     {
00234       *cp++ = '_';
00235       cp = stpcpy (cp, territory);
00236     }
00237   if ((mask & XPG_CODESET) != 0)
00238     {
00239       *cp++ = '.';
00240       cp = stpcpy (cp, codeset);
00241     }
00242   if ((mask & XPG_NORM_CODESET) != 0)
00243     {
00244       *cp++ = '.';
00245       cp = stpcpy (cp, normalized_codeset);
00246     }
00247   if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
00248     {
00249       /* This component can be part of both syntaces but has different
00250      leading characters.  For CEN we use `+', else `@'.  */
00251       *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
00252       cp = stpcpy (cp, modifier);
00253     }
00254   if ((mask & CEN_SPECIAL) != 0)
00255     {
00256       *cp++ = '+';
00257       cp = stpcpy (cp, special);
00258     }
00259   if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0)
00260     {
00261       *cp++ = ',';
00262       if ((mask & CEN_SPONSOR) != 0)
00263     cp = stpcpy (cp, sponsor);
00264       if ((mask & CEN_REVISION) != 0)
00265     {
00266       *cp++ = '_';
00267       cp = stpcpy (cp, revision);
00268     }
00269     }
00270 
00271   *cp++ = '/';
00272   stpcpy (cp, filename);
00273 
00274   /* Look in list of already loaded domains whether it is already
00275      available.  */
00276   last = NULL;
00277   for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
00278     if (retval->filename != NULL)
00279       {
00280     int compare = strcmp (retval->filename, abs_filename);
00281     if (compare == 0)
00282       /* We found it!  */
00283       break;
00284     if (compare < 0)
00285       {
00286         /* It's not in the list.  */
00287         retval = NULL;
00288         break;
00289       }
00290 
00291     last = retval;
00292       }
00293 
00294   if (retval != NULL || do_allocate == 0)
00295     {
00296       free (abs_filename);
00297       return retval;
00298     }
00299 
00300   retval = (struct loaded_l10nfile *)
00301     malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len)
00302                 * (1 << pop (mask))
00303                 * sizeof (struct loaded_l10nfile *)));
00304   if (retval == NULL)
00305     return NULL;
00306 
00307   retval->filename = abs_filename;
00308   retval->decided = (__argz_count (dirlist, dirlist_len) != 1
00309              || ((mask & XPG_CODESET) != 0
00310              && (mask & XPG_NORM_CODESET) != 0));
00311   retval->data = NULL;
00312 
00313   if (last == NULL)
00314     {
00315       retval->next = *l10nfile_list;
00316       *l10nfile_list = retval;
00317     }
00318   else
00319     {
00320       retval->next = last->next;
00321       last->next = retval;
00322     }
00323 
00324   entries = 0;
00325   /* If the DIRLIST is a real list the RETVAL entry corresponds not to
00326      a real file.  So we have to use the DIRLIST separation mechanism
00327      of the inner loop.  */
00328   cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask;
00329   for (; cnt >= 0; --cnt)
00330     if ((cnt & ~mask) == 0
00331     && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0)
00332     && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0))
00333       {
00334     /* Iterate over all elements of the DIRLIST.  */
00335     char *dir = NULL;
00336 
00337     while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
00338            != NULL)
00339       retval->successor[entries++]
00340         = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
00341                   language, territory, codeset,
00342                   normalized_codeset, modifier, special,
00343                   sponsor, revision, filename, 1);
00344       }
00345   retval->successor[entries] = NULL;
00346 
00347   return retval;
00348 }
00349 
00350 /* Normalize codeset name.  There is no standard for the codeset
00351    names.  Normalization allows the user to use any of the common
00352    names.  */
00353 const char *
00354 _nl_normalize_codeset (codeset, name_len)
00355      const char *codeset;
00356      size_t name_len;
00357 {
00358   int len = 0;
00359   int only_digit = 1;
00360   char *retval;
00361   char *wp;
00362   size_t cnt;
00363 
00364   for (cnt = 0; cnt < name_len; ++cnt)
00365     if (isalnum (codeset[cnt]))
00366       {
00367     ++len;
00368 
00369     if (isalpha (codeset[cnt]))
00370       only_digit = 0;
00371       }
00372 
00373   retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
00374 
00375   if (retval != NULL)
00376     {
00377       if (only_digit)
00378     wp = stpcpy (retval, "iso");
00379       else
00380     wp = retval;
00381 
00382       for (cnt = 0; cnt < name_len; ++cnt)
00383     if (isalpha (codeset[cnt]))
00384       *wp++ = tolower (codeset[cnt]);
00385     else if (isdigit (codeset[cnt]))
00386       *wp++ = codeset[cnt];
00387 
00388       *wp = '\0';
00389     }
00390 
00391   return (const char *) retval;
00392 }
00393 
00394 
00395 /* @@ begin of epilog @@ */
00396 
00397 /* We don't want libintl.a to depend on any other library.  So we
00398    avoid the non-standard function stpcpy.  In GNU C Library this
00399    function is available, though.  Also allow the symbol HAVE_STPCPY
00400    to be defined.  */
00401 #if !_LIBC && !HAVE_STPCPY
00402 static char *
00403 stpcpy (dest, src)
00404      char *dest;
00405      const char *src;
00406 {
00407   while ((*dest++ = *src++) != '\0')
00408     /* Do nothing. */ ;
00409   return dest - 1;
00410 }
00411 #endif

Generated at Mon Nov 6 22:47:04 2000 for TheGameofEvolution by doxygen 1.0.0 written by Dimitri van Heesch, © 1997-1999