1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/stdcpp/tsrc/Stdcpp_test/stdcxx/testengine/src/localedef.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,471 @@
1.4 +/************************************************************************
1.5 + *
1.6 + * localedef.cpp - definitions of locale helpers
1.7 + *
1.8 + * $Id: localedef.cpp 290022 2005-09-18 23:59:35Z sebor $
1.9 + *
1.10 + ************************************************************************
1.11 + *
1.12 + * Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave
1.13 + * Software division. Licensed under the Apache License, Version 2.0 (the
1.14 + * "License"); you may not use this file except in compliance with the
1.15 + * License. You may obtain a copy of the License at
1.16 + * http://www.apache.org/licenses/LICENSE-2.0. Unless required by
1.17 + * applicable law or agreed to in writing, software distributed under
1.18 + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
1.19 + * CONDITIONS OF ANY KIND, either express or implied. See the License
1.20 + * for the specific language governing permissions and limitations under
1.21 + * the License.
1.22 + *
1.23 + **************************************************************************/
1.24 +
1.25 +// expand _TEST_EXPORT macros
1.26 +#define _RWSTD_TEST_SRC
1.27 +
1.28 +#include <localedef.h>
1.29 +
1.30 +#include <environ.h> // for rw_putenv()
1.31 +#include <file.h> // for SHELL_RM_RF, rw_tmpnam
1.32 +#include <system.h> // for rw_system()
1.33 +
1.34 +
1.35 +#if defined __linux__
1.36 + // on Linux define _XOPEN_SOURCE to get CODESET defined in <langinfo.h>
1.37 +# define _XOPEN_SOURCE 500 /* Single Unix conformance */
1.38 + // bring __int32_t into scope (otherwise <wctype.h> fails to compile)
1.39 +# include <sys/types.h>
1.40 +#endif // __linux__
1.41 +
1.42 +#include <fcntl.h>
1.43 +#include <sys/stat.h> // for stat
1.44 +
1.45 +#if (!defined (_WIN32) && !defined (_WIN64)) || defined (__SYMBIAN32__)
1.46 +# include <unistd.h>
1.47 +# include <sys/wait.h> // for WIFEXITED(), WIFSIGNALED(), WTERMSIG()
1.48 +#else
1.49 +# include <io.h>
1.50 +# include <crtdbg.h> // for _malloc_dbg()
1.51 +#endif
1.52 +
1.53 +#include <ios> // for ios::*
1.54 +#include <limits> // for numeric_limits
1.55 +#include <locale> // for money_base::pattern
1.56 +
1.57 +#include <assert.h> // for assert
1.58 +#include <errno.h> // for EBADF
1.59 +#include <float.h> // for {FLT,DBL,LDBL}_DIG
1.60 +#include <limits.h> // for CHAR_BIT, PATH_MAX
1.61 +#include <locale.h> // for LC_XXX macros, setlocale
1.62 +#include <stdarg.h> // for va_copy, va_list, ...
1.63 +#include <stdio.h> // for fgets, remove, sprintf, ...
1.64 +#include <stdlib.h> // for getenv, free, malloc, realloc
1.65 +#include <string.h> // for strcat, strcpy, strlen, ...
1.66 +#include <ctype.h>
1.67 +#include <wchar.h> // for wcslen, ...
1.68 +
1.69 +#ifndef PATH_MAX
1.70 +# define PATH_MAX 1024
1.71 +#endif
1.72 +
1.73 +#ifndef _MSC_VER
1.74 +# include <clocale>
1.75 +# ifndef LC_MESSAGES
1.76 +# define LC_MESSAGES _RWSTD_LC_MESSAGES
1.77 +# endif // LC_MESSAGES
1.78 +# include <langinfo.h>
1.79 +# define EXE_SUFFIX ""
1.80 +#else // if MSVC
1.81 +# define EXE_SUFFIX ".exe"
1.82 +#endif // _MSC_VER
1.83 +
1.84 +
1.85 +#define TOPDIR "TOPDIR" /* the TOPDIR environment variable */
1.86 +#define BINDIR "BINDIR" /* the BINDIR environment variable */
1.87 +
1.88 +
1.89 +#if _RWSTD_PATH_SEP == '/'
1.90 +# define SLASH "/"
1.91 +# define IS_ABSOLUTE_PATHNAME(path) (_RWSTD_PATH_SEP == *(path))
1.92 +#else
1.93 +# define SLASH "\\"
1.94 +# define IS_ABSOLUTE_PATHNAME(path) \
1.95 + ( ( 'A' <= *(path) && 'Z' >= *(path) \
1.96 + || 'a' <= *(path) && 'z' >= *(path)) \
1.97 + && ':' == (path)[1] \
1.98 + && _RWSTD_PATH_SEP == (path)[2])
1.99 +#endif
1.100 +
1.101 +// relative paths to the etc/nls directory and its subdirectories
1.102 +#if defined (_RWSTD_USE_CONFIG)
1.103 +# define RELPATH "etc" SLASH "nls"
1.104 +# define TESTS_ETC_PATH "tests" SLASH "etc"
1.105 +#else
1.106 +# define RELPATH "etc" SLASH "stdlib" SLASH "nls"
1.107 +# define TESTS_ETC_PATH "tests" SLASH "stdlib" SLASH "etc"
1.108 +#endif // _RWSTD_USE_CONFIG
1.109 +
1.110 +/**************************************************************************/
1.111 +
1.112 +_TEST_EXPORT int
1.113 +rw_locale (const char *args, const char *fname)
1.114 +{
1.115 + // use BINDIR to determine the location of the locale command
1.116 + const char* bindir = getenv ("BINDIR");
1.117 + if (!bindir)
1.118 + bindir = ".." SLASH "bin";
1.119 +
1.120 + int ret;
1.121 +
1.122 + if (fname)
1.123 + ret = rw_system ("%s%slocale%s %s",
1.124 + bindir, SLASH, EXE_SUFFIX, args);
1.125 + else
1.126 + ret = rw_system ("%s%slocale%s %s >%s",
1.127 + bindir, SLASH, EXE_SUFFIX, args, fname);
1.128 +
1.129 + return ret;
1.130 +}
1.131 +
1.132 +/**************************************************************************/
1.133 +
1.134 +_TEST_EXPORT const char*
1.135 +rw_localedef (const char *args,
1.136 + const char* src, const char *charmap, const char *locname)
1.137 +{
1.138 + assert (src && charmap);
1.139 +
1.140 + // create a fully qualified pathname of the locale database
1.141 + // when (locname == 0), the pathname is computed by appending
1.142 + // the name of the character map file `charmap' to the name
1.143 + // of the locale definition file `src'
1.144 + // otherwise, when `locname' is not a pathname, the pathname
1.145 + // of the locale database is formed by appending `locname'
1.146 + // to the name of the locale root directory
1.147 + static char locale_path [PATH_MAX];
1.148 +
1.149 + const char* locale_root = getenv (LOCALE_ROOT_ENVAR);
1.150 + if (!locale_root)
1.151 + locale_root = ".";
1.152 +
1.153 + assert ( strlen (locale_root)
1.154 + + strlen (src)
1.155 + + strlen (charmap)
1.156 + + 2 < sizeof locale_path);
1.157 +
1.158 + strcpy (locale_path, locale_root);
1.159 +
1.160 + if (locname) {
1.161 + if (strchr (locname, _RWSTD_PATH_SEP))
1.162 + strcpy (locale_path, locname);
1.163 + else {
1.164 + strcat (locale_path, SLASH);
1.165 + strcat (locale_path, locname);
1.166 + }
1.167 + }
1.168 + else {
1.169 + // compute the locale pathname from `src', `charmap',
1.170 + // and `locale_root'
1.171 + strcpy (locale_path, locale_root);
1.172 + strcat (locale_path, SLASH);
1.173 +
1.174 + const char *slash = strrchr (src, _RWSTD_PATH_SEP);
1.175 + slash = slash ? slash + 1 : src;
1.176 +
1.177 + strcat (locale_path, src);
1.178 + strcat (locale_path, ".");
1.179 +
1.180 + slash = strrchr (charmap, _RWSTD_PATH_SEP);
1.181 + slash = slash ? slash + 1 : charmap;
1.182 +
1.183 + strcat (locale_path, slash);
1.184 + }
1.185 +
1.186 + // check to see if the locale database already exists and
1.187 + // if so, return immediately the locale filename to the caller
1.188 +#if !defined (_MSC_VER)
1.189 + struct stat sb;
1.190 + if (!stat (locale_path, &sb)) {
1.191 +#else
1.192 + struct _stat sb;
1.193 + if (!_stat (locale_path, &sb)) {
1.194 +#endif
1.195 + return strrchr (locale_path, _RWSTD_PATH_SEP) + 1;
1.196 + }
1.197 +
1.198 + // otherwise, try to create the locale database
1.199 +
1.200 + // use TOPDIR to determine the root of the source tree
1.201 + const char* const topdir = getenv (TOPDIR);
1.202 + if (!topdir || !*topdir) {
1.203 + fprintf (stderr, "%s:%d: the environment variable %s is %s\n",
1.204 + __FILE__, __LINE__, TOPDIR, topdir ? "empty" : "undefined");
1.205 + return 0;
1.206 + }
1.207 +
1.208 + // use BINDIR to determine the location of the localedef command
1.209 + const char* bindir = getenv ("BINDIR");
1.210 + if (!bindir)
1.211 + bindir = ".." SLASH "bin";
1.212 +
1.213 + // if `src' is relative pathname (or a filename) construct the fully
1.214 + // qualified absolute pathname to the locale definition file from it
1.215 + char src_path [PATH_MAX];
1.216 +
1.217 + if (!IS_ABSOLUTE_PATHNAME (src)) {
1.218 + strcpy (src_path, topdir);
1.219 + strcat (src_path, SLASH RELPATH SLASH "src" SLASH);
1.220 + strcat (src_path, src);
1.221 +
1.222 + // if the file doesn't exist, see if there is a file
1.223 + // with that name in the locale root directory (e.g.,
1.224 + // a temporary file)
1.225 + FILE* const file_exists = fopen (src_path, "r");
1.226 + if (file_exists)
1.227 + fclose (file_exists);
1.228 + else {
1.229 + strcpy (src_path, locale_root);
1.230 + strcat (src_path, SLASH);
1.231 + strcat (src_path, src);
1.232 + }
1.233 +
1.234 + src = src_path;
1.235 + }
1.236 +
1.237 + char charmap_path [PATH_MAX];
1.238 + if (!IS_ABSOLUTE_PATHNAME (charmap)) {
1.239 + strcpy (charmap_path, topdir);
1.240 + strcat (charmap_path, SLASH RELPATH SLASH "charmaps" SLASH);
1.241 + strcat (charmap_path, charmap);
1.242 +
1.243 + // if the file doesn't exist, see if there is a file
1.244 + // with that name in the locale root directory (e.g.,
1.245 + // a temporary file)
1.246 + FILE* const file_exists = fopen (charmap_path, "r");
1.247 + if (file_exists)
1.248 + fclose (file_exists);
1.249 + else {
1.250 + strcpy (charmap_path, locale_root);
1.251 + strcat (charmap_path, SLASH);
1.252 + strcat (charmap_path, charmap);
1.253 + }
1.254 +
1.255 + charmap = charmap_path;
1.256 + }
1.257 +
1.258 + if (!args)
1.259 + args = "";
1.260 +
1.261 + const int ret = rw_system ("%s%slocaledef%s %s -c -f %s -i %s %s",
1.262 + bindir, SLASH, EXE_SUFFIX, args,
1.263 + charmap, src, locale_path);
1.264 +
1.265 + // return the unqualified locale file name on success or 0 on failure
1.266 + return ret ? (char*)0 : strrchr (locale_path, _RWSTD_PATH_SEP) + 1;
1.267 +}
1.268 +
1.269 +/**************************************************************************/
1.270 +
1.271 +extern "C" {
1.272 +
1.273 +static char rw_locale_root [256];
1.274 +
1.275 +static void atexit_rm_locale_root ()
1.276 +{
1.277 + // remove temporary locale databases created by the test
1.278 + rw_system (SHELL_RM_RF "%s", rw_locale_root);
1.279 +}
1.280 +
1.281 +}
1.282 +
1.283 +_TEST_EXPORT const char*
1.284 +rw_set_locale_root ()
1.285 +{
1.286 + // set any additional environment variables defined in
1.287 + // the RW_PUTENV environment variable (if it exists)
1.288 + rw_putenv (0);
1.289 +
1.290 + // create a temporary directory for files created by the test
1.291 + const char* const locale_root = rw_tmpnam (rw_locale_root);
1.292 + if (!locale_root)
1.293 + return 0;
1.294 +
1.295 + char envvar [sizeof LOCALE_ROOT_ENVAR + sizeof rw_locale_root] =
1.296 + LOCALE_ROOT_ENVAR "=";
1.297 +#ifndef __SYMBIAN32__
1.298 + std::strcat (envvar, locale_root);
1.299 +#else
1.300 + strcat (envvar, locale_root);
1.301 +#endif
1.302 + // remove temporary file if mkstemp() rw_tmpnam() called mkstemp()
1.303 + if (rw_system (SHELL_RM_RF " %s", locale_root)) {
1.304 +
1.305 +#if defined (_WIN32) || defined (_WIN64)
1.306 + // ignore errors on WIN32 where the stupid DEL command
1.307 + // fails even with /Q /S when the files don't exist
1.308 +#else
1.309 + // assume a sane implementation of SHELL_RM_RF
1.310 + return 0;
1.311 +#endif // _WIN{32,64}
1.312 + }
1.313 +
1.314 + if (rw_system ("mkdir %s", locale_root))
1.315 + return 0;
1.316 +
1.317 + // set the "RWSTD_LOCALE_ROOT" environment variable
1.318 + // where std::locale looks for locale database files
1.319 + rw_putenv (envvar);
1.320 +
1.321 + if (atexit (atexit_rm_locale_root))
1.322 + perror ("atexit(atexit_rm_locale_root) failed");
1.323 +
1.324 + return locale_root;
1.325 +}
1.326 +
1.327 +/**************************************************************************/
1.328 +
1.329 +_TEST_EXPORT char*
1.330 +rw_locales (int loc_cat, const char* grep_exp)
1.331 +{
1.332 + static char* slocname = 0;
1.333 +
1.334 + static int size = 0; // the number of elements in the array
1.335 + static int total_size = 5120; // the size of the array
1.336 + static int last_cat = loc_cat; // last category
1.337 +
1.338 + // allocate first time through
1.339 + if (!slocname) {
1.340 +
1.341 +#ifndef _MSC_VER
1.342 + slocname = _RWSTD_STATIC_CAST (char*, malloc (5120));
1.343 +#else
1.344 + // prevent this leaked allocation from causing failures
1.345 + // in tests that keep track of storage allocated in
1.346 + // _NORMAL_BLOCKS
1.347 + slocname = _RWSTD_STATIC_CAST (char*,
1.348 + _malloc_dbg (5120, _CLIENT_BLOCK, 0, 0));
1.349 +#endif
1.350 + *slocname = '\0';
1.351 + }
1.352 +
1.353 + // return immediately if buffer is already initialized
1.354 + if (*slocname && loc_cat == last_cat)
1.355 + return slocname;
1.356 +
1.357 + // remmeber the category we were last called with
1.358 + last_cat = loc_cat;
1.359 +
1.360 + char* locname = slocname;
1.361 +
1.362 + char* save_localename = 0;
1.363 + char namebuf [256];
1.364 +
1.365 + if (loc_cat != _UNUSED_CAT) {
1.366 + // copy the locale name, the original may be overwitten by libc
1.367 + save_localename = strcpy (namebuf, setlocale (loc_cat, 0));
1.368 + }
1.369 +
1.370 + const char* const fname = rw_tmpnam (0);
1.371 +
1.372 + if (!fname) {
1.373 + return 0; // error
1.374 + }
1.375 +
1.376 + // make sure that grep_exp is <= 80
1.377 + if (grep_exp && 80 < strlen (grep_exp)) {
1.378 + abort ();
1.379 + }
1.380 +
1.381 + // execute a shell command and redirect its output into the file
1.382 + const int exit_status =
1.383 + grep_exp && *grep_exp
1.384 + ? rw_system ("locale -a | grep \"%s\" > %s", grep_exp, fname)
1.385 + : rw_system ("locale -a > %s", fname);
1.386 +
1.387 + if (exit_status) {
1.388 + return 0; // error
1.389 + }
1.390 +
1.391 + // open file containing the list of installed locales
1.392 + FILE *file = fopen (fname, "r");
1.393 +
1.394 + if (file) {
1.395 +
1.396 + char linebuf [256];
1.397 +
1.398 + // even simple locale names can be very long (e.g., on HP-UX,
1.399 + // where a locale name always consists of the names of all
1.400 + // categories, such as "C C C C C C")
1.401 + char last_name [256];
1.402 + *last_name = '\0';
1.403 +
1.404 + // if successful, construct a char array with the locales
1.405 + while (fgets (linebuf, sizeof linebuf, file)) {
1.406 +
1.407 + linebuf [strlen (linebuf) - 1] = '\0';
1.408 +
1.409 +#ifdef _RWSTD_OS_SUNOS
1.410 +
1.411 + // avoid the bad locale named iso_8859_1 on SunOS
1.412 + if (!strcmp ("iso_8859_1", linebuf))
1.413 + continue;
1.414 +
1.415 +#endif // _RWSTD_OS_SUNOS
1.416 +
1.417 + // if our buffer is full then dynamically allocate a new one
1.418 + if ((size += (strlen (linebuf) + 1)) > total_size) {
1.419 + total_size += 5120;
1.420 +
1.421 + char* tmp =
1.422 + _RWSTD_STATIC_CAST (char*, malloc (total_size));
1.423 +
1.424 + memcpy (tmp, slocname, total_size - 5120);
1.425 + free (slocname);
1.426 +
1.427 + slocname = tmp;
1.428 + locname = slocname + size - strlen (linebuf) - 1;
1.429 + }
1.430 +
1.431 +#ifdef _WIN64
1.432 +
1.433 + // prevent a hang (OS/libc bug?)
1.434 + strcpy (locname, linebuf);
1.435 + locname += strlen (linebuf) + 1;
1.436 +
1.437 +#else // if !defined (_WIN64)
1.438 + if (loc_cat != _UNUSED_CAT) {
1.439 +
1.440 + // set the C locale to verify that the name is valid
1.441 + const char *name = setlocale (loc_cat, linebuf);
1.442 +
1.443 + // if it is and if the actual locale name different
1.444 + // from the last one, append it to the list
1.445 + if (name && strcmp (last_name, name)) {
1.446 + strcpy (locname, linebuf);
1.447 + locname += strlen (linebuf) + 1;
1.448 +
1.449 + // save the last locale name
1.450 + assert (strlen (name) < sizeof last_name);
1.451 + strcpy (last_name, name);
1.452 + }
1.453 + }
1.454 + else {
1.455 + strcpy (locname, linebuf);
1.456 + locname += strlen (linebuf) + 1;
1.457 + }
1.458 +
1.459 +#endif // _WIN64
1.460 +
1.461 + }
1.462 + *locname = '\0';
1.463 + }
1.464 +
1.465 + if (loc_cat != _UNUSED_CAT)
1.466 + setlocale (loc_cat, save_localename);
1.467 +
1.468 + // close before removing
1.469 + fclose (file);
1.470 +
1.471 + remove (fname);
1.472 +
1.473 + return slocname;
1.474 +}