~ubuntu-branches/ubuntu/gutsy/findutils/gutsy-proposed

« back to all changes in this revision

Viewing changes to intl/l10nflist.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Metzler
  • Date: 2005-07-04 11:37:37 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20050704113737-ll89ui8be35r0pir
Tags: 4.2.22-2
* Remove locatedb on purge. (Closes: #315343)
* revert regex-syntax back to emacs-re. (Closes: #315136) Future versions
  will allow to select this by commandline parameter.

Show diffs side-by-side

added added

removed removed

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