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