/[cvs]/eggdrop1.9/intl/l10nflist.c
ViewVC logotype

Annotation of /eggdrop1.9/intl/l10nflist.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (hide annotations) (download) (as text)
Fri Mar 7 11:30:34 2003 UTC (17 years, 4 months ago) by tothwolf
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +96 -48 lines
File MIME type: text/x-chdr
* Upgraded gettext to version 0.11.5.

1 tothwolf 1.2 /* Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
2 ite 1.1 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 PARAMS ((char *dest, const char *src));
62     # endif
63     #endif
64    
65 tothwolf 1.2 /* 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 ite 1.1 /* 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 argz_count__ PARAMS ((const char *argz, size_t len));
88    
89     static size_t
90     argz_count__ (argz, len)
91     const char *argz;
92     size_t len;
93     {
94     size_t count = 0;
95     while (len > 0)
96     {
97     size_t part_len = strlen (argz);
98     argz += part_len + 1;
99     len -= part_len + 1;
100     count++;
101     }
102     return count;
103     }
104     # undef __argz_count
105     # define __argz_count(argz, len) argz_count__ (argz, len)
106 tothwolf 1.2 #else
107     # ifdef _LIBC
108     # define __argz_count(argz, len) INTUSE(__argz_count) (argz, len)
109     # endif
110 ite 1.1 #endif /* !_LIBC && !HAVE___ARGZ_COUNT */
111    
112     #if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
113     /* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
114     except the last into the character SEP. */
115     static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep));
116    
117     static void
118     argz_stringify__ (argz, len, sep)
119     char *argz;
120     size_t len;
121     int sep;
122     {
123     while (len > 0)
124     {
125     size_t part_len = strlen (argz);
126     argz += part_len;
127     len -= part_len + 1;
128     if (len > 0)
129     *argz++ = sep;
130     }
131     }
132     # undef __argz_stringify
133     # define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
134 tothwolf 1.2 #else
135     # ifdef _LIBC
136     # define __argz_stringify(argz, len, sep) \
137     INTUSE(__argz_stringify) (argz, len, sep)
138     # endif
139 ite 1.1 #endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */
140    
141     #if !defined _LIBC && !defined HAVE___ARGZ_NEXT
142     static char *argz_next__ PARAMS ((char *argz, size_t argz_len,
143     const char *entry));
144    
145     static char *
146     argz_next__ (argz, argz_len, entry)
147     char *argz;
148     size_t argz_len;
149     const char *entry;
150     {
151     if (entry)
152     {
153     if (entry < argz + argz_len)
154     entry = strchr (entry, '\0') + 1;
155    
156     return entry >= argz + argz_len ? NULL : (char *) entry;
157     }
158     else
159     if (argz_len > 0)
160     return argz;
161     else
162     return 0;
163     }
164     # undef __argz_next
165     # define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
166     #endif /* !_LIBC && !HAVE___ARGZ_NEXT */
167    
168    
169     /* Return number of bits set in X. */
170     static int pop PARAMS ((int x));
171    
172     static inline int
173     pop (x)
174     int x;
175     {
176     /* We assume that no more than 16 bits are used. */
177     x = ((x & ~0x5555) >> 1) + (x & 0x5555);
178     x = ((x & ~0x3333) >> 2) + (x & 0x3333);
179     x = ((x >> 4) + x) & 0x0f0f;
180     x = ((x >> 8) + x) & 0xff;
181    
182     return x;
183     }
184    
185    
186     struct loaded_l10nfile *
187     _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
188     territory, codeset, normalized_codeset, modifier, special,
189     sponsor, revision, filename, do_allocate)
190     struct loaded_l10nfile **l10nfile_list;
191     const char *dirlist;
192     size_t dirlist_len;
193     int mask;
194     const char *language;
195     const char *territory;
196     const char *codeset;
197     const char *normalized_codeset;
198     const char *modifier;
199     const char *special;
200     const char *sponsor;
201     const char *revision;
202     const char *filename;
203     int do_allocate;
204     {
205     char *abs_filename;
206 tothwolf 1.2 struct loaded_l10nfile **lastp;
207 ite 1.1 struct loaded_l10nfile *retval;
208     char *cp;
209 tothwolf 1.2 size_t dirlist_count;
210 ite 1.1 size_t entries;
211     int cnt;
212    
213 tothwolf 1.2 /* If LANGUAGE contains an absolute directory specification, we ignore
214     DIRLIST. */
215     if (IS_ABSOLUTE_PATH (language))
216     dirlist_len = 0;
217    
218 ite 1.1 /* Allocate room for the full file name. */
219     abs_filename = (char *) malloc (dirlist_len
220     + strlen (language)
221     + ((mask & TERRITORY) != 0
222     ? strlen (territory) + 1 : 0)
223     + ((mask & XPG_CODESET) != 0
224     ? strlen (codeset) + 1 : 0)
225     + ((mask & XPG_NORM_CODESET) != 0
226     ? strlen (normalized_codeset) + 1 : 0)
227     + (((mask & XPG_MODIFIER) != 0
228     || (mask & CEN_AUDIENCE) != 0)
229     ? strlen (modifier) + 1 : 0)
230     + ((mask & CEN_SPECIAL) != 0
231     ? strlen (special) + 1 : 0)
232     + (((mask & CEN_SPONSOR) != 0
233     || (mask & CEN_REVISION) != 0)
234     ? (1 + ((mask & CEN_SPONSOR) != 0
235 tothwolf 1.2 ? strlen (sponsor) : 0)
236 ite 1.1 + ((mask & CEN_REVISION) != 0
237     ? strlen (revision) + 1 : 0)) : 0)
238     + 1 + strlen (filename) + 1);
239    
240     if (abs_filename == NULL)
241     return NULL;
242    
243 tothwolf 1.2 /* Construct file name. */
244     cp = abs_filename;
245     if (dirlist_len > 0)
246     {
247     memcpy (cp, dirlist, dirlist_len);
248     __argz_stringify (cp, dirlist_len, PATH_SEPARATOR);
249     cp += dirlist_len;
250     cp[-1] = '/';
251     }
252 ite 1.1
253     cp = stpcpy (cp, language);
254    
255     if ((mask & TERRITORY) != 0)
256     {
257     *cp++ = '_';
258     cp = stpcpy (cp, territory);
259     }
260     if ((mask & XPG_CODESET) != 0)
261     {
262     *cp++ = '.';
263     cp = stpcpy (cp, codeset);
264     }
265     if ((mask & XPG_NORM_CODESET) != 0)
266     {
267     *cp++ = '.';
268     cp = stpcpy (cp, normalized_codeset);
269     }
270     if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
271     {
272     /* This component can be part of both syntaces but has different
273     leading characters. For CEN we use `+', else `@'. */
274     *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
275     cp = stpcpy (cp, modifier);
276     }
277     if ((mask & CEN_SPECIAL) != 0)
278     {
279     *cp++ = '+';
280     cp = stpcpy (cp, special);
281     }
282     if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0)
283     {
284     *cp++ = ',';
285     if ((mask & CEN_SPONSOR) != 0)
286     cp = stpcpy (cp, sponsor);
287     if ((mask & CEN_REVISION) != 0)
288     {
289     *cp++ = '_';
290     cp = stpcpy (cp, revision);
291     }
292     }
293    
294     *cp++ = '/';
295     stpcpy (cp, filename);
296    
297     /* Look in list of already loaded domains whether it is already
298     available. */
299 tothwolf 1.2 lastp = l10nfile_list;
300 ite 1.1 for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
301     if (retval->filename != NULL)
302     {
303     int compare = strcmp (retval->filename, abs_filename);
304     if (compare == 0)
305     /* We found it! */
306     break;
307     if (compare < 0)
308     {
309     /* It's not in the list. */
310     retval = NULL;
311     break;
312     }
313    
314 tothwolf 1.2 lastp = &retval->next;
315 ite 1.1 }
316    
317     if (retval != NULL || do_allocate == 0)
318     {
319     free (abs_filename);
320     return retval;
321     }
322    
323 tothwolf 1.2 dirlist_count = (dirlist_len > 0 ? __argz_count (dirlist, dirlist_len) : 1);
324    
325     /* Allocate a new loaded_l10nfile. */
326     retval =
327     (struct loaded_l10nfile *)
328     malloc (sizeof (*retval)
329     + (((dirlist_count << pop (mask)) + (dirlist_count > 1 ? 1 : 0))
330     * sizeof (struct loaded_l10nfile *)));
331 ite 1.1 if (retval == NULL)
332     return NULL;
333    
334     retval->filename = abs_filename;
335 tothwolf 1.2
336     /* We set retval->data to NULL here; it is filled in later.
337     Setting retval->decided to 1 here means that retval does not
338     correspond to a real file (dirlist_count > 1) or is not worth
339     looking up (if an unnormalized codeset was specified). */
340     retval->decided = (dirlist_count > 1
341 ite 1.1 || ((mask & XPG_CODESET) != 0
342     && (mask & XPG_NORM_CODESET) != 0));
343     retval->data = NULL;
344    
345 tothwolf 1.2 retval->next = *lastp;
346     *lastp = retval;
347 ite 1.1
348     entries = 0;
349 tothwolf 1.2 /* Recurse to fill the inheritance list of RETVAL.
350     If the DIRLIST is a real list (i.e. DIRLIST_COUNT > 1), the RETVAL
351     entry does not correspond to a real file; retval->filename contains
352     colons. In this case we loop across all elements of DIRLIST and
353     across all bit patterns dominated by MASK.
354     If the DIRLIST is a single directory or entirely redundant (i.e.
355     DIRLIST_COUNT == 1), we loop across all bit patterns dominated by
356     MASK, excluding MASK itself.
357     In either case, we loop down from MASK to 0. This has the effect
358     that the extra bits in the locale name are dropped in this order:
359     first the modifier, then the territory, then the codeset, then the
360     normalized_codeset. */
361     for (cnt = dirlist_count > 1 ? mask : mask - 1; cnt >= 0; --cnt)
362 ite 1.1 if ((cnt & ~mask) == 0
363     && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0)
364     && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0))
365     {
366 tothwolf 1.2 if (dirlist_count > 1)
367     {
368     /* Iterate over all elements of the DIRLIST. */
369     char *dir = NULL;
370 ite 1.1
371 tothwolf 1.2 while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
372     != NULL)
373     retval->successor[entries++]
374     = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1,
375     cnt, language, territory, codeset,
376     normalized_codeset, modifier, special,
377     sponsor, revision, filename, 1);
378     }
379     else
380 ite 1.1 retval->successor[entries++]
381 tothwolf 1.2 = _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len,
382     cnt, language, territory, codeset,
383 ite 1.1 normalized_codeset, modifier, special,
384     sponsor, revision, filename, 1);
385     }
386     retval->successor[entries] = NULL;
387    
388     return retval;
389     }
390    
391     /* Normalize codeset name. There is no standard for the codeset
392     names. Normalization allows the user to use any of the common
393     names. The return value is dynamically allocated and has to be
394     freed by the caller. */
395     const char *
396     _nl_normalize_codeset (codeset, name_len)
397     const char *codeset;
398     size_t name_len;
399     {
400     int len = 0;
401     int only_digit = 1;
402     char *retval;
403     char *wp;
404     size_t cnt;
405    
406     for (cnt = 0; cnt < name_len; ++cnt)
407 tothwolf 1.2 if (isalnum ((unsigned char) codeset[cnt]))
408 ite 1.1 {
409     ++len;
410    
411 tothwolf 1.2 if (isalpha ((unsigned char) codeset[cnt]))
412 ite 1.1 only_digit = 0;
413     }
414    
415     retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
416    
417     if (retval != NULL)
418     {
419     if (only_digit)
420     wp = stpcpy (retval, "iso");
421     else
422     wp = retval;
423    
424     for (cnt = 0; cnt < name_len; ++cnt)
425 tothwolf 1.2 if (isalpha ((unsigned char) codeset[cnt]))
426     *wp++ = tolower ((unsigned char) codeset[cnt]);
427     else if (isdigit ((unsigned char) codeset[cnt]))
428 ite 1.1 *wp++ = codeset[cnt];
429    
430     *wp = '\0';
431     }
432    
433     return (const char *) retval;
434     }
435    
436    
437     /* @@ begin of epilog @@ */
438    
439     /* We don't want libintl.a to depend on any other library. So we
440     avoid the non-standard function stpcpy. In GNU C Library this
441     function is available, though. Also allow the symbol HAVE_STPCPY
442     to be defined. */
443     #if !_LIBC && !HAVE_STPCPY
444     static char *
445     stpcpy (dest, src)
446     char *dest;
447     const char *src;
448     {
449     while ((*dest++ = *src++) != '\0')
450     /* Do nothing. */ ;
451     return dest - 1;
452     }
453     #endif

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23