1 /* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library 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.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA. */
24 #include "localeinfo.h"
26 /* For each category declare two external variables (with weak references):
27 extern const struct locale_data *_nl_current_CATEGORY;
28 This points to the current locale's in-core data for CATEGORY.
29 extern const struct locale_data _nl_C_CATEGORY;
30 This contains the built-in "C"/"POSIX" locale's data for CATEGORY.
31 Both are weak references; if &_nl_current_CATEGORY is zero,
32 then nothing is using the locale data. */
33 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
34 extern const struct locale_data *_nl_current_##category; \
35 extern const struct locale_data _nl_C_##category; \
36 weak_symbol (_nl_current_##category) weak_symbol (_nl_C_##category)
37 #include "categories.def"
38 #undef DEFINE_CATEGORY
40 /* Array indexed by category of pointers to _nl_current_CATEGORY slots.
41 Elements are zero for categories whose data is never used. */
42 const struct locale_data * *const _nl_current[] =
44 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
45 [category] = &_nl_current_##category,
46 #include "categories.def"
47 #undef DEFINE_CATEGORY
50 /* Array indexed by category of pointers to _nl_C_CATEGORY slots.
51 Elements are zero for categories whose data is never used. */
52 const struct locale_data *const _nl_C[] =
54 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
55 [category] = &_nl_C_##category,
56 #include "categories.def"
57 #undef DEFINE_CATEGORY
61 /* Define an array of category names (also the environment variable names),
62 indexed by integral category. */
63 const char *const _nl_category_names[] =
65 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
66 [category] = category_name,
67 #include "categories.def"
68 #undef DEFINE_CATEGORY
70 /* An array of their lengths, for convenience. */
71 const size_t _nl_category_name_sizes[] =
73 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
74 [category] = sizeof (category_name) - 1,
75 #include "categories.def"
76 #undef DEFINE_CATEGORY
80 /* Declare the postload functions used below. */
82 #define NO_POSTLOAD _nl_postload_ctype /* Harmless thing known to exist. */
83 #define DEFINE_CATEGORY(category, category_name, items, postload, b, c, d) \
84 extern void postload (void);
85 #include "categories.def"
86 #undef DEFINE_CATEGORY
89 /* Define an array indexed by category of postload functions to call after
90 loading and installing that category's data. */
91 void (*const _nl_category_postload[]) (void) =
93 #define DEFINE_CATEGORY(category, category_name, items, postload, b, c, d) \
94 [category] = postload,
95 #include "categories.def"
96 #undef DEFINE_CATEGORY
100 const char _nl_C_name[] = "C";
102 /* Name of current locale for each individual category.
103 Each is malloc'd unless it is nl_C_name. */
104 const char *_nl_current_names[] =
106 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
108 #include "categories.def"
109 #undef DEFINE_CATEGORY
112 /* Composite LC_ALL name for current locale.
113 This is malloc'd unless it's _nl_C_name. */
114 char *_nl_current_composite_name = (char *) _nl_C_name;
117 /* Switch to the locale called NAME in CATEGORY. Return a string
118 describing the locale. This string can be used as the NAME argument in
119 a later call. If NAME is NULL, don't switch locales, but return the
120 current one. If NAME is "", switch to a locale based on the environment
121 variables, as per POSIX. Return NULL on error. */
124 setlocale (int category, const char *name)
126 /* Return a malloc'd copy of STRING. */
127 char *copy (const char *string)
129 size_t len = strlen (string) + 1;
130 char *new = malloc (len);
131 return new ? memcpy (new, string, len) : NULL;
134 /* Construct a new composite name. */
135 char *new_composite_name (int category, char *newnames[LC_ALL])
137 size_t lens[LC_ALL], cumlen = 0;
142 for (i = 0; i < LC_ALL; ++i)
144 char *name = (category == LC_ALL ? newnames[i] :
145 category == i ? newnames[0] :
146 (char *) _nl_current_names[i]);
147 lens[i] = strlen (name);
148 cumlen += _nl_category_name_sizes[i] + 1 + lens[i] + 1;
149 if (i > 0 && same && strcmp (name, newnames[0]))
155 /* All the categories use the same name. */
156 new = malloc (lens[0] + 1);
159 if (!strcmp (newnames[0], "C") || !strcmp (newnames[0], "POSIX"))
160 return (char *) _nl_C_name;
163 memcpy (new, newnames[0], lens[0] + 1);
167 new = malloc (cumlen);
171 for (i = 0; i < LC_ALL; ++i)
173 /* Add "CATEGORY=NAME;" to the string. */
174 char *name = (category == LC_ALL ? newnames[i] :
175 category == i ? newnames[0] :
176 (char *) _nl_current_names[i]);
177 memcpy (p, _nl_category_names[i], _nl_category_name_sizes[i]);
178 p += _nl_category_name_sizes[i];
180 memcpy (p, name, lens[i]);
184 p[-1] = '\0'; /* Clobber the last ';'. */
187 /* Put COMPOSITE in _nl_current_composite_name and free the old value. */
188 void setcomposite (char *composite)
190 char *old = _nl_current_composite_name;
191 _nl_current_composite_name = composite;
192 if (old != _nl_C_name)
195 /* Put NAME in _nl_current_names and free the old value. */
196 void setname (int category, const char *name)
198 const char *oldname = _nl_current_names[category];
199 _nl_current_names[category] = name;
200 if (oldname != _nl_C_name)
201 free ((char *) oldname);
203 /* Put DATA in *_nl_current[CATEGORY] and free the old value. */
204 void setdata (int category, struct locale_data *data)
206 if (_nl_current[category])
208 const struct locale_data *olddata = *_nl_current[category];
209 *_nl_current[category] = data;
210 if (_nl_category_postload[category])
211 (*_nl_category_postload[category]) ();
212 if (olddata != _nl_C[category])
213 _nl_free_locale ((struct locale_data *) olddata);
217 const char *current_name;
220 if (category < 0 || category > LC_ALL)
226 if (category == LC_ALL)
227 current_name = _nl_current_composite_name;
229 current_name = _nl_current_names[category];
232 /* Return the name of the current locale. */
233 return (char *) current_name;
235 if (name == current_name)
236 /* Changing to the same thing. */
237 return (char *) current_name;
239 if (category == LC_ALL)
241 const size_t len = strlen (name) + 1;
242 char *newnames[LC_ALL];
244 struct locale_data *newdata[LC_ALL];
246 /* Set all name pointers to the argument name. */
247 for (category = 0; category < LC_ALL; ++category)
248 newnames[category] = (char *) name;
250 p = strchr (name, ';');
253 /* This is a composite name. Make a local copy and split it up. */
255 char *n = alloca (len);
256 memcpy (n, name, len);
258 while ((p = strchr (n, '=')) != NULL)
260 for (i = 0; i < LC_ALL; ++i)
261 if (_nl_category_name_sizes[i] == p - n &&
262 !memcmp (_nl_category_names[i], n, p - n))
266 /* Bogus category name. */
272 /* Found the category this clause sets. */
273 char *end = strchr (++p, ';');
277 /* Examine the next clause. */
282 /* This was the last clause. We are done. */
287 for (i = 0; i < LC_ALL; ++i)
288 if (newnames[i] == name)
289 /* The composite name did not specify all categories. */
293 /* Load the new data for each category. */
294 while (category-- > 0)
295 /* Only actually load the data if anything will use it. */
296 if (_nl_current[category])
298 newdata[category] = _nl_load_locale (category,
299 &newnames[category]);
300 if (newdata[category])
301 newnames[category] = copy (newnames[category]);
302 if (! newdata[category] || ! newnames[category])
304 if (!strcmp (newnames[category], "C") ||
305 !strcmp (newnames[category], "POSIX"))
307 /* Loading from a file failed, but this is a request
308 for the default locale. Use the built-in data. */
309 if (! newdata[category])
311 = (struct locale_data *) _nl_C[category];
312 newnames[category] = (char *) _nl_C_name;
316 /* Loading this part of the locale failed.
317 Abort the composite load. */
319 while (++category < LC_ALL)
321 if (_nl_current[category])
322 _nl_free_locale (newdata[category]);
323 if (newnames[category] != _nl_C_name)
324 free (newnames[category]);
332 /* The data is never used; just change the name. */
333 newnames[category] = copy (newnames[category]);
334 if (! newnames[category])
336 if (!strcmp (newnames[category], "C") ||
337 !strcmp (newnames[category], "POSIX"))
338 newnames[category] = (char *) _nl_C_name;
341 while (++category < LC_ALL)
342 if (newnames[category] != _nl_C_name)
343 free (newnames[category]);
348 composite = new_composite_name (LC_ALL, newnames);
352 goto abort_composite;
355 /* Now we have loaded all the new data. Put it in place. */
356 for (category = 0; category < LC_ALL; ++category)
358 setdata (category, newdata[category]);
359 setname (category, newnames[category]);
361 setcomposite (composite);
367 char *newname = copy (name);
370 if (!strcmp (name, "C") || !strcmp (name, "POSIX"))
371 newname = (char *) _nl_C_name;
376 composite = new_composite_name (category, &newname);
379 if (newname != _nl_C_name)
384 /* Only actually load the data if anything will use it. */
385 if (_nl_current[category])
387 struct locale_data *newdata = _nl_load_locale (category,
391 if (!strcmp (name, "C") || !strcmp (name, "POSIX"))
392 newdata = (struct locale_data *) _nl_C[category];
396 setdata (category, newdata);
399 setname (category, newname);
400 setcomposite (composite);