~ubuntu-branches/ubuntu/saucy/lordsawar/saucy

« back to all changes in this revision

Viewing changes to intl/l10nflist.c

  • Committer: Bazaar Package Importer
  • Author(s): Barry deFreese, Barry deFreese
  • Date: 2008-12-20 13:52:12 UTC
  • mfrom: (1.1.6 upstream) (5.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20081220135212-noeb2w3y98ebo7o9
Tags: 0.1.4-1
[ Barry deFreese ]
* New upstream release.
* Move 0.0.8-2.1 changelog entry to correct point in changelog.
* Make lordsawar-data suggest lordsawar.
* Update my e-mail address.
* Add build-depends on intltool, uuid-dev, and libboost-dev.
* Don't install locales since there are no translations currently.
* Add simple man page for new lordsawar-pbm binary.
* Drop gcc4.3 patches as they have been fixed upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 1995-1999, 2000-2003 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 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17
 
   USA.  */
18
 
 
19
 
/* Tell glibc's <string.h> to provide a prototype for stpcpy().
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 <string.h>
31
 
 
32
 
#if defined _LIBC || defined HAVE_ARGZ_H
33
 
# include <argz.h>
34
 
#endif
35
 
#include <ctype.h>
36
 
#include <sys/types.h>
37
 
#include <stdlib.h>
38
 
 
39
 
#include "loadinfo.h"
40
 
 
41
 
/* On some strange systems still no definition of NULL is found.  Sigh!  */
42
 
#ifndef NULL
43
 
# if defined __STDC__ && __STDC__
44
 
#  define NULL ((void *) 0)
45
 
# else
46
 
#  define NULL 0
47
 
# endif
48
 
#endif
49
 
 
50
 
/* @@ end of prolog @@ */
51
 
 
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 (char *dest, const char *src);
62
 
# endif
63
 
#endif
64
 
 
65
 
/* Pathname support.
66
 
   ISSLASH(C)           tests whether C is a directory separator character.
67
 
   IS_ABSOLUTE_PATH(P)  tests whether P is an absolute path.  If it is not,
68
 
                        it may be concatenated to a directory pathname.
69
 
 */
70
 
#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
71
 
  /* Win32, OS/2, DOS */
72
 
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
73
 
# define HAS_DEVICE(P) \
74
 
    ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
75
 
     && (P)[1] == ':')
76
 
# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
77
 
#else
78
 
  /* Unix */
79
 
# define ISSLASH(C) ((C) == '/')
80
 
# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
81
 
#endif
82
 
 
83
 
/* Define function which are usually not available.  */
84
 
 
85
 
#if !defined _LIBC && !defined HAVE___ARGZ_COUNT
86
 
/* Returns the number of strings in ARGZ.  */
87
 
static size_t
88
 
argz_count__ (const char *argz, size_t len)
89
 
{
90
 
  size_t count = 0;
91
 
  while (len > 0)
92
 
    {
93
 
      size_t part_len = strlen (argz);
94
 
      argz += part_len + 1;
95
 
      len -= part_len + 1;
96
 
      count++;
97
 
    }
98
 
  return count;
99
 
}
100
 
# undef __argz_count
101
 
# define __argz_count(argz, len) argz_count__ (argz, len)
102
 
#else
103
 
# ifdef _LIBC
104
 
#  define __argz_count(argz, len) INTUSE(__argz_count) (argz, len)
105
 
# endif
106
 
#endif  /* !_LIBC && !HAVE___ARGZ_COUNT */
107
 
 
108
 
#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
109
 
/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
110
 
   except the last into the character SEP.  */
111
 
static void
112
 
argz_stringify__ (char *argz, size_t len, int sep)
113
 
{
114
 
  while (len > 0)
115
 
    {
116
 
      size_t part_len = strlen (argz);
117
 
      argz += part_len;
118
 
      len -= part_len + 1;
119
 
      if (len > 0)
120
 
        *argz++ = sep;
121
 
    }
122
 
}
123
 
# undef __argz_stringify
124
 
# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
125
 
#else
126
 
# ifdef _LIBC
127
 
#  define __argz_stringify(argz, len, sep) \
128
 
  INTUSE(__argz_stringify) (argz, len, sep)
129
 
# endif
130
 
#endif  /* !_LIBC && !HAVE___ARGZ_STRINGIFY */
131
 
 
132
 
#if !defined _LIBC && !defined HAVE___ARGZ_NEXT
133
 
static char *
134
 
argz_next__ (char *argz, size_t argz_len, const char *entry)
135
 
{
136
 
  if (entry)
137
 
    {
138
 
      if (entry < argz + argz_len)
139
 
        entry = strchr (entry, '\0') + 1;
140
 
 
141
 
      return entry >= argz + argz_len ? NULL : (char *) entry;
142
 
    }
143
 
  else
144
 
    if (argz_len > 0)
145
 
      return argz;
146
 
    else
147
 
      return 0;
148
 
}
149
 
# undef __argz_next
150
 
# define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
151
 
#endif  /* !_LIBC && !HAVE___ARGZ_NEXT */
152
 
 
153
 
 
154
 
/* Return number of bits set in X.  */
155
 
static inline int
156
 
pop (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 (struct loaded_l10nfile **l10nfile_list,
170
 
                    const char *dirlist, size_t dirlist_len,
171
 
                    int mask, const char *language, const char *territory,
172
 
                    const char *codeset, const char *normalized_codeset,
173
 
                    const char *modifier, const char *special,
174
 
                    const char *sponsor, const char *revision,
175
 
                    const char *filename, int do_allocate)
176
 
{
177
 
  char *abs_filename;
178
 
  struct loaded_l10nfile **lastp;
179
 
  struct loaded_l10nfile *retval;
180
 
  char *cp;
181
 
  size_t dirlist_count;
182
 
  size_t entries;
183
 
  int cnt;
184
 
 
185
 
  /* If LANGUAGE contains an absolute directory specification, we ignore
186
 
     DIRLIST.  */
187
 
  if (IS_ABSOLUTE_PATH (language))
188
 
    dirlist_len = 0;
189
 
 
190
 
  /* Allocate room for the full file name.  */
191
 
  abs_filename = (char *) malloc (dirlist_len
192
 
                                  + strlen (language)
193
 
                                  + ((mask & TERRITORY) != 0
194
 
                                     ? strlen (territory) + 1 : 0)
195
 
                                  + ((mask & XPG_CODESET) != 0
196
 
                                     ? strlen (codeset) + 1 : 0)
197
 
                                  + ((mask & XPG_NORM_CODESET) != 0
198
 
                                     ? strlen (normalized_codeset) + 1 : 0)
199
 
                                  + (((mask & XPG_MODIFIER) != 0
200
 
                                      || (mask & CEN_AUDIENCE) != 0)
201
 
                                     ? strlen (modifier) + 1 : 0)
202
 
                                  + ((mask & CEN_SPECIAL) != 0
203
 
                                     ? strlen (special) + 1 : 0)
204
 
                                  + (((mask & CEN_SPONSOR) != 0
205
 
                                      || (mask & CEN_REVISION) != 0)
206
 
                                     ? (1 + ((mask & CEN_SPONSOR) != 0
207
 
                                             ? strlen (sponsor) : 0)
208
 
                                        + ((mask & CEN_REVISION) != 0
209
 
                                           ? strlen (revision) + 1 : 0)) : 0)
210
 
                                  + 1 + strlen (filename) + 1);
211
 
 
212
 
  if (abs_filename == NULL)
213
 
    return NULL;
214
 
 
215
 
  /* Construct file name.  */
216
 
  cp = abs_filename;
217
 
  if (dirlist_len > 0)
218
 
    {
219
 
      memcpy (cp, dirlist, dirlist_len);
220
 
      __argz_stringify (cp, dirlist_len, PATH_SEPARATOR);
221
 
      cp += dirlist_len;
222
 
      cp[-1] = '/';
223
 
    }
224
 
 
225
 
  cp = stpcpy (cp, language);
226
 
 
227
 
  if ((mask & TERRITORY) != 0)
228
 
    {
229
 
      *cp++ = '_';
230
 
      cp = stpcpy (cp, territory);
231
 
    }
232
 
  if ((mask & XPG_CODESET) != 0)
233
 
    {
234
 
      *cp++ = '.';
235
 
      cp = stpcpy (cp, codeset);
236
 
    }
237
 
  if ((mask & XPG_NORM_CODESET) != 0)
238
 
    {
239
 
      *cp++ = '.';
240
 
      cp = stpcpy (cp, normalized_codeset);
241
 
    }
242
 
  if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
243
 
    {
244
 
      /* This component can be part of both syntaces but has different
245
 
         leading characters.  For CEN we use `+', else `@'.  */
246
 
      *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
247
 
      cp = stpcpy (cp, modifier);
248
 
    }
249
 
  if ((mask & CEN_SPECIAL) != 0)
250
 
    {
251
 
      *cp++ = '+';
252
 
      cp = stpcpy (cp, special);
253
 
    }
254
 
  if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0)
255
 
    {
256
 
      *cp++ = ',';
257
 
      if ((mask & CEN_SPONSOR) != 0)
258
 
        cp = stpcpy (cp, sponsor);
259
 
      if ((mask & CEN_REVISION) != 0)
260
 
        {
261
 
          *cp++ = '_';
262
 
          cp = stpcpy (cp, revision);
263
 
        }
264
 
    }
265
 
 
266
 
  *cp++ = '/';
267
 
  stpcpy (cp, filename);
268
 
 
269
 
  /* Look in list of already loaded domains whether it is already
270
 
     available.  */
271
 
  lastp = l10nfile_list;
272
 
  for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
273
 
    if (retval->filename != NULL)
274
 
      {
275
 
        int compare = strcmp (retval->filename, abs_filename);
276
 
        if (compare == 0)
277
 
          /* We found it!  */
278
 
          break;
279
 
        if (compare < 0)
280
 
          {
281
 
            /* It's not in the list.  */
282
 
            retval = NULL;
283
 
            break;
284
 
          }
285
 
 
286
 
        lastp = &retval->next;
287
 
      }
288
 
 
289
 
  if (retval != NULL || do_allocate == 0)
290
 
    {
291
 
      free (abs_filename);
292
 
      return retval;
293
 
    }
294
 
 
295
 
  dirlist_count = (dirlist_len > 0 ? __argz_count (dirlist, dirlist_len) : 1);
296
 
 
297
 
  /* Allocate a new loaded_l10nfile.  */
298
 
  retval =
299
 
    (struct loaded_l10nfile *)
300
 
    malloc (sizeof (*retval)
301
 
            + (((dirlist_count << pop (mask)) + (dirlist_count > 1 ? 1 : 0))
302
 
               * sizeof (struct loaded_l10nfile *)));
303
 
  if (retval == NULL)
304
 
    return NULL;
305
 
 
306
 
  retval->filename = abs_filename;
307
 
 
308
 
  /* We set retval->data to NULL here; it is filled in later.
309
 
     Setting retval->decided to 1 here means that retval does not
310
 
     correspond to a real file (dirlist_count > 1) or is not worth
311
 
     looking up (if an unnormalized codeset was specified).  */
312
 
  retval->decided = (dirlist_count > 1
313
 
                     || ((mask & XPG_CODESET) != 0
314
 
                         && (mask & XPG_NORM_CODESET) != 0));
315
 
  retval->data = NULL;
316
 
 
317
 
  retval->next = *lastp;
318
 
  *lastp = retval;
319
 
 
320
 
  entries = 0;
321
 
  /* Recurse to fill the inheritance list of RETVAL.
322
 
     If the DIRLIST is a real list (i.e. DIRLIST_COUNT > 1), the RETVAL
323
 
     entry does not correspond to a real file; retval->filename contains
324
 
     colons.  In this case we loop across all elements of DIRLIST and
325
 
     across all bit patterns dominated by MASK.
326
 
     If the DIRLIST is a single directory or entirely redundant (i.e.
327
 
     DIRLIST_COUNT == 1), we loop across all bit patterns dominated by
328
 
     MASK, excluding MASK itself.
329
 
     In either case, we loop down from MASK to 0.  This has the effect
330
 
     that the extra bits in the locale name are dropped in this order:
331
 
     first the modifier, then the territory, then the codeset, then the
332
 
     normalized_codeset.  */
333
 
  for (cnt = dirlist_count > 1 ? mask : mask - 1; cnt >= 0; --cnt)
334
 
    if ((cnt & ~mask) == 0
335
 
        && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0)
336
 
        && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0))
337
 
      {
338
 
        if (dirlist_count > 1)
339
 
          {
340
 
            /* Iterate over all elements of the DIRLIST.  */
341
 
            char *dir = NULL;
342
 
 
343
 
            while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
344
 
                   != NULL)
345
 
              retval->successor[entries++]
346
 
                = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1,
347
 
                                      cnt, language, territory, codeset,
348
 
                                      normalized_codeset, modifier, special,
349
 
                                      sponsor, revision, filename, 1);
350
 
          }
351
 
        else
352
 
          retval->successor[entries++]
353
 
            = _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len,
354
 
                                  cnt, language, territory, codeset,
355
 
                                  normalized_codeset, modifier, special,
356
 
                                  sponsor, revision, filename, 1);
357
 
      }
358
 
  retval->successor[entries] = NULL;
359
 
 
360
 
  return retval;
361
 
}
362
 
 
363
 
/* Normalize codeset name.  There is no standard for the codeset
364
 
   names.  Normalization allows the user to use any of the common
365
 
   names.  The return value is dynamically allocated and has to be
366
 
   freed by the caller.  */
367
 
const char *
368
 
_nl_normalize_codeset (const char *codeset, size_t name_len)
369
 
{
370
 
  int len = 0;
371
 
  int only_digit = 1;
372
 
  char *retval;
373
 
  char *wp;
374
 
  size_t cnt;
375
 
 
376
 
  for (cnt = 0; cnt < name_len; ++cnt)
377
 
    if (isalnum ((unsigned char) codeset[cnt]))
378
 
      {
379
 
        ++len;
380
 
 
381
 
        if (isalpha ((unsigned char) codeset[cnt]))
382
 
          only_digit = 0;
383
 
      }
384
 
 
385
 
  retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
386
 
 
387
 
  if (retval != NULL)
388
 
    {
389
 
      if (only_digit)
390
 
        wp = stpcpy (retval, "iso");
391
 
      else
392
 
        wp = retval;
393
 
 
394
 
      for (cnt = 0; cnt < name_len; ++cnt)
395
 
        if (isalpha ((unsigned char) codeset[cnt]))
396
 
          *wp++ = tolower ((unsigned char) codeset[cnt]);
397
 
        else if (isdigit ((unsigned char) codeset[cnt]))
398
 
          *wp++ = codeset[cnt];
399
 
 
400
 
      *wp = '\0';
401
 
    }
402
 
 
403
 
  return (const char *) retval;
404
 
}
405
 
 
406
 
 
407
 
/* @@ begin of epilog @@ */
408
 
 
409
 
/* We don't want libintl.a to depend on any other library.  So we
410
 
   avoid the non-standard function stpcpy.  In GNU C Library this
411
 
   function is available, though.  Also allow the symbol HAVE_STPCPY
412
 
   to be defined.  */
413
 
#if !_LIBC && !HAVE_STPCPY
414
 
static char *
415
 
stpcpy (char *dest, const char *src)
416
 
{
417
 
  while ((*dest++ = *src++) != '\0')
418
 
    /* Do nothing. */ ;
419
 
  return dest - 1;
420
 
}
421
 
#endif