]>
Commit | Line | Data |
---|---|---|
320054e8 DG |
1 | #include <locale.h> |
2 | #include <stdlib.h> | |
3 | #include <string.h> | |
4 | #include "locale_impl.h" | |
5 | #include "libc.h" | |
6 | #include "lock.h" | |
7 | ||
8 | static char buf[LC_ALL*(LOCALE_NAME_MAX+1)]; | |
9 | ||
10 | char *setlocale(int cat, const char *name) | |
11 | { | |
320054e8 DG |
12 | const struct __locale_map *lm; |
13 | ||
14 | if ((unsigned)cat > LC_ALL) return 0; | |
15 | ||
322bd4ff | 16 | LOCK(__locale_lock); |
320054e8 DG |
17 | |
18 | /* For LC_ALL, setlocale is required to return a string which | |
19 | * encodes the current setting for all categories. The format of | |
20 | * this string is unspecified, and only the following code, which | |
21 | * performs both the serialization and deserialization, depends | |
22 | * on the format, so it can easily be changed if needed. */ | |
23 | if (cat == LC_ALL) { | |
24 | int i; | |
25 | if (name) { | |
26 | struct __locale_struct tmp_locale; | |
27 | char part[LOCALE_NAME_MAX+1] = "C.UTF-8"; | |
28 | const char *p = name; | |
29 | for (i=0; i<LC_ALL; i++) { | |
30 | const char *z = __strchrnul(p, ';'); | |
31 | if (z-p <= LOCALE_NAME_MAX) { | |
32 | memcpy(part, p, z-p); | |
33 | part[z-p] = 0; | |
34 | if (*z) p = z+1; | |
35 | } | |
36 | lm = __get_locale(i, part); | |
37 | if (lm == LOC_MAP_FAILED) { | |
322bd4ff | 38 | UNLOCK(__locale_lock); |
320054e8 DG |
39 | return 0; |
40 | } | |
41 | tmp_locale.cat[i] = lm; | |
42 | } | |
43 | libc.global_locale = tmp_locale; | |
44 | } | |
45 | char *s = buf; | |
46 | const char *part; | |
47 | int same = 0; | |
48 | for (i=0; i<LC_ALL; i++) { | |
49 | const struct __locale_map *lm = | |
50 | libc.global_locale.cat[i]; | |
51 | if (lm == libc.global_locale.cat[0]) same++; | |
52 | part = lm ? lm->name : "C"; | |
53 | size_t l = strlen(part); | |
54 | memcpy(s, part, l); | |
55 | s[l] = ';'; | |
56 | s += l+1; | |
57 | } | |
58 | *--s = 0; | |
322bd4ff | 59 | UNLOCK(__locale_lock); |
320054e8 DG |
60 | return same==LC_ALL ? (char *)part : buf; |
61 | } | |
62 | ||
63 | if (name) { | |
64 | lm = __get_locale(cat, name); | |
65 | if (lm == LOC_MAP_FAILED) { | |
322bd4ff | 66 | UNLOCK(__locale_lock); |
320054e8 DG |
67 | return 0; |
68 | } | |
69 | libc.global_locale.cat[cat] = lm; | |
70 | } else { | |
71 | lm = libc.global_locale.cat[cat]; | |
72 | } | |
73 | char *ret = lm ? (char *)lm->name : "C"; | |
74 | ||
322bd4ff | 75 | UNLOCK(__locale_lock); |
320054e8 DG |
76 | |
77 | return ret; | |
78 | } |