* sysdeps/i386/fpu/__math.h (logb): Correct contraint from =u to =t.
[glibc.git] / intl / l10nflist.c
blobb0fdf51d73545bfe264a2efd90518f57b8ab1810
1 /* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If
17 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #include <argz.h>
21 #include <ctype.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #include "loadinfo.h"
27 /* Return number of bits set in X. */
28 static int pop __P ((int x));
30 static inline int
31 pop (x)
32 int x;
34 /* We assume that no more than 16 bits are used. */
35 x = ((x & ~0x5555) >> 1) + (x & 0x5555);
36 x = ((x & ~0x3333) >> 2) + (x & 0x3333);
37 x = ((x >> 4) + x) & 0x0f0f;
38 x = ((x >> 8) + x) & 0xff;
40 return x;
44 struct loaded_l10nfile *
45 _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
46 territory, codeset, normalized_codeset, modifier, special,
47 sponsor, revision, filename, do_allocate)
48 struct loaded_l10nfile **l10nfile_list;
49 const char *dirlist;
50 size_t dirlist_len;
51 int mask;
52 const char *language;
53 const char *territory;
54 const char *codeset;
55 const char *normalized_codeset;
56 const char *modifier;
57 const char *special;
58 const char *sponsor;
59 const char *revision;
60 const char *filename;
61 int do_allocate;
63 char *abs_filename;
64 struct loaded_l10nfile *last = NULL;
65 struct loaded_l10nfile *retval;
66 char *cp;
67 size_t entries;
68 int cnt;
70 /* Allocate room for the full file name. */
71 abs_filename = (char *) malloc (dirlist_len
72 + strlen (language)
73 + ((mask & TERRITORY) != 0
74 ? strlen (territory) + 1 : 0)
75 + ((mask & XPG_CODESET) != 0
76 ? strlen (codeset) + 1 : 0)
77 + ((mask & XPG_NORM_CODESET) != 0
78 ? strlen (normalized_codeset) + 1 : 0)
79 + (((mask & XPG_MODIFIER) != 0
80 || (mask & CEN_AUDIENCE) != 0) ?
81 strlen (modifier) + 1 : 0)
82 + ((mask & CEN_SPECIAL) != 0
83 ? strlen (special) + 1 : 0)
84 + ((mask & CEN_SPONSOR) != 0
85 ? strlen (sponsor) + 1 : 0)
86 + ((mask & CEN_REVISION) != 0
87 ? strlen (revision) + 1 : 0)
88 + 1 + strlen (filename) + 1);
90 if (abs_filename == NULL)
91 return NULL;
93 retval = NULL;
94 last = NULL;
96 /* Construct file name. */
97 memcpy (abs_filename, dirlist, dirlist_len);
98 __argz_stringify (abs_filename, dirlist_len, ':');
99 cp = abs_filename + (dirlist_len - 1);
100 *cp++ = '/';
101 cp = stpcpy (cp, language);
103 if ((mask & TERRITORY) != 0)
105 *cp++ = '_';
106 cp = stpcpy (cp, territory);
108 if ((mask & XPG_CODESET) != 0)
110 *cp++ = '.';
111 cp = stpcpy (cp, codeset);
113 if ((mask & XPG_NORM_CODESET) != 0)
115 *cp++ = '.';
116 cp = stpcpy (cp, normalized_codeset);
118 if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
120 /* This component can be part of both syntaces but has different
121 leading characters. For CEN we use `+', else `@'. */
122 *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
123 cp = stpcpy (cp, modifier);
125 if ((mask & CEN_SPECIAL) != 0)
127 *cp++ = '+';
128 cp = stpcpy (cp, special);
130 if ((mask & CEN_SPONSOR) != 0)
132 *cp++ = ',';
133 cp = stpcpy (cp, sponsor);
135 if ((mask & CEN_REVISION) != 0)
137 *cp++ = '_';
138 cp = stpcpy (cp, revision);
141 *cp++ = '/';
142 stpcpy (cp, filename);
144 /* Look in list of already loaded domains whether it is already
145 available. */
146 last = NULL;
147 for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
148 if (retval->filename != NULL)
150 int compare = strcmp (retval->filename, abs_filename);
151 if (compare == 0)
152 /* We found it! */
153 break;
154 if (compare < 0)
156 /* It's not in the list. */
157 retval = NULL;
158 break;
161 last = retval;
164 if (retval != NULL || do_allocate == 0)
166 free (abs_filename);
167 return retval;
170 retval = (struct loaded_l10nfile *)
171 malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len)
172 * (1 << pop (mask))
173 * sizeof (struct loaded_l10nfile *)));
174 if (retval == NULL)
175 return NULL;
177 retval->filename = abs_filename;
178 retval->decided = (__argz_count (dirlist, dirlist_len) != 1
179 || ((mask & XPG_CODESET) != 0
180 && (mask & XPG_NORM_CODESET) != 0));
181 retval->data = NULL;
183 if (last == NULL)
185 retval->next = *l10nfile_list;
186 *l10nfile_list = retval;
188 else
190 retval->next = last->next;
191 last->next = retval;
194 entries = 0;
195 /* If the DIRLIST is a real list the RETVAL entry correcponds not to
196 a real file. So we have to use the DIRLIST separation machanism
197 of the inner loop. */
198 cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask;
199 for (; cnt >= 0; --cnt)
200 if ((cnt & ~mask) == 0
201 && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0)
202 && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0))
204 /* Iterate over all elements of the DIRLIST. */
205 char *dir = NULL;
207 while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
208 != NULL)
209 retval->successor[entries++]
210 = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
211 language, territory, codeset,
212 normalized_codeset, modifier, special,
213 sponsor, revision, filename, 1);
215 retval->successor[entries] = NULL;
217 return retval;
220 /* Normalize codeset name. There is no standard for the codeset
221 names. Normalization allows the user to use any of the common
222 names. */
223 const char *
224 _nl_normalize_codeset (codeset, name_len)
225 const char *codeset;
226 size_t name_len;
228 int len = 0;
229 int only_digit = 1;
230 char *retval;
231 char *wp;
232 size_t cnt;
234 for (cnt = 0; cnt < name_len; ++cnt)
235 if (isalnum (codeset[cnt]))
237 ++len;
239 if (isalpha (codeset[cnt]))
240 only_digit = 0;
243 retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
245 if (retval != NULL)
247 if (only_digit)
248 wp = stpcpy (retval, "ISO");
249 else
250 wp = retval;
252 for (cnt = 0; cnt < name_len; ++cnt)
253 if (isalpha (codeset[cnt]))
254 *wp++ = tolower (codeset[cnt]);
255 else if (isdigit (codeset[cnt]))
256 *wp++ = codeset[cnt];
258 *wp = '\0';
261 return (const char *) retval;