sl@0
|
1 |
/************************************************************************
|
sl@0
|
2 |
*
|
sl@0
|
3 |
* localedef.cpp - definitions of locale helpers
|
sl@0
|
4 |
*
|
sl@0
|
5 |
* $Id: localedef.cpp 290022 2005-09-18 23:59:35Z sebor $
|
sl@0
|
6 |
*
|
sl@0
|
7 |
************************************************************************
|
sl@0
|
8 |
*
|
sl@0
|
9 |
* Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave
|
sl@0
|
10 |
* Software division. Licensed under the Apache License, Version 2.0 (the
|
sl@0
|
11 |
* "License"); you may not use this file except in compliance with the
|
sl@0
|
12 |
* License. You may obtain a copy of the License at
|
sl@0
|
13 |
* http://www.apache.org/licenses/LICENSE-2.0. Unless required by
|
sl@0
|
14 |
* applicable law or agreed to in writing, software distributed under
|
sl@0
|
15 |
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
sl@0
|
16 |
* CONDITIONS OF ANY KIND, either express or implied. See the License
|
sl@0
|
17 |
* for the specific language governing permissions and limitations under
|
sl@0
|
18 |
* the License.
|
sl@0
|
19 |
*
|
sl@0
|
20 |
**************************************************************************/
|
sl@0
|
21 |
|
sl@0
|
22 |
// expand _TEST_EXPORT macros
|
sl@0
|
23 |
#define _RWSTD_TEST_SRC
|
sl@0
|
24 |
|
sl@0
|
25 |
#include <localedef.h>
|
sl@0
|
26 |
|
sl@0
|
27 |
#include <environ.h> // for rw_putenv()
|
sl@0
|
28 |
#include <file.h> // for SHELL_RM_RF, rw_tmpnam
|
sl@0
|
29 |
#include <system.h> // for rw_system()
|
sl@0
|
30 |
|
sl@0
|
31 |
|
sl@0
|
32 |
#if defined __linux__
|
sl@0
|
33 |
// on Linux define _XOPEN_SOURCE to get CODESET defined in <langinfo.h>
|
sl@0
|
34 |
# define _XOPEN_SOURCE 500 /* Single Unix conformance */
|
sl@0
|
35 |
// bring __int32_t into scope (otherwise <wctype.h> fails to compile)
|
sl@0
|
36 |
# include <sys/types.h>
|
sl@0
|
37 |
#endif // __linux__
|
sl@0
|
38 |
|
sl@0
|
39 |
#include <fcntl.h>
|
sl@0
|
40 |
#include <sys/stat.h> // for stat
|
sl@0
|
41 |
|
sl@0
|
42 |
#if (!defined (_WIN32) && !defined (_WIN64)) || defined (__SYMBIAN32__)
|
sl@0
|
43 |
# include <unistd.h>
|
sl@0
|
44 |
# include <sys/wait.h> // for WIFEXITED(), WIFSIGNALED(), WTERMSIG()
|
sl@0
|
45 |
#else
|
sl@0
|
46 |
# include <io.h>
|
sl@0
|
47 |
# include <crtdbg.h> // for _malloc_dbg()
|
sl@0
|
48 |
#endif
|
sl@0
|
49 |
|
sl@0
|
50 |
#include <ios> // for ios::*
|
sl@0
|
51 |
#include <limits> // for numeric_limits
|
sl@0
|
52 |
#include <locale> // for money_base::pattern
|
sl@0
|
53 |
|
sl@0
|
54 |
#include <assert.h> // for assert
|
sl@0
|
55 |
#include <errno.h> // for EBADF
|
sl@0
|
56 |
#include <float.h> // for {FLT,DBL,LDBL}_DIG
|
sl@0
|
57 |
#include <limits.h> // for CHAR_BIT, PATH_MAX
|
sl@0
|
58 |
#include <locale.h> // for LC_XXX macros, setlocale
|
sl@0
|
59 |
#include <stdarg.h> // for va_copy, va_list, ...
|
sl@0
|
60 |
#include <stdio.h> // for fgets, remove, sprintf, ...
|
sl@0
|
61 |
#include <stdlib.h> // for getenv, free, malloc, realloc
|
sl@0
|
62 |
#include <string.h> // for strcat, strcpy, strlen, ...
|
sl@0
|
63 |
#include <ctype.h>
|
sl@0
|
64 |
#include <wchar.h> // for wcslen, ...
|
sl@0
|
65 |
|
sl@0
|
66 |
#ifndef PATH_MAX
|
sl@0
|
67 |
# define PATH_MAX 1024
|
sl@0
|
68 |
#endif
|
sl@0
|
69 |
|
sl@0
|
70 |
#ifndef _MSC_VER
|
sl@0
|
71 |
# include <clocale>
|
sl@0
|
72 |
# ifndef LC_MESSAGES
|
sl@0
|
73 |
# define LC_MESSAGES _RWSTD_LC_MESSAGES
|
sl@0
|
74 |
# endif // LC_MESSAGES
|
sl@0
|
75 |
# include <langinfo.h>
|
sl@0
|
76 |
# define EXE_SUFFIX ""
|
sl@0
|
77 |
#else // if MSVC
|
sl@0
|
78 |
# define EXE_SUFFIX ".exe"
|
sl@0
|
79 |
#endif // _MSC_VER
|
sl@0
|
80 |
|
sl@0
|
81 |
|
sl@0
|
82 |
#define TOPDIR "TOPDIR" /* the TOPDIR environment variable */
|
sl@0
|
83 |
#define BINDIR "BINDIR" /* the BINDIR environment variable */
|
sl@0
|
84 |
|
sl@0
|
85 |
|
sl@0
|
86 |
#if _RWSTD_PATH_SEP == '/'
|
sl@0
|
87 |
# define SLASH "/"
|
sl@0
|
88 |
# define IS_ABSOLUTE_PATHNAME(path) (_RWSTD_PATH_SEP == *(path))
|
sl@0
|
89 |
#else
|
sl@0
|
90 |
# define SLASH "\\"
|
sl@0
|
91 |
# define IS_ABSOLUTE_PATHNAME(path) \
|
sl@0
|
92 |
( ( 'A' <= *(path) && 'Z' >= *(path) \
|
sl@0
|
93 |
|| 'a' <= *(path) && 'z' >= *(path)) \
|
sl@0
|
94 |
&& ':' == (path)[1] \
|
sl@0
|
95 |
&& _RWSTD_PATH_SEP == (path)[2])
|
sl@0
|
96 |
#endif
|
sl@0
|
97 |
|
sl@0
|
98 |
// relative paths to the etc/nls directory and its subdirectories
|
sl@0
|
99 |
#if defined (_RWSTD_USE_CONFIG)
|
sl@0
|
100 |
# define RELPATH "etc" SLASH "nls"
|
sl@0
|
101 |
# define TESTS_ETC_PATH "tests" SLASH "etc"
|
sl@0
|
102 |
#else
|
sl@0
|
103 |
# define RELPATH "etc" SLASH "stdlib" SLASH "nls"
|
sl@0
|
104 |
# define TESTS_ETC_PATH "tests" SLASH "stdlib" SLASH "etc"
|
sl@0
|
105 |
#endif // _RWSTD_USE_CONFIG
|
sl@0
|
106 |
|
sl@0
|
107 |
/**************************************************************************/
|
sl@0
|
108 |
|
sl@0
|
109 |
_TEST_EXPORT int
|
sl@0
|
110 |
rw_locale (const char *args, const char *fname)
|
sl@0
|
111 |
{
|
sl@0
|
112 |
// use BINDIR to determine the location of the locale command
|
sl@0
|
113 |
const char* bindir = getenv ("BINDIR");
|
sl@0
|
114 |
if (!bindir)
|
sl@0
|
115 |
bindir = ".." SLASH "bin";
|
sl@0
|
116 |
|
sl@0
|
117 |
int ret;
|
sl@0
|
118 |
|
sl@0
|
119 |
if (fname)
|
sl@0
|
120 |
ret = rw_system ("%s%slocale%s %s",
|
sl@0
|
121 |
bindir, SLASH, EXE_SUFFIX, args);
|
sl@0
|
122 |
else
|
sl@0
|
123 |
ret = rw_system ("%s%slocale%s %s >%s",
|
sl@0
|
124 |
bindir, SLASH, EXE_SUFFIX, args, fname);
|
sl@0
|
125 |
|
sl@0
|
126 |
return ret;
|
sl@0
|
127 |
}
|
sl@0
|
128 |
|
sl@0
|
129 |
/**************************************************************************/
|
sl@0
|
130 |
|
sl@0
|
131 |
_TEST_EXPORT const char*
|
sl@0
|
132 |
rw_localedef (const char *args,
|
sl@0
|
133 |
const char* src, const char *charmap, const char *locname)
|
sl@0
|
134 |
{
|
sl@0
|
135 |
assert (src && charmap);
|
sl@0
|
136 |
|
sl@0
|
137 |
// create a fully qualified pathname of the locale database
|
sl@0
|
138 |
// when (locname == 0), the pathname is computed by appending
|
sl@0
|
139 |
// the name of the character map file `charmap' to the name
|
sl@0
|
140 |
// of the locale definition file `src'
|
sl@0
|
141 |
// otherwise, when `locname' is not a pathname, the pathname
|
sl@0
|
142 |
// of the locale database is formed by appending `locname'
|
sl@0
|
143 |
// to the name of the locale root directory
|
sl@0
|
144 |
static char locale_path [PATH_MAX];
|
sl@0
|
145 |
|
sl@0
|
146 |
const char* locale_root = getenv (LOCALE_ROOT_ENVAR);
|
sl@0
|
147 |
if (!locale_root)
|
sl@0
|
148 |
locale_root = ".";
|
sl@0
|
149 |
|
sl@0
|
150 |
assert ( strlen (locale_root)
|
sl@0
|
151 |
+ strlen (src)
|
sl@0
|
152 |
+ strlen (charmap)
|
sl@0
|
153 |
+ 2 < sizeof locale_path);
|
sl@0
|
154 |
|
sl@0
|
155 |
strcpy (locale_path, locale_root);
|
sl@0
|
156 |
|
sl@0
|
157 |
if (locname) {
|
sl@0
|
158 |
if (strchr (locname, _RWSTD_PATH_SEP))
|
sl@0
|
159 |
strcpy (locale_path, locname);
|
sl@0
|
160 |
else {
|
sl@0
|
161 |
strcat (locale_path, SLASH);
|
sl@0
|
162 |
strcat (locale_path, locname);
|
sl@0
|
163 |
}
|
sl@0
|
164 |
}
|
sl@0
|
165 |
else {
|
sl@0
|
166 |
// compute the locale pathname from `src', `charmap',
|
sl@0
|
167 |
// and `locale_root'
|
sl@0
|
168 |
strcpy (locale_path, locale_root);
|
sl@0
|
169 |
strcat (locale_path, SLASH);
|
sl@0
|
170 |
|
sl@0
|
171 |
const char *slash = strrchr (src, _RWSTD_PATH_SEP);
|
sl@0
|
172 |
slash = slash ? slash + 1 : src;
|
sl@0
|
173 |
|
sl@0
|
174 |
strcat (locale_path, src);
|
sl@0
|
175 |
strcat (locale_path, ".");
|
sl@0
|
176 |
|
sl@0
|
177 |
slash = strrchr (charmap, _RWSTD_PATH_SEP);
|
sl@0
|
178 |
slash = slash ? slash + 1 : charmap;
|
sl@0
|
179 |
|
sl@0
|
180 |
strcat (locale_path, slash);
|
sl@0
|
181 |
}
|
sl@0
|
182 |
|
sl@0
|
183 |
// check to see if the locale database already exists and
|
sl@0
|
184 |
// if so, return immediately the locale filename to the caller
|
sl@0
|
185 |
#if !defined (_MSC_VER)
|
sl@0
|
186 |
struct stat sb;
|
sl@0
|
187 |
if (!stat (locale_path, &sb)) {
|
sl@0
|
188 |
#else
|
sl@0
|
189 |
struct _stat sb;
|
sl@0
|
190 |
if (!_stat (locale_path, &sb)) {
|
sl@0
|
191 |
#endif
|
sl@0
|
192 |
return strrchr (locale_path, _RWSTD_PATH_SEP) + 1;
|
sl@0
|
193 |
}
|
sl@0
|
194 |
|
sl@0
|
195 |
// otherwise, try to create the locale database
|
sl@0
|
196 |
|
sl@0
|
197 |
// use TOPDIR to determine the root of the source tree
|
sl@0
|
198 |
const char* const topdir = getenv (TOPDIR);
|
sl@0
|
199 |
if (!topdir || !*topdir) {
|
sl@0
|
200 |
fprintf (stderr, "%s:%d: the environment variable %s is %s\n",
|
sl@0
|
201 |
__FILE__, __LINE__, TOPDIR, topdir ? "empty" : "undefined");
|
sl@0
|
202 |
return 0;
|
sl@0
|
203 |
}
|
sl@0
|
204 |
|
sl@0
|
205 |
// use BINDIR to determine the location of the localedef command
|
sl@0
|
206 |
const char* bindir = getenv ("BINDIR");
|
sl@0
|
207 |
if (!bindir)
|
sl@0
|
208 |
bindir = ".." SLASH "bin";
|
sl@0
|
209 |
|
sl@0
|
210 |
// if `src' is relative pathname (or a filename) construct the fully
|
sl@0
|
211 |
// qualified absolute pathname to the locale definition file from it
|
sl@0
|
212 |
char src_path [PATH_MAX];
|
sl@0
|
213 |
|
sl@0
|
214 |
if (!IS_ABSOLUTE_PATHNAME (src)) {
|
sl@0
|
215 |
strcpy (src_path, topdir);
|
sl@0
|
216 |
strcat (src_path, SLASH RELPATH SLASH "src" SLASH);
|
sl@0
|
217 |
strcat (src_path, src);
|
sl@0
|
218 |
|
sl@0
|
219 |
// if the file doesn't exist, see if there is a file
|
sl@0
|
220 |
// with that name in the locale root directory (e.g.,
|
sl@0
|
221 |
// a temporary file)
|
sl@0
|
222 |
FILE* const file_exists = fopen (src_path, "r");
|
sl@0
|
223 |
if (file_exists)
|
sl@0
|
224 |
fclose (file_exists);
|
sl@0
|
225 |
else {
|
sl@0
|
226 |
strcpy (src_path, locale_root);
|
sl@0
|
227 |
strcat (src_path, SLASH);
|
sl@0
|
228 |
strcat (src_path, src);
|
sl@0
|
229 |
}
|
sl@0
|
230 |
|
sl@0
|
231 |
src = src_path;
|
sl@0
|
232 |
}
|
sl@0
|
233 |
|
sl@0
|
234 |
char charmap_path [PATH_MAX];
|
sl@0
|
235 |
if (!IS_ABSOLUTE_PATHNAME (charmap)) {
|
sl@0
|
236 |
strcpy (charmap_path, topdir);
|
sl@0
|
237 |
strcat (charmap_path, SLASH RELPATH SLASH "charmaps" SLASH);
|
sl@0
|
238 |
strcat (charmap_path, charmap);
|
sl@0
|
239 |
|
sl@0
|
240 |
// if the file doesn't exist, see if there is a file
|
sl@0
|
241 |
// with that name in the locale root directory (e.g.,
|
sl@0
|
242 |
// a temporary file)
|
sl@0
|
243 |
FILE* const file_exists = fopen (charmap_path, "r");
|
sl@0
|
244 |
if (file_exists)
|
sl@0
|
245 |
fclose (file_exists);
|
sl@0
|
246 |
else {
|
sl@0
|
247 |
strcpy (charmap_path, locale_root);
|
sl@0
|
248 |
strcat (charmap_path, SLASH);
|
sl@0
|
249 |
strcat (charmap_path, charmap);
|
sl@0
|
250 |
}
|
sl@0
|
251 |
|
sl@0
|
252 |
charmap = charmap_path;
|
sl@0
|
253 |
}
|
sl@0
|
254 |
|
sl@0
|
255 |
if (!args)
|
sl@0
|
256 |
args = "";
|
sl@0
|
257 |
|
sl@0
|
258 |
const int ret = rw_system ("%s%slocaledef%s %s -c -f %s -i %s %s",
|
sl@0
|
259 |
bindir, SLASH, EXE_SUFFIX, args,
|
sl@0
|
260 |
charmap, src, locale_path);
|
sl@0
|
261 |
|
sl@0
|
262 |
// return the unqualified locale file name on success or 0 on failure
|
sl@0
|
263 |
return ret ? (char*)0 : strrchr (locale_path, _RWSTD_PATH_SEP) + 1;
|
sl@0
|
264 |
}
|
sl@0
|
265 |
|
sl@0
|
266 |
/**************************************************************************/
|
sl@0
|
267 |
|
sl@0
|
268 |
extern "C" {
|
sl@0
|
269 |
|
sl@0
|
270 |
static char rw_locale_root [256];
|
sl@0
|
271 |
|
sl@0
|
272 |
static void atexit_rm_locale_root ()
|
sl@0
|
273 |
{
|
sl@0
|
274 |
// remove temporary locale databases created by the test
|
sl@0
|
275 |
rw_system (SHELL_RM_RF "%s", rw_locale_root);
|
sl@0
|
276 |
}
|
sl@0
|
277 |
|
sl@0
|
278 |
}
|
sl@0
|
279 |
|
sl@0
|
280 |
_TEST_EXPORT const char*
|
sl@0
|
281 |
rw_set_locale_root ()
|
sl@0
|
282 |
{
|
sl@0
|
283 |
// set any additional environment variables defined in
|
sl@0
|
284 |
// the RW_PUTENV environment variable (if it exists)
|
sl@0
|
285 |
rw_putenv (0);
|
sl@0
|
286 |
|
sl@0
|
287 |
// create a temporary directory for files created by the test
|
sl@0
|
288 |
const char* const locale_root = rw_tmpnam (rw_locale_root);
|
sl@0
|
289 |
if (!locale_root)
|
sl@0
|
290 |
return 0;
|
sl@0
|
291 |
|
sl@0
|
292 |
char envvar [sizeof LOCALE_ROOT_ENVAR + sizeof rw_locale_root] =
|
sl@0
|
293 |
LOCALE_ROOT_ENVAR "=";
|
sl@0
|
294 |
#ifndef __SYMBIAN32__
|
sl@0
|
295 |
std::strcat (envvar, locale_root);
|
sl@0
|
296 |
#else
|
sl@0
|
297 |
strcat (envvar, locale_root);
|
sl@0
|
298 |
#endif
|
sl@0
|
299 |
// remove temporary file if mkstemp() rw_tmpnam() called mkstemp()
|
sl@0
|
300 |
if (rw_system (SHELL_RM_RF " %s", locale_root)) {
|
sl@0
|
301 |
|
sl@0
|
302 |
#if defined (_WIN32) || defined (_WIN64)
|
sl@0
|
303 |
// ignore errors on WIN32 where the stupid DEL command
|
sl@0
|
304 |
// fails even with /Q /S when the files don't exist
|
sl@0
|
305 |
#else
|
sl@0
|
306 |
// assume a sane implementation of SHELL_RM_RF
|
sl@0
|
307 |
return 0;
|
sl@0
|
308 |
#endif // _WIN{32,64}
|
sl@0
|
309 |
}
|
sl@0
|
310 |
|
sl@0
|
311 |
if (rw_system ("mkdir %s", locale_root))
|
sl@0
|
312 |
return 0;
|
sl@0
|
313 |
|
sl@0
|
314 |
// set the "RWSTD_LOCALE_ROOT" environment variable
|
sl@0
|
315 |
// where std::locale looks for locale database files
|
sl@0
|
316 |
rw_putenv (envvar);
|
sl@0
|
317 |
|
sl@0
|
318 |
if (atexit (atexit_rm_locale_root))
|
sl@0
|
319 |
perror ("atexit(atexit_rm_locale_root) failed");
|
sl@0
|
320 |
|
sl@0
|
321 |
return locale_root;
|
sl@0
|
322 |
}
|
sl@0
|
323 |
|
sl@0
|
324 |
/**************************************************************************/
|
sl@0
|
325 |
|
sl@0
|
326 |
_TEST_EXPORT char*
|
sl@0
|
327 |
rw_locales (int loc_cat, const char* grep_exp)
|
sl@0
|
328 |
{
|
sl@0
|
329 |
static char* slocname = 0;
|
sl@0
|
330 |
|
sl@0
|
331 |
static int size = 0; // the number of elements in the array
|
sl@0
|
332 |
static int total_size = 5120; // the size of the array
|
sl@0
|
333 |
static int last_cat = loc_cat; // last category
|
sl@0
|
334 |
|
sl@0
|
335 |
// allocate first time through
|
sl@0
|
336 |
if (!slocname) {
|
sl@0
|
337 |
|
sl@0
|
338 |
#ifndef _MSC_VER
|
sl@0
|
339 |
slocname = _RWSTD_STATIC_CAST (char*, malloc (5120));
|
sl@0
|
340 |
#else
|
sl@0
|
341 |
// prevent this leaked allocation from causing failures
|
sl@0
|
342 |
// in tests that keep track of storage allocated in
|
sl@0
|
343 |
// _NORMAL_BLOCKS
|
sl@0
|
344 |
slocname = _RWSTD_STATIC_CAST (char*,
|
sl@0
|
345 |
_malloc_dbg (5120, _CLIENT_BLOCK, 0, 0));
|
sl@0
|
346 |
#endif
|
sl@0
|
347 |
*slocname = '\0';
|
sl@0
|
348 |
}
|
sl@0
|
349 |
|
sl@0
|
350 |
// return immediately if buffer is already initialized
|
sl@0
|
351 |
if (*slocname && loc_cat == last_cat)
|
sl@0
|
352 |
return slocname;
|
sl@0
|
353 |
|
sl@0
|
354 |
// remmeber the category we were last called with
|
sl@0
|
355 |
last_cat = loc_cat;
|
sl@0
|
356 |
|
sl@0
|
357 |
char* locname = slocname;
|
sl@0
|
358 |
|
sl@0
|
359 |
char* save_localename = 0;
|
sl@0
|
360 |
char namebuf [256];
|
sl@0
|
361 |
|
sl@0
|
362 |
if (loc_cat != _UNUSED_CAT) {
|
sl@0
|
363 |
// copy the locale name, the original may be overwitten by libc
|
sl@0
|
364 |
save_localename = strcpy (namebuf, setlocale (loc_cat, 0));
|
sl@0
|
365 |
}
|
sl@0
|
366 |
|
sl@0
|
367 |
const char* const fname = rw_tmpnam (0);
|
sl@0
|
368 |
|
sl@0
|
369 |
if (!fname) {
|
sl@0
|
370 |
return 0; // error
|
sl@0
|
371 |
}
|
sl@0
|
372 |
|
sl@0
|
373 |
// make sure that grep_exp is <= 80
|
sl@0
|
374 |
if (grep_exp && 80 < strlen (grep_exp)) {
|
sl@0
|
375 |
abort ();
|
sl@0
|
376 |
}
|
sl@0
|
377 |
|
sl@0
|
378 |
// execute a shell command and redirect its output into the file
|
sl@0
|
379 |
const int exit_status =
|
sl@0
|
380 |
grep_exp && *grep_exp
|
sl@0
|
381 |
? rw_system ("locale -a | grep \"%s\" > %s", grep_exp, fname)
|
sl@0
|
382 |
: rw_system ("locale -a > %s", fname);
|
sl@0
|
383 |
|
sl@0
|
384 |
if (exit_status) {
|
sl@0
|
385 |
return 0; // error
|
sl@0
|
386 |
}
|
sl@0
|
387 |
|
sl@0
|
388 |
// open file containing the list of installed locales
|
sl@0
|
389 |
FILE *file = fopen (fname, "r");
|
sl@0
|
390 |
|
sl@0
|
391 |
if (file) {
|
sl@0
|
392 |
|
sl@0
|
393 |
char linebuf [256];
|
sl@0
|
394 |
|
sl@0
|
395 |
// even simple locale names can be very long (e.g., on HP-UX,
|
sl@0
|
396 |
// where a locale name always consists of the names of all
|
sl@0
|
397 |
// categories, such as "C C C C C C")
|
sl@0
|
398 |
char last_name [256];
|
sl@0
|
399 |
*last_name = '\0';
|
sl@0
|
400 |
|
sl@0
|
401 |
// if successful, construct a char array with the locales
|
sl@0
|
402 |
while (fgets (linebuf, sizeof linebuf, file)) {
|
sl@0
|
403 |
|
sl@0
|
404 |
linebuf [strlen (linebuf) - 1] = '\0';
|
sl@0
|
405 |
|
sl@0
|
406 |
#ifdef _RWSTD_OS_SUNOS
|
sl@0
|
407 |
|
sl@0
|
408 |
// avoid the bad locale named iso_8859_1 on SunOS
|
sl@0
|
409 |
if (!strcmp ("iso_8859_1", linebuf))
|
sl@0
|
410 |
continue;
|
sl@0
|
411 |
|
sl@0
|
412 |
#endif // _RWSTD_OS_SUNOS
|
sl@0
|
413 |
|
sl@0
|
414 |
// if our buffer is full then dynamically allocate a new one
|
sl@0
|
415 |
if ((size += (strlen (linebuf) + 1)) > total_size) {
|
sl@0
|
416 |
total_size += 5120;
|
sl@0
|
417 |
|
sl@0
|
418 |
char* tmp =
|
sl@0
|
419 |
_RWSTD_STATIC_CAST (char*, malloc (total_size));
|
sl@0
|
420 |
|
sl@0
|
421 |
memcpy (tmp, slocname, total_size - 5120);
|
sl@0
|
422 |
free (slocname);
|
sl@0
|
423 |
|
sl@0
|
424 |
slocname = tmp;
|
sl@0
|
425 |
locname = slocname + size - strlen (linebuf) - 1;
|
sl@0
|
426 |
}
|
sl@0
|
427 |
|
sl@0
|
428 |
#ifdef _WIN64
|
sl@0
|
429 |
|
sl@0
|
430 |
// prevent a hang (OS/libc bug?)
|
sl@0
|
431 |
strcpy (locname, linebuf);
|
sl@0
|
432 |
locname += strlen (linebuf) + 1;
|
sl@0
|
433 |
|
sl@0
|
434 |
#else // if !defined (_WIN64)
|
sl@0
|
435 |
if (loc_cat != _UNUSED_CAT) {
|
sl@0
|
436 |
|
sl@0
|
437 |
// set the C locale to verify that the name is valid
|
sl@0
|
438 |
const char *name = setlocale (loc_cat, linebuf);
|
sl@0
|
439 |
|
sl@0
|
440 |
// if it is and if the actual locale name different
|
sl@0
|
441 |
// from the last one, append it to the list
|
sl@0
|
442 |
if (name && strcmp (last_name, name)) {
|
sl@0
|
443 |
strcpy (locname, linebuf);
|
sl@0
|
444 |
locname += strlen (linebuf) + 1;
|
sl@0
|
445 |
|
sl@0
|
446 |
// save the last locale name
|
sl@0
|
447 |
assert (strlen (name) < sizeof last_name);
|
sl@0
|
448 |
strcpy (last_name, name);
|
sl@0
|
449 |
}
|
sl@0
|
450 |
}
|
sl@0
|
451 |
else {
|
sl@0
|
452 |
strcpy (locname, linebuf);
|
sl@0
|
453 |
locname += strlen (linebuf) + 1;
|
sl@0
|
454 |
}
|
sl@0
|
455 |
|
sl@0
|
456 |
#endif // _WIN64
|
sl@0
|
457 |
|
sl@0
|
458 |
}
|
sl@0
|
459 |
*locname = '\0';
|
sl@0
|
460 |
}
|
sl@0
|
461 |
|
sl@0
|
462 |
if (loc_cat != _UNUSED_CAT)
|
sl@0
|
463 |
setlocale (loc_cat, save_localename);
|
sl@0
|
464 |
|
sl@0
|
465 |
// close before removing
|
sl@0
|
466 |
fclose (file);
|
sl@0
|
467 |
|
sl@0
|
468 |
remove (fname);
|
sl@0
|
469 |
|
sl@0
|
470 |
return slocname;
|
sl@0
|
471 |
}
|