OLD | NEW |
1 #include <locale.h> | 1 #include <locale.h> |
2 #include <string.h> | 2 #include <string.h> |
3 #include "locale_impl.h" | 3 #include "locale_impl.h" |
4 #include "libc.h" | 4 #include "libc.h" |
5 #include "atomic.h" | 5 #include "atomic.h" |
6 | 6 |
7 const char *__lctrans_impl(const char *msg, const struct __locale_map *lm) | 7 const char* __lctrans_impl(const char* msg, const struct __locale_map* lm) { |
8 { | 8 const char* trans = 0; |
9 » const char *trans = 0; | 9 if (lm) |
10 » if (lm) trans = __mo_lookup(lm->map, lm->map_size, msg); | 10 trans = __mo_lookup(lm->map, lm->map_size, msg); |
11 » return trans ? trans : msg; | 11 return trans ? trans : msg; |
12 } | 12 } |
13 | 13 |
14 const unsigned char *__map_file(const char *, size_t *); | 14 const unsigned char* __map_file(const char*, size_t*); |
15 int __munmap(void *, size_t); | 15 int __munmap(void*, size_t); |
16 char *__strchrnul(const char *, int); | 16 char* __strchrnul(const char*, int); |
17 | 17 |
18 static const char envvars[][12] = { | 18 static const char envvars[][12] = { |
19 » "LC_CTYPE", | 19 "LC_CTYPE", "LC_NUMERIC", "LC_TIME", |
20 » "LC_NUMERIC", | 20 "LC_COLLATE", "LC_MONETARY", "LC_MESSAGES", |
21 » "LC_TIME", | |
22 » "LC_COLLATE", | |
23 » "LC_MONETARY", | |
24 » "LC_MESSAGES", | |
25 }; | 21 }; |
26 | 22 |
27 const struct __locale_map *__get_locale(int cat, const char *val) | 23 const struct __locale_map* __get_locale(int cat, const char* val) { |
28 { | 24 static int lock[2]; |
29 » static int lock[2]; | 25 static void* volatile loc_head; |
30 » static void *volatile loc_head; | 26 const struct __locale_map* p; |
31 » const struct __locale_map *p; | 27 struct __locale_map* new = 0; |
32 » struct __locale_map *new = 0; | 28 const char *path = 0, *z; |
33 » const char *path = 0, *z; | 29 char buf[256]; |
34 » char buf[256]; | 30 size_t l, n; |
35 » size_t l, n; | |
36 | 31 |
37 » if (!*val) { | 32 if (!*val) { |
38 » » ((val = getenv("LC_ALL")) && *val) || | 33 ((val = getenv("LC_ALL")) && *val) || |
39 » » ((val = getenv(envvars[cat])) && *val) || | 34 ((val = getenv(envvars[cat])) && *val) || |
40 » » ((val = getenv("LANG")) && *val) || | 35 ((val = getenv("LANG")) && *val) || (val = "C.UTF-8"); |
41 » » (val = "C.UTF-8"); | 36 } |
42 » } | |
43 | 37 |
44 » /* Limit name length and forbid leading dot or any slashes. */ | 38 /* Limit name length and forbid leading dot or any slashes. */ |
45 » for (n=0; n<LOCALE_NAME_MAX && val[n] && val[n]!='/'; n++); | 39 for (n = 0; n < LOCALE_NAME_MAX && val[n] && val[n] != '/'; n++) |
46 » if (val[0]=='.' || val[n]) val = "C.UTF-8"; | 40 ; |
47 » int builtin = (val[0]=='C' && !val[1]) | 41 if (val[0] == '.' || val[n]) |
48 » » || !strcmp(val, "C.UTF-8") | 42 val = "C.UTF-8"; |
49 » » || !strcmp(val, "POSIX"); | 43 int builtin = (val[0] == 'C' && !val[1]) || !strcmp(val, "C.UTF-8") || |
| 44 !strcmp(val, "POSIX"); |
50 | 45 |
51 » if (builtin) { | 46 if (builtin) { |
52 » » if (cat == LC_CTYPE && val[1]=='.') | 47 if (cat == LC_CTYPE && val[1] == '.') |
53 » » » return (void *)&__c_dot_utf8; | 48 return (void*)&__c_dot_utf8; |
54 » » return 0; | 49 return 0; |
55 » } | 50 } |
56 | 51 |
57 » for (p=loc_head; p; p=p->next) | 52 for (p = loc_head; p; p = p->next) |
58 » » if (!strcmp(val, p->name)) return p; | 53 if (!strcmp(val, p->name)) |
| 54 return p; |
59 | 55 |
60 » LOCK(lock); | 56 LOCK(lock); |
61 | 57 |
62 » for (p=loc_head; p; p=p->next) | 58 for (p = loc_head; p; p = p->next) |
63 » » if (!strcmp(val, p->name)) { | 59 if (!strcmp(val, p->name)) { |
64 » » » UNLOCK(lock); | 60 UNLOCK(lock); |
65 » » » return p; | 61 return p; |
66 » » } | 62 } |
67 | 63 |
68 » if (!libc.secure) path = getenv("MUSL_LOCPATH"); | 64 if (!libc.secure) |
69 » /* FIXME: add a default path? */ | 65 path = getenv("MUSL_LOCPATH"); |
| 66 /* FIXME: add a default path? */ |
70 | 67 |
71 » if (path) for (; *path; path=z+!!*z) { | 68 if (path) |
72 » » z = __strchrnul(path, ':'); | 69 for (; *path; path = z + !!*z) { |
73 » » l = z - path - !!*z; | 70 z = __strchrnul(path, ':'); |
74 » » if (l >= sizeof buf - n - 2) continue; | 71 l = z - path - !!*z; |
75 » » memcpy(buf, path, l); | 72 if (l >= sizeof buf - n - 2) |
76 » » buf[l] = '/'; | 73 continue; |
77 » » memcpy(buf+l+1, val, n); | 74 memcpy(buf, path, l); |
78 » » buf[l+1+n] = 0; | 75 buf[l] = '/'; |
79 » » size_t map_size; | 76 memcpy(buf + l + 1, val, n); |
80 » » const void *map = __map_file(buf, &map_size); | 77 buf[l + 1 + n] = 0; |
81 » » if (map) { | 78 size_t map_size; |
82 » » » new = malloc(sizeof *new); | 79 const void* map = __map_file(buf, &map_size); |
83 » » » if (!new) { | 80 if (map) { |
84 » » » » __munmap((void *)map, map_size); | 81 new = malloc(sizeof *new); |
85 » » » » break; | 82 if (!new) { |
86 » » » } | 83 __munmap((void*)map, map_size); |
87 » » » new->map = map; | 84 break; |
88 » » » new->map_size = map_size; | 85 } |
89 » » » memcpy(new->name, val, n); | 86 new->map = map; |
90 » » » new->name[n] = 0; | 87 new->map_size = map_size; |
91 » » » new->next = loc_head; | 88 memcpy(new->name, val, n); |
92 » » » loc_head = new; | 89 new->name[n] = 0; |
93 » » » break; | 90 new->next = loc_head; |
94 » » } | 91 loc_head = new; |
95 » } | 92 break; |
| 93 } |
| 94 } |
96 | 95 |
97 » /* If no locale definition was found, make a locale map | 96 /* If no locale definition was found, make a locale map |
98 » * object anyway to store the name, which is kept for the | 97 * object anyway to store the name, which is kept for the |
99 » * sake of being able to do message translations at the | 98 * sake of being able to do message translations at the |
100 » * application level. */ | 99 * application level. */ |
101 » if (!new && (new = malloc(sizeof *new))) { | 100 if (!new && (new = malloc(sizeof *new))) { |
102 » » new->map = __c_dot_utf8.map; | 101 new->map = __c_dot_utf8.map; |
103 » » new->map_size = __c_dot_utf8.map_size; | 102 new->map_size = __c_dot_utf8.map_size; |
104 » » memcpy(new->name, val, n); | 103 memcpy(new->name, val, n); |
105 » » new->name[n] = 0; | 104 new->name[n] = 0; |
106 » » new->next = loc_head; | 105 new->next = loc_head; |
107 » » loc_head = new; | 106 loc_head = new; |
108 » } | 107 } |
109 | 108 |
110 » /* For LC_CTYPE, never return a null pointer unless the | 109 /* For LC_CTYPE, never return a null pointer unless the |
111 » * requested name was "C" or "POSIX". */ | 110 * requested name was "C" or "POSIX". */ |
112 » if (!new && cat == LC_CTYPE) new = (void *)&__c_dot_utf8; | 111 if (!new&& cat == LC_CTYPE) |
| 112 new = (void*)&__c_dot_utf8; |
113 | 113 |
114 » UNLOCK(lock); | 114 UNLOCK(lock); |
115 » return new; | 115 return new; |
116 } | 116 } |
OLD | NEW |