setlocale.c 2.0 KB
Newer Older
R
Rich Felker 已提交
1
#include <locale.h>
R
Rich Felker 已提交
2 3 4 5 6
#include <stdlib.h>
#include <string.h>
#include "locale_impl.h"
#include "libc.h"
#include "atomic.h"
R
Rich Felker 已提交
7

R
Rich Felker 已提交
8 9 10
static char buf[2+4*(LOCALE_NAME_MAX+1)];

char *setlocale(int cat, const char *name)
R
Rich Felker 已提交
11
{
12 13 14
	struct __locale_map *lm;
	int i, j;

R
Rich Felker 已提交
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
	if (!libc.global_locale.messages_name) {
		libc.global_locale.messages_name =
			buf + 2 + 3*(LOCALE_NAME_MAX+1);
	}

	if ((unsigned)cat > LC_ALL) return 0;

	/* For LC_ALL, setlocale is required to return a string which
	 * encodes the current setting for all categories. The format of
	 * this string is unspecified, and only the following code, which
	 * performs both the serialization and deserialization, depends
	 * on the format, so it can easily be changed if needed. */
	if (cat == LC_ALL) {
		if (name) {
			char part[LOCALE_NAME_MAX+1];
			if (name[0] && name[1]==';'
			    && strlen(name) > 2 + 3*(LOCALE_NAME_MAX+1)) {
				part[0] = name[0];
				part[1] = 0;
				setlocale(LC_CTYPE, part);
				part[LOCALE_NAME_MAX] = 0;
				for (i=LC_TIME; i<LC_MESSAGES; i++) {
					memcpy(part, name + 2 + (i-2)*(LOCALE_NAME_MAX+1), LOCALE_NAME_MAX);
					for (j=LOCALE_NAME_MAX-1; j && part[j]==';'; j--)
						part[j] = 0;
					setlocale(i, part);
				}
				setlocale(LC_MESSAGES, name + 2 + 3*(LOCALE_NAME_MAX+1));
			} else {
				for (i=0; i<LC_ALL; i++)
					setlocale(i, name);
			}
		}
		memset(buf, ';', 2 + 3*(LOCALE_NAME_MAX+1));
		buf[0] = libc.global_locale.ctype_utf8 ? 'U' : 'C';
50 51 52 53 54
		for (i=LC_TIME; i<LC_MESSAGES; i++) {
			lm = libc.global_locale.cat[i-2];
			if (lm) memcpy(buf + 2 + (i-2)*(LOCALE_NAME_MAX+1),
				lm->name, strlen(lm->name));
		}
R
Rich Felker 已提交
55 56 57
		return buf;
	}

58
	if (name) __setlocalecat(&libc.global_locale, cat, name);
R
Rich Felker 已提交
59 60 61 62

	switch (cat) {
	case LC_CTYPE:
		return libc.global_locale.ctype_utf8 ? "C.UTF-8" : "C";
63 64
	case LC_NUMERIC:
		return "C";
R
Rich Felker 已提交
65 66 67 68
	case LC_MESSAGES:
		return libc.global_locale.messages_name[0]
			? libc.global_locale.messages_name : "C";
	default:
69 70
		lm = libc.global_locale.cat[cat-2];
		return lm ? lm->name : "C";
R
Rich Felker 已提交
71
	}
R
Rich Felker 已提交
72
}