]>
git.saurik.com Git - apple/libc.git/blob - locale/setlocale.c
3ec6fca3e4ddfa024f8802533d1bdefdd43194c5
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Paul Borman at Krystal Technologies.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 static const char rcsid
[] =
39 "$FreeBSD: src/lib/libc/locale/setlocale.c,v 1.25.2.4 2001/03/05 13:08:42 ru Exp $";
42 #if defined(LIBC_SCCS) && !defined(lint)
43 static char sccsid
[] = "@(#)setlocale.c 8.1 (Berkeley) 7/4/93";
44 #endif /* LIBC_SCCS and not lint */
46 #include <sys/types.h>
55 #include "setlocale.h"
58 * Category names for getenv()
60 static char *categories
[_LC_LAST
] = {
71 * Current locales for each category
73 static char current_categories
[_LC_LAST
][ENCODING_LEN
+ 1] = {
84 * The locales we are going to try and load
86 static char new_categories
[_LC_LAST
][ENCODING_LEN
+ 1];
87 static char saved_categories
[_LC_LAST
][ENCODING_LEN
+ 1];
89 static char current_locale_string
[_LC_LAST
* (ENCODING_LEN
+ 1/*"/"*/ + 1)];
91 static char *currentlocale
__P((void));
92 static char *loadlocale
__P((int));
93 static int stub_load_locale
__P((const char *));
95 extern int __time_load_locale
__P((const char *)); /* strftime.c */
98 setlocale(category
, locale
)
105 if (category
< LC_ALL
|| category
>= _LC_LAST
)
109 return (category
!= LC_ALL
?
110 current_categories
[category
] : currentlocale());
113 * Default to the current locale for everything.
115 for (i
= 1; i
< _LC_LAST
; ++i
)
116 (void)strcpy(new_categories
[i
], current_categories
[i
]);
119 * Now go fill up new_categories from the locale argument
122 env
= getenv("LC_ALL");
124 if (category
!= LC_ALL
&& (!env
|| !*env
))
125 env
= getenv(categories
[category
]);
128 env
= getenv("LANG");
130 if (!env
|| !*env
|| strchr(env
, '/'))
133 (void) strncpy(new_categories
[category
], env
, ENCODING_LEN
);
134 new_categories
[category
][ENCODING_LEN
] = '\0';
135 if (category
== LC_ALL
) {
136 for (i
= 1; i
< _LC_LAST
; ++i
) {
137 if (!(env
= getenv(categories
[i
])) || !*env
)
138 env
= new_categories
[LC_ALL
];
139 (void)strncpy(new_categories
[i
], env
, ENCODING_LEN
);
140 new_categories
[i
][ENCODING_LEN
] = '\0';
143 } else if (category
!= LC_ALL
) {
144 (void)strncpy(new_categories
[category
], locale
, ENCODING_LEN
);
145 new_categories
[category
][ENCODING_LEN
] = '\0';
147 if ((r
= strchr(locale
, '/')) == NULL
) {
148 for (i
= 1; i
< _LC_LAST
; ++i
) {
149 (void)strncpy(new_categories
[i
], locale
, ENCODING_LEN
);
150 new_categories
[i
][ENCODING_LEN
] = '\0';
153 for (i
= 1; r
[1] == '/'; ++r
);
155 return (NULL
); /* Hmm, just slashes... */
157 len
= r
- locale
> ENCODING_LEN
? ENCODING_LEN
: r
- locale
;
158 (void)strncpy(new_categories
[i
], locale
, len
);
159 new_categories
[i
][len
] = '\0';
162 while (*locale
== '/')
164 while (*++r
&& *r
!= '/');
166 while (i
< _LC_LAST
) {
167 (void)strcpy(new_categories
[i
],
168 new_categories
[i
-1]);
175 return (loadlocale(category
));
177 for (i
= 1; i
< _LC_LAST
; ++i
) {
178 (void)strcpy(saved_categories
[i
], current_categories
[i
]);
179 if (loadlocale(i
) == NULL
) {
180 for (j
= 1; j
< i
; j
++) {
181 (void)strcpy(new_categories
[j
],
182 saved_categories
[j
]);
183 /* XXX can fail too */
189 return (currentlocale());
197 (void)strcpy(current_locale_string
, current_categories
[1]);
199 for (i
= 2; i
< _LC_LAST
; ++i
)
200 if (strcmp(current_categories
[1], current_categories
[i
])) {
201 for (i
= 2; i
< _LC_LAST
; ++i
) {
202 (void) strcat(current_locale_string
, "/");
203 (void) strcat(current_locale_string
, current_categories
[i
]);
207 return (current_locale_string
);
215 char *new = new_categories
[category
];
216 char *old
= current_categories
[category
];
218 if (_PathLocale
== NULL
) {
219 char *p
= getenv("PATH_LOCALE");
222 #ifndef __NETBSD_SYSCALLS
226 if (strlen(p
) + 1/*"/"*/ + ENCODING_LEN
+
227 1/*"/"*/ + CATEGORY_LEN
>= PATH_MAX
)
229 _PathLocale
= strdup(p
);
230 if (_PathLocale
== NULL
)
233 _PathLocale
= _PATH_LOCALE
;
236 if (strcmp(new, old
) == 0)
239 if (category
== LC_CTYPE
) {
240 ret
= setrunelocale(new) ? NULL
: new;
242 (void)setrunelocale(old
);
244 (void)strcpy(old
, new);
248 if (category
== LC_COLLATE
) {
249 ret
= (__collate_load_tables(new) < 0) ? NULL
: new;
251 (void)__collate_load_tables(old
);
253 (void)strcpy(old
, new);
257 if (category
== LC_TIME
) {
258 ret
= (__time_load_locale(new) < 0) ? NULL
: new;
260 (void)__time_load_locale(old
);
262 (void)strcpy(old
, new);
266 if (category
== LC_MONETARY
||
267 category
== LC_MESSAGES
||
268 category
== LC_NUMERIC
) {
269 ret
= stub_load_locale(new) ? NULL
: new;
271 (void)stub_load_locale(old
);
273 (void)strcpy(old
, new);
282 stub_load_locale(encoding
)
283 const char *encoding
;
291 * The "C" and "POSIX" locale are always here.
293 if (!strcmp(encoding
, "C") || !strcmp(encoding
, "POSIX"))
297 /* Range checking not needed, encoding has fixed size */
298 strcpy(name
, _PathLocale
);
300 strcat(name
, encoding
);
303 * Some day we will actually look at this file.
306 return (stat(name
, &st
) != 0 || !S_ISDIR(st
.st_mode
));