VirtualBox

source: kBuild/trunk/src/sed/intl/l10nflist.c@ 3140

Last change on this file since 3140 was 599, checked in by bird, 18 years ago

GNU sed 4.1.5.

File size: 10.2 KB
Line 
1/* Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
2 Contributed by Ulrich Drepper <[email protected]>, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
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
61static char *stpcpy PARAMS ((char *dest, const char *src));
62# endif
63#endif
64
65/* Define function which are usually not available. */
66
67#if !defined _LIBC && !defined HAVE___ARGZ_COUNT
68/* Returns the number of strings in ARGZ. */
69static size_t argz_count__ PARAMS ((const char *argz, size_t len));
70
71static size_t
72argz_count__ (argz, len)
73 const char *argz;
74 size_t len;
75{
76 size_t count = 0;
77 while (len > 0)
78 {
79 size_t part_len = strlen (argz);
80 argz += part_len + 1;
81 len -= part_len + 1;
82 count++;
83 }
84 return count;
85}
86# undef __argz_count
87# define __argz_count(argz, len) argz_count__ (argz, len)
88#endif /* !_LIBC && !HAVE___ARGZ_COUNT */
89
90#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
91/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
92 except the last into the character SEP. */
93static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep));
94
95static void
96argz_stringify__ (argz, len, sep)
97 char *argz;
98 size_t len;
99 int sep;
100{
101 while (len > 0)
102 {
103 size_t part_len = strlen (argz);
104 argz += part_len;
105 len -= part_len + 1;
106 if (len > 0)
107 *argz++ = sep;
108 }
109}
110# undef __argz_stringify
111# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
112#endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */
113
114#if !defined _LIBC && !defined HAVE___ARGZ_NEXT
115static char *argz_next__ PARAMS ((char *argz, size_t argz_len,
116 const char *entry));
117
118static char *
119argz_next__ (argz, argz_len, entry)
120 char *argz;
121 size_t argz_len;
122 const char *entry;
123{
124 if (entry)
125 {
126 if (entry < argz + argz_len)
127 entry = strchr (entry, '\0') + 1;
128
129 return entry >= argz + argz_len ? NULL : (char *) entry;
130 }
131 else
132 if (argz_len > 0)
133 return argz;
134 else
135 return 0;
136}
137# undef __argz_next
138# define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
139#endif /* !_LIBC && !HAVE___ARGZ_NEXT */
140
141
142/* Return number of bits set in X. */
143static int pop PARAMS ((int x));
144
145static inline int
146pop (x)
147 int x;
148{
149 /* We assume that no more than 16 bits are used. */
150 x = ((x & ~0x5555) >> 1) + (x & 0x5555);
151 x = ((x & ~0x3333) >> 2) + (x & 0x3333);
152 x = ((x >> 4) + x) & 0x0f0f;
153 x = ((x >> 8) + x) & 0xff;
154
155 return x;
156}
157
158
159
160struct loaded_l10nfile *
161_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
162 territory, codeset, normalized_codeset, modifier, special,
163 sponsor, revision, filename, do_allocate)
164 struct loaded_l10nfile **l10nfile_list;
165 const char *dirlist;
166 size_t dirlist_len;
167 int mask;
168 const char *language;
169 const char *territory;
170 const char *codeset;
171 const char *normalized_codeset;
172 const char *modifier;
173 const char *special;
174 const char *sponsor;
175 const char *revision;
176 const char *filename;
177 int do_allocate;
178{
179 char *abs_filename;
180 struct loaded_l10nfile *last = NULL;
181 struct loaded_l10nfile *retval;
182 char *cp;
183 size_t entries;
184 int cnt;
185
186 /* Allocate room for the full file name. */
187 abs_filename = (char *) malloc (dirlist_len
188 + strlen (language)
189 + ((mask & TERRITORY) != 0
190 ? strlen (territory) + 1 : 0)
191 + ((mask & XPG_CODESET) != 0
192 ? strlen (codeset) + 1 : 0)
193 + ((mask & XPG_NORM_CODESET) != 0
194 ? strlen (normalized_codeset) + 1 : 0)
195 + (((mask & XPG_MODIFIER) != 0
196 || (mask & CEN_AUDIENCE) != 0)
197 ? strlen (modifier) + 1 : 0)
198 + ((mask & CEN_SPECIAL) != 0
199 ? strlen (special) + 1 : 0)
200 + (((mask & CEN_SPONSOR) != 0
201 || (mask & CEN_REVISION) != 0)
202 ? (1 + ((mask & CEN_SPONSOR) != 0
203 ? strlen (sponsor) + 1 : 0)
204 + ((mask & CEN_REVISION) != 0
205 ? strlen (revision) + 1 : 0)) : 0)
206 + 1 + strlen (filename) + 1);
207
208 if (abs_filename == NULL)
209 return NULL;
210
211 retval = NULL;
212 last = NULL;
213
214 /* Construct file name. */
215 memcpy (abs_filename, dirlist, dirlist_len);
216 __argz_stringify (abs_filename, dirlist_len, PATH_SEPARATOR);
217 cp = abs_filename + (dirlist_len - 1);
218 *cp++ = '/';
219 cp = stpcpy (cp, language);
220
221 if ((mask & TERRITORY) != 0)
222 {
223 *cp++ = '_';
224 cp = stpcpy (cp, territory);
225 }
226 if ((mask & XPG_CODESET) != 0)
227 {
228 *cp++ = '.';
229 cp = stpcpy (cp, codeset);
230 }
231 if ((mask & XPG_NORM_CODESET) != 0)
232 {
233 *cp++ = '.';
234 cp = stpcpy (cp, normalized_codeset);
235 }
236 if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
237 {
238 /* This component can be part of both syntaces but has different
239 leading characters. For CEN we use `+', else `@'. */
240 *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
241 cp = stpcpy (cp, modifier);
242 }
243 if ((mask & CEN_SPECIAL) != 0)
244 {
245 *cp++ = '+';
246 cp = stpcpy (cp, special);
247 }
248 if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0)
249 {
250 *cp++ = ',';
251 if ((mask & CEN_SPONSOR) != 0)
252 cp = stpcpy (cp, sponsor);
253 if ((mask & CEN_REVISION) != 0)
254 {
255 *cp++ = '_';
256 cp = stpcpy (cp, revision);
257 }
258 }
259
260 *cp++ = '/';
261 stpcpy (cp, filename);
262
263 /* Look in list of already loaded domains whether it is already
264 available. */
265 last = NULL;
266 for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
267 if (retval->filename != NULL)
268 {
269 int compare = strcmp (retval->filename, abs_filename);
270 if (compare == 0)
271 /* We found it! */
272 break;
273 if (compare < 0)
274 {
275 /* It's not in the list. */
276 retval = NULL;
277 break;
278 }
279
280 last = retval;
281 }
282
283 if (retval != NULL || do_allocate == 0)
284 {
285 free (abs_filename);
286 return retval;
287 }
288
289 retval = (struct loaded_l10nfile *)
290 malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len)
291 * (1 << pop (mask))
292 * sizeof (struct loaded_l10nfile *)));
293 if (retval == NULL)
294 return NULL;
295
296 retval->filename = abs_filename;
297 retval->decided = (__argz_count (dirlist, dirlist_len) != 1
298 || ((mask & XPG_CODESET) != 0
299 && (mask & XPG_NORM_CODESET) != 0));
300 retval->data = NULL;
301
302 if (last == NULL)
303 {
304 retval->next = *l10nfile_list;
305 *l10nfile_list = retval;
306 }
307 else
308 {
309 retval->next = last->next;
310 last->next = retval;
311 }
312
313 entries = 0;
314 /* If the DIRLIST is a real list the RETVAL entry corresponds not to
315 a real file. So we have to use the DIRLIST separation mechanism
316 of the inner loop. */
317 cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask;
318 for (; cnt >= 0; --cnt)
319 if ((cnt & ~mask) == 0
320 && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0)
321 && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0))
322 {
323 /* Iterate over all elements of the DIRLIST. */
324 char *dir = NULL;
325
326 while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
327 != NULL)
328 retval->successor[entries++]
329 = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
330 language, territory, codeset,
331 normalized_codeset, modifier, special,
332 sponsor, revision, filename, 1);
333 }
334 retval->successor[entries] = NULL;
335
336 return retval;
337}
338
339
340/* Normalize codeset name. There is no standard for the codeset
341 names. Normalization allows the user to use any of the common
342 names. The return value is dynamically allocated and has to be
343 freed by the caller. */
344const char *
345_nl_normalize_codeset (codeset, name_len)
346 const char *codeset;
347 size_t name_len;
348{
349 int len = 0;
350 int only_digit = 1;
351 char *retval;
352 char *wp;
353 size_t cnt;
354
355 for (cnt = 0; cnt < name_len; ++cnt)
356 if (isalnum ((unsigned char) codeset[cnt]))
357 {
358 ++len;
359
360 if (isalpha ((unsigned char) codeset[cnt]))
361 only_digit = 0;
362 }
363
364 retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
365
366 if (retval != NULL)
367 {
368 if (only_digit)
369 wp = stpcpy (retval, "iso");
370 else
371 wp = retval;
372
373 for (cnt = 0; cnt < name_len; ++cnt)
374 if (isalpha ((unsigned char) codeset[cnt]))
375 *wp++ = tolower ((unsigned char) codeset[cnt]);
376 else if (isdigit ((unsigned char) codeset[cnt]))
377 *wp++ = codeset[cnt];
378
379 *wp = '\0';
380 }
381
382 return (const char *) retval;
383}
384
385
386/* @@ begin of epilog @@ */
387
388/* We don't want libintl.a to depend on any other library. So we
389 avoid the non-standard function stpcpy. In GNU C Library this
390 function is available, though. Also allow the symbol HAVE_STPCPY
391 to be defined. */
392#if !_LIBC && !HAVE_STPCPY
393static char *
394stpcpy (dest, src)
395 char *dest;
396 const char *src;
397{
398 while ((*dest++ = *src++) != '\0')
399 /* Do nothing. */ ;
400 return dest - 1;
401}
402#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette