1570af302Sopenharmony_ci#include <locale.h>
2570af302Sopenharmony_ci#include <stdlib.h>
3570af302Sopenharmony_ci#include <string.h>
4570af302Sopenharmony_ci#include "locale_impl.h"
5570af302Sopenharmony_ci#include "libc.h"
6570af302Sopenharmony_ci#include "lock.h"
7570af302Sopenharmony_ci
8570af302Sopenharmony_cistatic char buf[LC_ALL*(LOCALE_NAME_MAX+1)];
9570af302Sopenharmony_ci
10570af302Sopenharmony_ci#ifndef __LITEOS__
11570af302Sopenharmony_cistatic inline int Fresh(struct __locale_map *lm)
12570af302Sopenharmony_ci{
13570af302Sopenharmony_ci	if (lm != NULL) {
14570af302Sopenharmony_ci		return lm->flag;
15570af302Sopenharmony_ci	}
16570af302Sopenharmony_ci	return VALID;
17570af302Sopenharmony_ci}
18570af302Sopenharmony_ci#endif
19570af302Sopenharmony_ci
20570af302Sopenharmony_cichar *setlocale(int cat, const char *name)
21570af302Sopenharmony_ci{
22570af302Sopenharmony_ci	const struct __locale_map *lm;
23570af302Sopenharmony_ci	char flag = VALID;
24570af302Sopenharmony_ci	if ((unsigned)cat > LC_ALL) return 0;
25570af302Sopenharmony_ci
26570af302Sopenharmony_ci	LOCK(__locale_lock);
27570af302Sopenharmony_ci
28570af302Sopenharmony_ci	/* For LC_ALL, setlocale is required to return a string which
29570af302Sopenharmony_ci	 * encodes the current setting for all categories. The format of
30570af302Sopenharmony_ci	 * this string is unspecified, and only the following code, which
31570af302Sopenharmony_ci	 * performs both the serialization and deserialization, depends
32570af302Sopenharmony_ci	 * on the format, so it can easily be changed if needed. */
33570af302Sopenharmony_ci	if (cat == LC_ALL) {
34570af302Sopenharmony_ci		int i;
35570af302Sopenharmony_ci		if (name) {
36570af302Sopenharmony_ci			struct __locale_struct tmp_locale;
37570af302Sopenharmony_ci			char part[LOCALE_NAME_MAX+1] = "C.UTF-8";
38570af302Sopenharmony_ci			const char *p = name;
39570af302Sopenharmony_ci			for (i=0; i<LC_ALL; i++) {
40570af302Sopenharmony_ci				const char *z = __strchrnul(p, ';');
41570af302Sopenharmony_ci				if (z-p <= LOCALE_NAME_MAX) {
42570af302Sopenharmony_ci					memcpy(part, p, z-p);
43570af302Sopenharmony_ci					part[z-p] = 0;
44570af302Sopenharmony_ci					if (*z) p = z+1;
45570af302Sopenharmony_ci				}
46570af302Sopenharmony_ci				lm = __get_locale(i, part);
47570af302Sopenharmony_ci				if (lm == LOC_MAP_FAILED) {
48570af302Sopenharmony_ci					UNLOCK(__locale_lock);
49570af302Sopenharmony_ci					return 0;
50570af302Sopenharmony_ci				}
51570af302Sopenharmony_ci#ifndef __LITEOS__
52570af302Sopenharmony_ci				if(Fresh(lm) == INVALID) {
53570af302Sopenharmony_ci					flag = INVALID;
54570af302Sopenharmony_ci				}
55570af302Sopenharmony_ci#endif
56570af302Sopenharmony_ci				tmp_locale.cat[i] = lm;
57570af302Sopenharmony_ci			}
58570af302Sopenharmony_ci			libc.global_locale = tmp_locale;
59570af302Sopenharmony_ci		}
60570af302Sopenharmony_ci		char *s = buf;
61570af302Sopenharmony_ci		const char *part;
62570af302Sopenharmony_ci		int same = 0;
63570af302Sopenharmony_ci		for (i=0; i<LC_ALL; i++) {
64570af302Sopenharmony_ci			const struct __locale_map *lm =
65570af302Sopenharmony_ci				libc.global_locale.cat[i];
66570af302Sopenharmony_ci			if (lm == libc.global_locale.cat[0]) same++;
67570af302Sopenharmony_ci			part = lm ? lm->name : "C";
68570af302Sopenharmony_ci			size_t l = strlen(part);
69570af302Sopenharmony_ci			memcpy(s, part, l);
70570af302Sopenharmony_ci			s[l] = ';';
71570af302Sopenharmony_ci			s += l+1;
72570af302Sopenharmony_ci		}
73570af302Sopenharmony_ci		*--s = 0;
74570af302Sopenharmony_ci		UNLOCK(__locale_lock);
75570af302Sopenharmony_ci		if (flag == INVALID) {
76570af302Sopenharmony_ci			return 0;
77570af302Sopenharmony_ci		}
78570af302Sopenharmony_ci		return same==LC_ALL ? (char *)part : buf;
79570af302Sopenharmony_ci	}
80570af302Sopenharmony_ci
81570af302Sopenharmony_ci	if (name) {
82570af302Sopenharmony_ci		lm = __get_locale(cat, name);
83570af302Sopenharmony_ci		if (lm == LOC_MAP_FAILED) {
84570af302Sopenharmony_ci			UNLOCK(__locale_lock);
85570af302Sopenharmony_ci			return 0;
86570af302Sopenharmony_ci		}
87570af302Sopenharmony_ci#ifndef __LITEOS__
88570af302Sopenharmony_ci		flag = Fresh(lm);
89570af302Sopenharmony_ci#endif
90570af302Sopenharmony_ci		libc.global_locale.cat[cat] = lm;
91570af302Sopenharmony_ci	} else {
92570af302Sopenharmony_ci		lm = libc.global_locale.cat[cat];
93570af302Sopenharmony_ci	}
94570af302Sopenharmony_ci	char *ret = lm ? (char *)lm->name : "C";
95570af302Sopenharmony_ci
96570af302Sopenharmony_ci	UNLOCK(__locale_lock);
97570af302Sopenharmony_ci	if (flag == INVALID) {
98570af302Sopenharmony_ci		return 0;
99570af302Sopenharmony_ci	}
100570af302Sopenharmony_ci	return ret;
101570af302Sopenharmony_ci}
102