1 /* Copyright (C) 1991, 92, 95, 96, 97, 98, 99 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 not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
22 #include <bits/libc-lock.h>
28 #include "localeinfo.h"
30 /* For each category declare two external variables (with weak references):
31 extern const struct locale_data *_nl_current_CATEGORY;
32 This points to the current locale's in-core data for CATEGORY.
33 extern const struct locale_data _nl_C_CATEGORY;
34 This contains the built-in "C"/"POSIX" locale's data for CATEGORY.
35 Both are weak references; if &_nl_current_CATEGORY is zero,
36 then nothing is using the locale data. */
37 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
38 extern struct locale_data *_nl_current_##category; \
39 extern struct locale_data _nl_C_##category;
40 #include "categories.def"
41 #undef DEFINE_CATEGORY
43 /* Array indexed by category of pointers to _nl_current_CATEGORY slots. */
44 struct locale_data
* *const _nl_current
[] =
46 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
47 [category] = &_nl_current_##category,
48 #include "categories.def"
49 #undef DEFINE_CATEGORY
50 /* We need this additional element to simplify the code. It must
52 [LC_ALL
] = (struct locale_data
**) ~0ul
55 /* Array indexed by category of pointers to _nl_C_CATEGORY slots.
56 Elements are zero for categories whose data is never used. */
57 struct locale_data
*const _nl_C
[] =
59 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
60 [category] = &_nl_C_##category,
61 #include "categories.def"
62 #undef DEFINE_CATEGORY
66 /* Define an array of category names (also the environment variable names),
67 indexed by integral category.
69 We have entries of fixed width (16 for now) do avoid an array of
70 pointers. Update the size of the outer array if new, longer locale
71 names are introduced. */
72 const char _nl_category_names
[][16] =
74 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
75 [category] = category_name,
76 #include "categories.def"
77 #undef DEFINE_CATEGORY
80 /* An array of their lengths, for convenience. */
81 const size_t _nl_category_name_sizes
[] =
83 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
84 [category] = sizeof (category_name) - 1,
85 #include "categories.def"
86 #undef DEFINE_CATEGORY
87 [LC_ALL
] = sizeof ("LC_ALL") - 1
91 /* Declare the postload functions used below. */
93 #define NO_POSTLOAD _nl_postload_ctype /* Harmless thing known to exist. */
94 #define DEFINE_CATEGORY(category, category_name, items, postload, b, c, d) \
95 extern void postload (void);
96 #include "categories.def"
97 #undef DEFINE_CATEGORY
100 /* Define an array indexed by category of postload functions to call after
101 loading and installing that category's data. */
102 static void (*const _nl_category_postload
[]) (void) =
104 #define DEFINE_CATEGORY(category, category_name, items, postload, b, c, d) \
105 [category] = postload,
106 #include "categories.def"
107 #undef DEFINE_CATEGORY
111 /* Name of current locale for each individual category.
112 Each is malloc'd unless it is nl_C_name. */
113 static const char *_nl_current_names
[] =
115 #define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
116 [category] = _nl_C_name,
117 #include "categories.def"
118 #undef DEFINE_CATEGORY
119 [LC_ALL
] = _nl_C_name
/* For LC_ALL. */
123 /* Lock for protecting global data. */
124 __libc_lock_define_initialized (, __libc_setlocale_lock
)
127 /* Use this when we come along an error. */
128 #define ERROR_RETURN \
130 __set_errno (EINVAL); \
135 /* Construct a new composite name. */
137 new_composite_name (int category
, const char *newnames
[LC_ALL
])
145 for (i
= 0; i
< LC_ALL
; ++i
)
147 const char *name
= (category
== LC_ALL
? newnames
[i
] :
148 category
== i
? newnames
[0] :
149 _nl_current_names
[i
]);
150 last_len
= strlen (name
);
151 cumlen
+= _nl_category_name_sizes
[i
] + 1 + last_len
+ 1;
152 if (same
&& strcmp (name
, newnames
[0]) != 0)
158 /* All the categories use the same name. */
159 if (strcmp (newnames
[0], _nl_C_name
) == 0
160 || strcmp (newnames
[0], _nl_POSIX_name
) == 0)
161 return (char *) _nl_C_name
;
163 new = malloc (last_len
+ 1);
165 return new == NULL
? NULL
: memcpy (new, newnames
[0], last_len
+ 1);
168 new = malloc (cumlen
);
172 for (i
= 0; i
< LC_ALL
; ++i
)
174 /* Add "CATEGORY=NAME;" to the string. */
175 const char *name
= (category
== LC_ALL
? newnames
[i
] :
176 category
== i
? newnames
[0] :
177 _nl_current_names
[i
]);
178 p
= __stpcpy (p
, _nl_category_names
[i
]);
180 p
= __stpcpy (p
, name
);
183 p
[-1] = '\0'; /* Clobber the last ';'. */
188 /* Put NAME in _nl_current_names. */
190 setname (int category
, const char *name
)
192 if (_nl_current_names
[category
] == name
)
195 if (category
== LC_ALL
&& _nl_current_names
[category
] != _nl_C_name
)
196 free ((char *) _nl_current_names
[category
]);
198 _nl_current_names
[category
] = name
;
202 /* Put DATA in *_nl_current[CATEGORY]. */
204 setdata (int category
, struct locale_data
*data
)
206 if (_nl_current
[category
] != NULL
)
208 *_nl_current
[category
] = data
;
209 if (_nl_category_postload
[category
])
210 (*_nl_category_postload
[category
]) ();
216 setlocale (int category
, const char *locale
)
219 size_t locale_path_len
;
220 const char *locpath_var
;
223 /* Sanity check for CATEGORY argument. */
224 if (category
< 0 || category
> LC_ALL
)
227 /* Does user want name of current locale? */
229 return (char *) _nl_current_names
[category
];
231 if (strcmp (locale
, _nl_current_names
[category
]) == 0)
232 /* Changing to the same thing. */
233 return (char *) _nl_current_names
[category
];
235 /* We perhaps really have to load some data. So we determine the
236 path in which to look for the data now. The environment variable
237 `LOCPATH' must only be used when the binary has no SUID or SGID
242 locpath_var
= __secure_getenv ("LOCPATH");
243 if (locpath_var
!= NULL
&& locpath_var
[0] != '\0')
244 if (__argz_create_sep (locpath_var
, ':',
245 &locale_path
, &locale_path_len
) != 0)
248 if (__argz_add_sep (&locale_path
, &locale_path_len
, LOCALE_PATH
, ':') != 0)
251 if (category
== LC_ALL
)
253 /* The user wants to set all categories. The desired locales
254 for the individual categories can be selected by using a
255 composite locale name. This is a semi-colon separated list
256 of entries of the form `CATEGORY=VALUE'. */
257 const char *newnames
[LC_ALL
];
258 struct locale_data
*newdata
[LC_ALL
];
260 /* Set all name pointers to the argument name. */
261 for (category
= 0; category
< LC_ALL
; ++category
)
262 newnames
[category
] = (char *) locale
;
264 if (strchr (locale
, ';') != NULL
)
266 /* This is a composite name. Make a copy and split it up. */
267 char *np
= strdupa (locale
);
271 while ((cp
= strchr (np
, '=')) != NULL
)
273 for (cnt
= 0; cnt
< LC_ALL
; ++cnt
)
274 if ((size_t) (cp
- np
) == _nl_category_name_sizes
[cnt
]
275 && memcmp (np
, _nl_category_names
[cnt
], cp
- np
) == 0)
279 /* Bogus category name. */
282 /* Found the category this clause sets. */
283 newnames
[cnt
] = ++cp
;
284 cp
= strchr (cp
, ';');
287 /* Examine the next clause. */
292 /* This was the last clause. We are done. */
296 for (cnt
= 0; cnt
< LC_ALL
; ++cnt
)
297 if (newnames
[cnt
] == locale
)
298 /* The composite name did not specify all categories. */
302 /* Protect global data. */
303 __libc_lock_lock (__libc_setlocale_lock
);
305 /* Load the new data for each category. */
306 while (category
-- > 0)
308 newdata
[category
] = _nl_find_locale (locale_path
, locale_path_len
,
310 &newnames
[category
]);
312 if (newdata
[category
] == NULL
)
315 /* We must not simply free a global locale since we have no
316 control over the usage. So we mark it as un-deletable. */
317 if (newdata
[category
]->usage_count
!= UNDELETABLE
)
318 newdata
[category
]->usage_count
= UNDELETABLE
;
321 /* Create new composite name. */
323 || (composite
= new_composite_name (LC_ALL
, newnames
)) == NULL
)
324 /* Loading this part of the locale failed. Abort the
329 /* Now we have loaded all the new data. Put it in place. */
330 for (category
= 0; category
< LC_ALL
; ++category
)
332 setdata (category
, newdata
[category
]);
333 setname (category
, newnames
[category
]);
335 setname (LC_ALL
, composite
);
338 /* Critical section left. */
339 __libc_lock_unlock (__libc_setlocale_lock
);
341 /* Free the resources (the locale path variable. */
348 struct locale_data
*newdata
= NULL
;
349 const char *newname
[1] = { locale
};
351 /* Protect global data. */
352 __libc_lock_lock (__libc_setlocale_lock
);
354 if (_nl_current
[category
] != NULL
)
356 /* Only actually load the data if anything will use it. */
357 newdata
= _nl_find_locale (locale_path
, locale_path_len
, category
,
362 /* We must not simply free a global locale since we have no
363 control over the usage. So we mark it as un-deletable.
365 Note: do not remove the `if', it's necessary to copy with
366 the builtin locale data. */
367 if (newdata
->usage_count
!= UNDELETABLE
)
368 newdata
->usage_count
= UNDELETABLE
;
371 /* Create new composite name. */
372 composite
= new_composite_name (category
, newname
);
373 if (composite
== NULL
)
375 /* Say that we don't have any data loaded. */
381 if (_nl_current
[category
] != NULL
)
382 setdata (category
, newdata
);
384 setname (category
, newname
[0]);
385 setname (LC_ALL
, composite
);
388 /* Critical section left. */
389 __libc_lock_unlock (__libc_setlocale_lock
);
391 /* Free the resources (the locale path variable. */
394 return (char *) newname
[0];
399 static void __attribute__ ((unused
))
404 for (category
= 0; category
< LC_ALL
; ++category
)
406 struct locale_data
*here
= *_nl_current
[category
];
408 /* If this category is already "C" don't do anything. */
409 if (here
== _nl_C
[category
])
412 /* We have to be prepared that sometime later me still might
413 need the locale information. */
414 setdata (category
, _nl_C
[category
]);
415 setname (category
, _nl_C_name
);
417 _nl_unload_locale (here
);
420 setname (LC_ALL
, _nl_C_name
);
422 text_set_element (__libc_subfreeres
, free_mem
);