]> git.saurik.com Git - apple/libc.git/blame - locale.subproj/setlocale.c
Libc-166.tar.gz
[apple/libc.git] / locale.subproj / setlocale.c
CommitLineData
e9ce8d39
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * Copyright (c) 1991, 1993
24 * The Regents of the University of California. All rights reserved.
25 *
26 * This code is derived from software contributed to Berkeley by
27 * Paul Borman at Krystal Technologies.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 */
57
58
59#include <limits.h>
60#include <locale.h>
61#include <rune.h>
62#include <stdlib.h>
63#include <string.h>
64
65/*
66 * Category names for getenv()
67 */
68static char *categories[_LC_LAST] = {
69 "LC_ALL",
70 "LC_COLLATE",
71 "LC_CTYPE",
72 "LC_MONETARY",
73 "LC_NUMERIC",
74 "LC_TIME",
75};
76
77/*
78 * Current locales for each category
79 */
80static char current_categories[_LC_LAST][32] = {
81 "C",
82 "C",
83 "C",
84 "C",
85 "C",
86 "C",
87};
88
89/*
90 * The locales we are going to try and load
91 */
92static char new_categories[_LC_LAST][32];
93
94static char current_locale_string[_LC_LAST * 33];
95static char *PathLocale;
96
97static char *currentlocale __P((void));
98static char *loadlocale __P((int));
99
100char *
101setlocale(category, locale)
102 int category;
103 const char *locale;
104{
105 int found, i, len;
106 char *env, *r;
107
108 if (!PathLocale && !(PathLocale = getenv("PATH_LOCALE")))
109 PathLocale = _PATH_LOCALE;
110
111 if (category < 0 || category >= _LC_LAST)
112 return (NULL);
113
114 if (!locale)
115 return (category ?
116 current_categories[category] : currentlocale());
117
118 /*
119 * Default to the current locale for everything.
120 */
121 for (i = 1; i < _LC_LAST; ++i)
122 (void)strcpy(new_categories[i], current_categories[i]);
123
124 /*
125 * Now go fill up new_categories from the locale argument
126 */
127 if (!*locale) {
128 env = getenv(categories[category]);
129
130 if (!env)
131 env = getenv(categories[0]);
132
133 if (!env)
134 env = getenv("LANG");
135
136 if (!env)
137 env = "C";
138
139 (void) strncpy(new_categories[category], env, 31);
140 new_categories[category][31] = 0;
141 if (!category) {
142 for (i = 1; i < _LC_LAST; ++i) {
143 if (!(env = getenv(categories[i])))
144 env = new_categories[0];
145 (void)strncpy(new_categories[i], env, 31);
146 new_categories[i][31] = 0;
147 }
148 }
149 } else if (category) {
150 (void)strncpy(new_categories[category], locale, 31);
151 new_categories[category][31] = 0;
152 } else {
153 if ((r = strchr(locale, '/')) == 0) {
154 for (i = 1; i < _LC_LAST; ++i) {
155 (void)strncpy(new_categories[i], locale, 31);
156 new_categories[i][31] = 0;
157 }
158 } else {
159 for (i = 1; r[1] == '/'; ++r);
160 if (!r[1])
161 return (NULL); /* Hmm, just slashes... */
162 do {
163 len = r - locale > 31 ? 31 : r - locale;
164 (void)strncpy(new_categories[i++], locale, len);
165 new_categories[i++][len] = 0;
166 locale = r;
167 while (*locale == '/')
168 ++locale;
169 while (*++r && *r != '/');
170 } while (*locale);
171 while (i < _LC_LAST)
172 (void)strcpy(new_categories[i],
173 new_categories[i-1]);
174 }
175 }
176
177 if (category)
178 return (loadlocale(category));
179
180 found = 0;
181 for (i = 1; i < _LC_LAST; ++i)
182 if (loadlocale(i) != NULL)
183 found = 1;
184 if (found)
185 return (currentlocale());
186 return (NULL);
187}
188
189static char *
190currentlocale()
191{
192 int i;
193
194 (void)strcpy(current_locale_string, current_categories[1]);
195
196 for (i = 2; i < _LC_LAST; ++i)
197 if (strcmp(current_categories[1], current_categories[i])) {
198 (void)snprintf(current_locale_string,
199 sizeof(current_locale_string), "%s/%s/%s/%s/%s",
200 current_categories[1], current_categories[2],
201 current_categories[3], current_categories[4],
202 current_categories[5]);
203 break;
204 }
205 return (current_locale_string);
206}
207
208static char *
209loadlocale(category)
210 int category;
211{
212 char name[PATH_MAX];
213
214 if (strcmp(new_categories[category],
215 current_categories[category]) == 0)
216 return (current_categories[category]);
217
218 if (category == LC_CTYPE) {
219 if (setrunelocale(new_categories[LC_CTYPE]))
220 return (NULL);
221 (void)strcpy(current_categories[LC_CTYPE],
222 new_categories[LC_CTYPE]);
223 return (current_categories[LC_CTYPE]);
224 }
225
226 if (!strcmp(new_categories[category], "C") ||
227 !strcmp(new_categories[category], "POSIX")) {
228
229 /*
230 * Some day this will need to reset the locale to the default
231 * C locale. Since we have no way to change them as of yet,
232 * there is no need to reset them.
233 */
234 (void)strcpy(current_categories[category],
235 new_categories[category]);
236 return (current_categories[category]);
237 }
238
239 /*
240 * Some day we will actually look at this file.
241 */
242 (void)snprintf(name, sizeof(name), "%s/%s/%s",
243 PathLocale, new_categories[category], categories[category]);
244
245 switch (category) {
246 case LC_COLLATE:
247 case LC_MONETARY:
248 case LC_NUMERIC:
249 case LC_TIME:
250 return (NULL);
251 }
252}