60
60
# ifndef HAVE_STPCPY
61
static char *stpcpy PARAMS ((char *dest, const char *src));
61
static char *stpcpy (char *dest, const char *src);
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.
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')) \
76
# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
79
# define ISSLASH(C) ((C) == '/')
80
# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
65
83
/* Define function which are usually not available. */
67
85
#if !defined _LIBC && !defined HAVE___ARGZ_COUNT
68
86
/* Returns the number of strings in ARGZ. */
69
static size_t argz_count__ PARAMS ((const char *argz, size_t len));
72
argz_count__ (argz, len)
88
argz_count__ (const char *argz, size_t len)
86
100
# undef __argz_count
87
101
# define __argz_count(argz, len) argz_count__ (argz, len)
104
# define __argz_count(argz, len) INTUSE(__argz_count) (argz, len)
88
106
#endif /* !_LIBC && !HAVE___ARGZ_COUNT */
90
108
#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
91
109
/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
92
110
except the last into the character SEP. */
93
static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep));
96
argz_stringify__ (argz, len, sep)
112
argz_stringify__ (char *argz, size_t len, int sep)
110
123
# undef __argz_stringify
111
124
# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
127
# define __argz_stringify(argz, len, sep) \
128
INTUSE(__argz_stringify) (argz, len, sep)
112
130
#endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */
114
132
#if !defined _LIBC && !defined HAVE___ARGZ_NEXT
115
static char *argz_next__ PARAMS ((char *argz, size_t argz_len,
119
argz_next__ (argz, argz_len, entry)
134
argz_next__ (char *argz, size_t argz_len, const char *entry)
159
168
struct loaded_l10nfile *
160
_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
161
territory, codeset, normalized_codeset, modifier, special,
162
sponsor, revision, filename, do_allocate)
163
struct loaded_l10nfile **l10nfile_list;
167
const char *language;
168
const char *territory;
170
const char *normalized_codeset;
171
const char *modifier;
174
const char *revision;
175
const char *filename;
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)
178
177
char *abs_filename;
179
struct loaded_l10nfile *last = NULL;
178
struct loaded_l10nfile **lastp;
180
179
struct loaded_l10nfile *retval;
181
size_t dirlist_count;
185
/* If LANGUAGE contains an absolute directory specification, we ignore
187
if (IS_ABSOLUTE_PATH (language))
185
190
/* Allocate room for the full file name. */
186
191
abs_filename = (char *) malloc (dirlist_len
187
192
+ strlen (language)
207
212
if (abs_filename == NULL)
213
215
/* Construct file name. */
214
memcpy (abs_filename, dirlist, dirlist_len);
215
__argz_stringify (abs_filename, dirlist_len, PATH_SEPARATOR);
216
cp = abs_filename + (dirlist_len - 1);
219
memcpy (cp, dirlist, dirlist_len);
220
__argz_stringify (cp, dirlist_len, PATH_SEPARATOR);
218
225
cp = stpcpy (cp, language);
220
227
if ((mask & TERRITORY) != 0)
288
retval = (struct loaded_l10nfile *)
289
malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len)
291
* sizeof (struct loaded_l10nfile *)));
295
dirlist_count = (dirlist_len > 0 ? __argz_count (dirlist, dirlist_len) : 1);
297
/* Allocate a new loaded_l10nfile. */
299
(struct loaded_l10nfile *)
300
malloc (sizeof (*retval)
301
+ (((dirlist_count << pop (mask)) + (dirlist_count > 1 ? 1 : 0))
302
* sizeof (struct loaded_l10nfile *)));
292
303
if (retval == NULL)
295
306
retval->filename = abs_filename;
296
retval->decided = (__argz_count (dirlist, dirlist_len) != 1
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
297
313
|| ((mask & XPG_CODESET) != 0
298
314
&& (mask & XPG_NORM_CODESET) != 0));
299
315
retval->data = NULL;
303
retval->next = *l10nfile_list;
304
*l10nfile_list = retval;
308
retval->next = last->next;
317
retval->next = *lastp;
313
/* If the DIRLIST is a real list the RETVAL entry corresponds not to
314
a real file. So we have to use the DIRLIST separation mechanism
315
of the inner loop. */
316
cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask;
317
for (; cnt >= 0; --cnt)
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)
318
334
if ((cnt & ~mask) == 0
319
335
&& ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0)
320
336
&& ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0))
322
/* Iterate over all elements of the DIRLIST. */
338
if (dirlist_count > 1)
340
/* Iterate over all elements of the DIRLIST. */
325
while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
343
while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
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);
327
352
retval->successor[entries++]
328
= _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
329
language, territory, codeset,
353
= _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len,
354
cnt, language, territory, codeset,
330
355
normalized_codeset, modifier, special,
331
356
sponsor, revision, filename, 1);