1 1.1 christos /* Implementation of the internal dcigettext function. 2 1.1 christos Copyright (C) 1995-1999, 2000-2006 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos This program is free software; you can redistribute it and/or modify it 5 1.1 christos under the terms of the GNU Library General Public License as published 6 1.1 christos by the Free Software Foundation; either version 2, or (at your option) 7 1.1 christos any later version. 8 1.1 christos 9 1.1 christos This program is distributed in the hope that it will be useful, 10 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 11 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 1.1 christos Library General Public License for more details. 13 1.1 christos 14 1.1 christos You should have received a copy of the GNU Library General Public 15 1.1 christos License along with this program; if not, write to the Free Software 16 1.1 christos Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 17 1.1 christos USA. */ 18 1.1 christos 19 1.1 christos /* Tell glibc's <string.h> to provide a prototype for mempcpy(). 20 1.1 christos This must come before <config.h> because <config.h> may include 21 1.1 christos <features.h>, and once <features.h> has been included, it's too late. */ 22 1.1 christos #ifndef _GNU_SOURCE 23 1.1 christos # define _GNU_SOURCE 1 24 1.1 christos #endif 25 1.1 christos 26 1.1 christos #ifdef HAVE_CONFIG_H 27 1.1 christos # include <config.h> 28 1.1 christos #endif 29 1.1 christos 30 1.1 christos /* NL_LOCALE_NAME does not work in glibc-2.4. Ignore it. */ 31 1.1 christos #undef HAVE_NL_LOCALE_NAME 32 1.1 christos 33 1.1 christos #include <sys/types.h> 34 1.1 christos 35 1.1 christos #ifdef __GNUC__ 36 1.1 christos # define alloca __builtin_alloca 37 1.1 christos # define HAVE_ALLOCA 1 38 1.1 christos #else 39 1.1 christos # ifdef _MSC_VER 40 1.1 christos # include <malloc.h> 41 1.1 christos # define alloca _alloca 42 1.1 christos # else 43 1.1 christos # if defined HAVE_ALLOCA_H || defined _LIBC 44 1.1 christos # include <alloca.h> 45 1.1 christos # else 46 1.1 christos # ifdef _AIX 47 1.1 christos #pragma alloca 48 1.1 christos # else 49 1.1 christos # ifndef alloca 50 1.1 christos char *alloca (); 51 1.1 christos # endif 52 1.1 christos # endif 53 1.1 christos # endif 54 1.1 christos # endif 55 1.1 christos #endif 56 1.1 christos 57 1.1 christos #include <errno.h> 58 1.1 christos #ifndef errno 59 1.1 christos extern int errno; 60 1.1 christos #endif 61 1.1 christos #ifndef __set_errno 62 1.1 christos # define __set_errno(val) errno = (val) 63 1.1 christos #endif 64 1.1 christos 65 1.1 christos #include <stddef.h> 66 1.1 christos #include <stdlib.h> 67 1.1 christos #include <string.h> 68 1.1 christos 69 1.1 christos #if defined HAVE_UNISTD_H || defined _LIBC 70 1.1 christos # include <unistd.h> 71 1.1 christos #endif 72 1.1 christos 73 1.1 christos #include <locale.h> 74 1.1 christos 75 1.1 christos #ifdef _LIBC 76 1.1 christos /* Guess whether integer division by zero raises signal SIGFPE. 77 1.1 christos Set to 1 only if you know for sure. In case of doubt, set to 0. */ 78 1.1 christos # if defined __alpha__ || defined __arm__ || defined __i386__ \ 79 1.1 christos || defined __m68k__ || defined __s390__ 80 1.1 christos # define INTDIV0_RAISES_SIGFPE 1 81 1.1 christos # else 82 1.1 christos # define INTDIV0_RAISES_SIGFPE 0 83 1.1 christos # endif 84 1.1 christos #endif 85 1.1 christos #if !INTDIV0_RAISES_SIGFPE 86 1.1 christos # include <signal.h> 87 1.1 christos #endif 88 1.1 christos 89 1.1 christos #if defined HAVE_SYS_PARAM_H || defined _LIBC 90 1.1 christos # include <sys/param.h> 91 1.1 christos #endif 92 1.1 christos 93 1.1 christos #if !defined _LIBC && HAVE_NL_LOCALE_NAME 94 1.1 christos # include <langinfo.h> 95 1.1 christos #endif 96 1.1 christos 97 1.1 christos #include "gettextP.h" 98 1.1 christos #include "plural-exp.h" 99 1.1 christos #ifdef _LIBC 100 1.1 christos # include <libintl.h> 101 1.1 christos #else 102 1.1 christos # ifdef IN_LIBGLOCALE 103 1.1 christos # include <libintl.h> 104 1.1 christos # endif 105 1.1 christos # include "libgnuintl.h" 106 1.1 christos #endif 107 1.1 christos #include "hash-string.h" 108 1.1 christos 109 1.1 christos /* Handle multi-threaded applications. */ 110 1.1 christos #ifdef _LIBC 111 1.1 christos # include <bits/libc-lock.h> 112 1.1 christos # define gl_rwlock_define_initialized __libc_rwlock_define_initialized 113 1.1 christos # define gl_rwlock_rdlock __libc_rwlock_rdlock 114 1.1 christos # define gl_rwlock_wrlock __libc_rwlock_wrlock 115 1.1 christos # define gl_rwlock_unlock __libc_rwlock_unlock 116 1.1 christos #else 117 1.1 christos # include "lock.h" 118 1.1 christos #endif 119 1.1 christos 120 1.1 christos /* Alignment of types. */ 121 1.1 christos #if defined __GNUC__ && __GNUC__ >= 2 122 1.1 christos # define alignof(TYPE) __alignof__ (TYPE) 123 1.1 christos #else 124 1.1 christos # define alignof(TYPE) \ 125 1.1 christos ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2) 126 1.1 christos #endif 127 1.1 christos 128 1.1 christos /* The internal variables in the standalone libintl.a must have different 129 1.1 christos names than the internal variables in GNU libc, otherwise programs 130 1.1 christos using libintl.a cannot be linked statically. */ 131 1.1 christos #if !defined _LIBC 132 1.1 christos # define _nl_default_default_domain libintl_nl_default_default_domain 133 1.1 christos # define _nl_current_default_domain libintl_nl_current_default_domain 134 1.1 christos # define _nl_default_dirname libintl_nl_default_dirname 135 1.1 christos # define _nl_domain_bindings libintl_nl_domain_bindings 136 1.1 christos #endif 137 1.1 christos 138 1.1 christos /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */ 139 1.1 christos #ifndef offsetof 140 1.1 christos # define offsetof(type,ident) ((size_t)&(((type*)0)->ident)) 141 1.1 christos #endif 142 1.1 christos 143 1.1 christos /* @@ end of prolog @@ */ 144 1.1 christos 145 1.1 christos #ifdef _LIBC 146 1.1 christos /* Rename the non ANSI C functions. This is required by the standard 147 1.1 christos because some ANSI C functions will require linking with this object 148 1.1 christos file and the name space must not be polluted. */ 149 1.1 christos # define getcwd __getcwd 150 1.1 christos # ifndef stpcpy 151 1.1 christos # define stpcpy __stpcpy 152 1.1 christos # endif 153 1.1 christos # define tfind __tfind 154 1.1 christos #else 155 1.1 christos # if !defined HAVE_GETCWD 156 1.1 christos char *getwd (); 157 1.1 christos # define getcwd(buf, max) getwd (buf) 158 1.1 christos # else 159 1.1 christos # if VMS 160 1.1 christos # define getcwd(buf, max) (getcwd) (buf, max, 0) 161 1.1 christos # else 162 1.1 christos char *getcwd (); 163 1.1 christos # endif 164 1.1 christos # endif 165 1.1 christos # ifndef HAVE_STPCPY 166 1.1 christos static char *stpcpy (char *dest, const char *src); 167 1.1 christos # endif 168 1.1 christos # ifndef HAVE_MEMPCPY 169 1.1 christos static void *mempcpy (void *dest, const void *src, size_t n); 170 1.1 christos # endif 171 1.1 christos #endif 172 1.1 christos 173 1.1 christos /* Amount to increase buffer size by in each try. */ 174 1.1 christos #define PATH_INCR 32 175 1.1 christos 176 1.1 christos /* The following is from pathmax.h. */ 177 1.1 christos /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define 178 1.1 christos PATH_MAX but might cause redefinition warnings when sys/param.h is 179 1.1 christos later included (as on MORE/BSD 4.3). */ 180 1.1 christos #if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__) 181 1.1 christos # include <limits.h> 182 1.1 christos #endif 183 1.1 christos 184 1.1 christos #ifndef _POSIX_PATH_MAX 185 1.1 christos # define _POSIX_PATH_MAX 255 186 1.1 christos #endif 187 1.1 christos 188 1.1 christos #if !defined PATH_MAX && defined _PC_PATH_MAX 189 1.1 christos # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX)) 190 1.1 christos #endif 191 1.1 christos 192 1.1 christos /* Don't include sys/param.h if it already has been. */ 193 1.1 christos #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN 194 1.1 christos # include <sys/param.h> 195 1.1 christos #endif 196 1.1 christos 197 1.1 christos #if !defined PATH_MAX && defined MAXPATHLEN 198 1.1 christos # define PATH_MAX MAXPATHLEN 199 1.1 christos #endif 200 1.1 christos 201 1.1 christos #ifndef PATH_MAX 202 1.1 christos # define PATH_MAX _POSIX_PATH_MAX 203 1.1 christos #endif 204 1.1 christos 205 1.1 christos /* Pathname support. 206 1.1 christos ISSLASH(C) tests whether C is a directory separator character. 207 1.1 christos IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not, 208 1.1 christos it may be concatenated to a directory pathname. 209 1.1 christos IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. 210 1.1 christos */ 211 1.1 christos #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ 212 1.1 christos /* Win32, Cygwin, OS/2, DOS */ 213 1.1 christos # define ISSLASH(C) ((C) == '/' || (C) == '\\') 214 1.1 christos # define HAS_DEVICE(P) \ 215 1.1 christos ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ 216 1.1 christos && (P)[1] == ':') 217 1.1 christos # define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P)) 218 1.1 christos # define IS_PATH_WITH_DIR(P) \ 219 1.1 christos (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P)) 220 1.1 christos #else 221 1.1 christos /* Unix */ 222 1.1 christos # define ISSLASH(C) ((C) == '/') 223 1.1 christos # define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0]) 224 1.1 christos # define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) 225 1.1 christos #endif 226 1.1 christos 227 1.1 christos /* Whether to support different locales in different threads. */ 228 1.1 christos #if defined _LIBC || HAVE_NL_LOCALE_NAME || (HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS) || defined IN_LIBGLOCALE 229 1.1 christos # define HAVE_PER_THREAD_LOCALE 230 1.1 christos #endif 231 1.1 christos 232 1.1 christos /* This is the type used for the search tree where known translations 233 1.1 christos are stored. */ 234 1.1 christos struct known_translation_t 235 1.1 christos { 236 1.1 christos /* Domain in which to search. */ 237 1.1 christos const char *domainname; 238 1.1 christos 239 1.1 christos /* The category. */ 240 1.1 christos int category; 241 1.1 christos 242 1.1 christos #ifdef HAVE_PER_THREAD_LOCALE 243 1.1 christos /* Name of the relevant locale category, or "" for the global locale. */ 244 1.1 christos const char *localename; 245 1.1 christos #endif 246 1.1 christos 247 1.1 christos #ifdef IN_LIBGLOCALE 248 1.1 christos /* The character encoding. */ 249 1.1 christos const char *encoding; 250 1.1 christos #endif 251 1.1 christos 252 1.1 christos /* State of the catalog counter at the point the string was found. */ 253 1.1 christos int counter; 254 1.1 christos 255 1.1 christos /* Catalog where the string was found. */ 256 1.1 christos struct loaded_l10nfile *domain; 257 1.1 christos 258 1.1 christos /* And finally the translation. */ 259 1.1 christos const char *translation; 260 1.1 christos size_t translation_length; 261 1.1 christos 262 1.1 christos /* Pointer to the string in question. */ 263 1.1 christos char msgid[ZERO]; 264 1.1 christos }; 265 1.1 christos 266 1.1 christos /* Root of the search tree with known translations. We can use this 267 1.1 christos only if the system provides the `tsearch' function family. */ 268 1.1 christos #if defined HAVE_TSEARCH || defined _LIBC 269 1.1 christos # include <search.h> 270 1.1 christos 271 1.1 christos gl_rwlock_define_initialized (static, tree_lock) 272 1.1 christos 273 1.1 christos static void *root; 274 1.1 christos 275 1.1 christos # ifdef _LIBC 276 1.1 christos # define tsearch __tsearch 277 1.1 christos # endif 278 1.1 christos 279 1.1 christos /* Function to compare two entries in the table of known translations. */ 280 1.1 christos static int 281 1.1 christos transcmp (const void *p1, const void *p2) 282 1.1 christos { 283 1.1 christos const struct known_translation_t *s1; 284 1.1 christos const struct known_translation_t *s2; 285 1.1 christos int result; 286 1.1 christos 287 1.1 christos s1 = (const struct known_translation_t *) p1; 288 1.1 christos s2 = (const struct known_translation_t *) p2; 289 1.1 christos 290 1.1 christos result = strcmp (s1->msgid, s2->msgid); 291 1.1 christos if (result == 0) 292 1.1 christos { 293 1.1 christos result = strcmp (s1->domainname, s2->domainname); 294 1.1 christos if (result == 0) 295 1.1 christos { 296 1.1 christos #ifdef HAVE_PER_THREAD_LOCALE 297 1.1 christos result = strcmp (s1->localename, s2->localename); 298 1.1 christos if (result == 0) 299 1.1 christos #endif 300 1.1 christos { 301 1.1 christos #ifdef IN_LIBGLOCALE 302 1.1 christos result = strcmp (s1->encoding, s2->encoding); 303 1.1 christos if (result == 0) 304 1.1 christos #endif 305 1.1 christos /* We compare the category last (though this is the cheapest 306 1.1 christos operation) since it is hopefully always the same (namely 307 1.1 christos LC_MESSAGES). */ 308 1.1 christos result = s1->category - s2->category; 309 1.1 christos } 310 1.1 christos } 311 1.1 christos } 312 1.1 christos 313 1.1 christos return result; 314 1.1 christos } 315 1.1 christos #endif 316 1.1 christos 317 1.1 christos /* Name of the default domain used for gettext(3) prior any call to 318 1.1 christos textdomain(3). The default value for this is "messages". */ 319 1.1 christos const char _nl_default_default_domain[] attribute_hidden = "messages"; 320 1.1 christos 321 1.1 christos #ifndef IN_LIBGLOCALE 322 1.1 christos /* Value used as the default domain for gettext(3). */ 323 1.1 christos const char *_nl_current_default_domain attribute_hidden 324 1.1 christos = _nl_default_default_domain; 325 1.1 christos #endif 326 1.1 christos 327 1.1 christos /* Contains the default location of the message catalogs. */ 328 1.1 christos #if defined __EMX__ 329 1.1 christos extern const char _nl_default_dirname[]; 330 1.1 christos #else 331 1.1 christos # ifdef _LIBC 332 1.1 christos extern const char _nl_default_dirname[]; 333 1.1 christos libc_hidden_proto (_nl_default_dirname) 334 1.1 christos # endif 335 1.1 christos const char _nl_default_dirname[] = LOCALEDIR; 336 1.1 christos # ifdef _LIBC 337 1.1 christos libc_hidden_data_def (_nl_default_dirname) 338 1.1 christos # endif 339 1.1 christos #endif 340 1.1 christos 341 1.1 christos #ifndef IN_LIBGLOCALE 342 1.1 christos /* List with bindings of specific domains created by bindtextdomain() 343 1.1 christos calls. */ 344 1.1 christos struct binding *_nl_domain_bindings; 345 1.1 christos #endif 346 1.1 christos 347 1.1 christos /* Prototypes for local functions. */ 348 1.1 christos static char *plural_lookup (struct loaded_l10nfile *domain, 349 1.1 christos unsigned long int n, 350 1.1 christos const char *translation, size_t translation_len) 351 1.1 christos internal_function; 352 1.1 christos 353 1.1 christos #ifdef IN_LIBGLOCALE 354 1.1 christos static const char *guess_category_value (int category, 355 1.1 christos const char *categoryname, 356 1.1 christos const char *localename) 357 1.1 christos internal_function; 358 1.1 christos #else 359 1.1 christos static const char *guess_category_value (int category, 360 1.1 christos const char *categoryname) 361 1.1 christos internal_function; 362 1.1 christos #endif 363 1.1 christos 364 1.1 christos #ifdef _LIBC 365 1.1 christos # include "../locale/localeinfo.h" 366 1.1 christos # define category_to_name(category) \ 367 1.1 christos _nl_category_names.str + _nl_category_name_idxs[category] 368 1.1 christos #else 369 1.1 christos static const char *category_to_name (int category) internal_function; 370 1.1 christos #endif 371 1.1 christos #if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE 372 1.1 christos static const char *get_output_charset (struct binding *domainbinding) 373 1.1 christos internal_function; 374 1.1 christos #endif 375 1.1 christos 376 1.1 christos 377 1.1 christos /* For those loosing systems which don't have `alloca' we have to add 378 1.1 christos some additional code emulating it. */ 379 1.1 christos #ifdef HAVE_ALLOCA 380 1.1 christos /* Nothing has to be done. */ 381 1.1 christos # define freea(p) /* nothing */ 382 1.1 christos # define ADD_BLOCK(list, address) /* nothing */ 383 1.1 christos # define FREE_BLOCKS(list) /* nothing */ 384 1.1 christos #else 385 1.1 christos struct block_list 386 1.1 christos { 387 1.1 christos void *address; 388 1.1 christos struct block_list *next; 389 1.1 christos }; 390 1.1 christos # define ADD_BLOCK(list, addr) \ 391 1.1 christos do { \ 392 1.1 christos struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \ 393 1.1 christos /* If we cannot get a free block we cannot add the new element to \ 394 1.1 christos the list. */ \ 395 1.1 christos if (newp != NULL) { \ 396 1.1 christos newp->address = (addr); \ 397 1.1 christos newp->next = (list); \ 398 1.1 christos (list) = newp; \ 399 1.1 christos } \ 400 1.1 christos } while (0) 401 1.1 christos # define FREE_BLOCKS(list) \ 402 1.1 christos do { \ 403 1.1 christos while (list != NULL) { \ 404 1.1 christos struct block_list *old = list; \ 405 1.1 christos list = list->next; \ 406 1.1 christos free (old->address); \ 407 1.1 christos free (old); \ 408 1.1 christos } \ 409 1.1 christos } while (0) 410 1.1 christos # undef alloca 411 1.1 christos # define alloca(size) (malloc (size)) 412 1.1 christos # define freea(p) free (p) 413 1.1 christos #endif /* have alloca */ 414 1.1 christos 415 1.1 christos 416 1.1 christos #ifdef _LIBC 417 1.1 christos /* List of blocks allocated for translations. */ 418 1.1 christos typedef struct transmem_list 419 1.1 christos { 420 1.1 christos struct transmem_list *next; 421 1.1 christos char data[ZERO]; 422 1.1 christos } transmem_block_t; 423 1.1 christos static struct transmem_list *transmem_list; 424 1.1 christos #else 425 1.1 christos typedef unsigned char transmem_block_t; 426 1.1 christos #endif 427 1.1 christos 428 1.1 christos 429 1.1 christos /* Names for the libintl functions are a problem. They must not clash 430 1.1 christos with existing names and they should follow ANSI C. But this source 431 1.1 christos code is also used in GNU C Library where the names have a __ 432 1.1 christos prefix. So we have to make a difference here. */ 433 1.1 christos #ifdef _LIBC 434 1.1 christos # define DCIGETTEXT __dcigettext 435 1.1 christos #else 436 1.1 christos # define DCIGETTEXT libintl_dcigettext 437 1.1 christos #endif 438 1.1 christos 439 1.1 christos /* Lock variable to protect the global data in the gettext implementation. */ 440 1.1 christos gl_rwlock_define_initialized (, _nl_state_lock attribute_hidden) 441 1.1 christos 442 1.1 christos /* Checking whether the binaries runs SUID must be done and glibc provides 443 1.1 christos easier methods therefore we make a difference here. */ 444 1.1 christos #ifdef _LIBC 445 1.1 christos # define ENABLE_SECURE __libc_enable_secure 446 1.1 christos # define DETERMINE_SECURE 447 1.1 christos #else 448 1.1 christos # ifndef HAVE_GETUID 449 1.1 christos # define getuid() 0 450 1.1 christos # endif 451 1.1 christos # ifndef HAVE_GETGID 452 1.1 christos # define getgid() 0 453 1.1 christos # endif 454 1.1 christos # ifndef HAVE_GETEUID 455 1.1 christos # define geteuid() getuid() 456 1.1 christos # endif 457 1.1 christos # ifndef HAVE_GETEGID 458 1.1 christos # define getegid() getgid() 459 1.1 christos # endif 460 1.1 christos static int enable_secure; 461 1.1 christos # define ENABLE_SECURE (enable_secure == 1) 462 1.1 christos # define DETERMINE_SECURE \ 463 1.1 christos if (enable_secure == 0) \ 464 1.1 christos { \ 465 1.1 christos if (getuid () != geteuid () || getgid () != getegid ()) \ 466 1.1 christos enable_secure = 1; \ 467 1.1 christos else \ 468 1.1 christos enable_secure = -1; \ 469 1.1 christos } 470 1.1 christos #endif 471 1.1 christos 472 1.1 christos /* Get the function to evaluate the plural expression. */ 473 1.1 christos #include "eval-plural.h" 474 1.1 christos 475 1.1 christos /* Look up MSGID in the DOMAINNAME message catalog for the current 476 1.1 christos CATEGORY locale and, if PLURAL is nonzero, search over string 477 1.1 christos depending on the plural form determined by N. */ 478 1.1 christos #ifdef IN_LIBGLOCALE 479 1.1 christos char * 480 1.1 christos gl_dcigettext (const char *domainname, 481 1.1 christos const char *msgid1, const char *msgid2, 482 1.1 christos int plural, unsigned long int n, 483 1.1 christos int category, 484 1.1 christos const char *localename, const char *encoding) 485 1.1 christos #else 486 1.1 christos char * 487 1.1 christos DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, 488 1.1 christos int plural, unsigned long int n, int category) 489 1.1 christos #endif 490 1.1 christos { 491 1.1 christos #ifndef HAVE_ALLOCA 492 1.1 christos struct block_list *block_list = NULL; 493 1.1 christos #endif 494 1.1 christos struct loaded_l10nfile *domain; 495 1.1 christos struct binding *binding; 496 1.1 christos const char *categoryname; 497 1.1 christos const char *categoryvalue; 498 1.1 christos const char *dirname; 499 1.1 christos char *xdomainname; 500 1.1 christos char *single_locale; 501 1.1 christos char *retval; 502 1.1 christos size_t retlen; 503 1.1 christos int saved_errno; 504 1.1 christos #if defined HAVE_TSEARCH || defined _LIBC 505 1.1 christos struct known_translation_t *search; 506 1.1 christos struct known_translation_t **foundp = NULL; 507 1.1 christos size_t msgid_len; 508 1.1 christos # if defined HAVE_PER_THREAD_LOCALE && !defined IN_LIBGLOCALE 509 1.1 christos const char *localename; 510 1.1 christos # endif 511 1.1 christos #endif 512 1.1 christos size_t domainname_len; 513 1.1 christos 514 1.1 christos /* If no real MSGID is given return NULL. */ 515 1.1 christos if (msgid1 == NULL) 516 1.1 christos return NULL; 517 1.1 christos 518 1.1 christos #ifdef _LIBC 519 1.1 christos if (category < 0 || category >= __LC_LAST || category == LC_ALL) 520 1.1 christos /* Bogus. */ 521 1.1 christos return (plural == 0 522 1.1 christos ? (char *) msgid1 523 1.1 christos /* Use the Germanic plural rule. */ 524 1.1 christos : n == 1 ? (char *) msgid1 : (char *) msgid2); 525 1.1 christos #endif 526 1.1 christos 527 1.1 christos gl_rwlock_rdlock (_nl_state_lock); 528 1.1 christos 529 1.1 christos /* If DOMAINNAME is NULL, we are interested in the default domain. If 530 1.1 christos CATEGORY is not LC_MESSAGES this might not make much sense but the 531 1.1 christos definition left this undefined. */ 532 1.1 christos if (domainname == NULL) 533 1.1 christos domainname = _nl_current_default_domain; 534 1.1 christos 535 1.1 christos /* OS/2 specific: backward compatibility with older libintl versions */ 536 1.1 christos #ifdef LC_MESSAGES_COMPAT 537 1.1 christos if (category == LC_MESSAGES_COMPAT) 538 1.1 christos category = LC_MESSAGES; 539 1.1 christos #endif 540 1.1 christos 541 1.1 christos #if defined HAVE_TSEARCH || defined _LIBC 542 1.1 christos msgid_len = strlen (msgid1) + 1; 543 1.1 christos 544 1.1 christos /* Try to find the translation among those which we found at 545 1.1 christos some time. */ 546 1.1 christos search = (struct known_translation_t *) 547 1.1 christos alloca (offsetof (struct known_translation_t, msgid) + msgid_len); 548 1.1 christos memcpy (search->msgid, msgid1, msgid_len); 549 1.1 christos search->domainname = domainname; 550 1.1 christos search->category = category; 551 1.1 christos # ifdef HAVE_PER_THREAD_LOCALE 552 1.1 christos # ifndef IN_LIBGLOCALE 553 1.1 christos # ifdef _LIBC 554 1.1 christos localename = __current_locale_name (category); 555 1.1 christos # else 556 1.1 christos # if HAVE_NL_LOCALE_NAME 557 1.1 christos /* NL_LOCALE_NAME is public glibc API introduced in glibc-2.4. */ 558 1.1 christos localename = nl_langinfo (NL_LOCALE_NAME (category)); 559 1.1 christos # else 560 1.1 christos # if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS 561 1.1 christos /* The __names field is not public glibc API and must therefore not be used 562 1.1 christos in code that is installed in public locations. */ 563 1.1 christos { 564 1.1 christos locale_t thread_locale = uselocale (NULL); 565 1.1 christos if (thread_locale != LC_GLOBAL_LOCALE) 566 1.1 christos localename = thread_locale->__names[category]; 567 1.1 christos else 568 1.1 christos localename = ""; 569 1.1 christos } 570 1.1 christos # endif 571 1.1 christos # endif 572 1.1 christos # endif 573 1.1 christos # endif 574 1.1 christos search->localename = localename; 575 1.1 christos # ifdef IN_LIBGLOCALE 576 1.1 christos search->encoding = encoding; 577 1.1 christos # endif 578 1.1 christos # endif 579 1.1 christos 580 1.1 christos /* Since tfind/tsearch manage a balanced tree, concurrent tfind and 581 1.1 christos tsearch calls can be fatal. */ 582 1.1 christos gl_rwlock_rdlock (tree_lock); 583 1.1 christos 584 1.1 christos foundp = (struct known_translation_t **) tfind (search, &root, transcmp); 585 1.1 christos 586 1.1 christos gl_rwlock_unlock (tree_lock); 587 1.1 christos 588 1.1 christos freea (search); 589 1.1 christos if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr) 590 1.1 christos { 591 1.1 christos /* Now deal with plural. */ 592 1.1 christos if (plural) 593 1.1 christos retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation, 594 1.1 christos (*foundp)->translation_length); 595 1.1 christos else 596 1.1 christos retval = (char *) (*foundp)->translation; 597 1.1 christos 598 1.1 christos gl_rwlock_unlock (_nl_state_lock); 599 1.1 christos return retval; 600 1.1 christos } 601 1.1 christos #endif 602 1.1 christos 603 1.1 christos /* Preserve the `errno' value. */ 604 1.1 christos saved_errno = errno; 605 1.1 christos 606 1.1 christos /* See whether this is a SUID binary or not. */ 607 1.1 christos DETERMINE_SECURE; 608 1.1 christos 609 1.1 christos /* First find matching binding. */ 610 1.1 christos #ifdef IN_LIBGLOCALE 611 1.1 christos /* We can use a trivial binding, since _nl_find_msg will ignore it anyway, 612 1.1 christos and _nl_load_domain and _nl_find_domain just pass it through. */ 613 1.1 christos binding = NULL; 614 1.1 christos dirname = bindtextdomain (domainname, NULL); 615 1.1 christos #else 616 1.1 christos for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) 617 1.1 christos { 618 1.1 christos int compare = strcmp (domainname, binding->domainname); 619 1.1 christos if (compare == 0) 620 1.1 christos /* We found it! */ 621 1.1 christos break; 622 1.1 christos if (compare < 0) 623 1.1 christos { 624 1.1 christos /* It is not in the list. */ 625 1.1 christos binding = NULL; 626 1.1 christos break; 627 1.1 christos } 628 1.1 christos } 629 1.1 christos 630 1.1 christos if (binding == NULL) 631 1.1 christos dirname = _nl_default_dirname; 632 1.1 christos else 633 1.1 christos { 634 1.1 christos dirname = binding->dirname; 635 1.1 christos #endif 636 1.1 christos if (!IS_ABSOLUTE_PATH (dirname)) 637 1.1 christos { 638 1.1 christos /* We have a relative path. Make it absolute now. */ 639 1.1 christos size_t dirname_len = strlen (dirname) + 1; 640 1.1 christos size_t path_max; 641 1.1 christos char *resolved_dirname; 642 1.1 christos char *ret; 643 1.1 christos 644 1.1 christos path_max = (unsigned int) PATH_MAX; 645 1.1 christos path_max += 2; /* The getcwd docs say to do this. */ 646 1.1 christos 647 1.1 christos for (;;) 648 1.1 christos { 649 1.1 christos resolved_dirname = (char *) alloca (path_max + dirname_len); 650 1.1 christos ADD_BLOCK (block_list, tmp_dirname); 651 1.1 christos 652 1.1 christos __set_errno (0); 653 1.1 christos ret = getcwd (resolved_dirname, path_max); 654 1.1 christos if (ret != NULL || errno != ERANGE) 655 1.1 christos break; 656 1.1 christos 657 1.1 christos path_max += path_max / 2; 658 1.1 christos path_max += PATH_INCR; 659 1.1 christos } 660 1.1 christos 661 1.1 christos if (ret == NULL) 662 1.1 christos /* We cannot get the current working directory. Don't signal an 663 1.1 christos error but simply return the default string. */ 664 1.1 christos goto return_untranslated; 665 1.1 christos 666 1.1 christos stpcpy (stpcpy (strchr (resolved_dirname, '\0'), "/"), dirname); 667 1.1 christos dirname = resolved_dirname; 668 1.1 christos } 669 1.1 christos #ifndef IN_LIBGLOCALE 670 1.1 christos } 671 1.1 christos #endif 672 1.1 christos 673 1.1 christos /* Now determine the symbolic name of CATEGORY and its value. */ 674 1.1 christos categoryname = category_to_name (category); 675 1.1 christos #ifdef IN_LIBGLOCALE 676 1.1 christos categoryvalue = guess_category_value (category, categoryname, localename); 677 1.1 christos #else 678 1.1 christos categoryvalue = guess_category_value (category, categoryname); 679 1.1 christos #endif 680 1.1 christos 681 1.1 christos domainname_len = strlen (domainname); 682 1.1 christos xdomainname = (char *) alloca (strlen (categoryname) 683 1.1 christos + domainname_len + 5); 684 1.1 christos ADD_BLOCK (block_list, xdomainname); 685 1.1 christos 686 1.1 christos stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"), 687 1.1 christos domainname, domainname_len), 688 1.1 christos ".mo"); 689 1.1 christos 690 1.1 christos /* Creating working area. */ 691 1.1 christos single_locale = (char *) alloca (strlen (categoryvalue) + 1); 692 1.1 christos ADD_BLOCK (block_list, single_locale); 693 1.1 christos 694 1.1 christos 695 1.1 christos /* Search for the given string. This is a loop because we perhaps 696 1.1 christos got an ordered list of languages to consider for the translation. */ 697 1.1 christos while (1) 698 1.1 christos { 699 1.1 christos /* Make CATEGORYVALUE point to the next element of the list. */ 700 1.1 christos while (categoryvalue[0] != '\0' && categoryvalue[0] == ':') 701 1.1 christos ++categoryvalue; 702 1.1 christos if (categoryvalue[0] == '\0') 703 1.1 christos { 704 1.1 christos /* The whole contents of CATEGORYVALUE has been searched but 705 1.1 christos no valid entry has been found. We solve this situation 706 1.1 christos by implicitly appending a "C" entry, i.e. no translation 707 1.1 christos will take place. */ 708 1.1 christos single_locale[0] = 'C'; 709 1.1 christos single_locale[1] = '\0'; 710 1.1 christos } 711 1.1 christos else 712 1.1 christos { 713 1.1 christos char *cp = single_locale; 714 1.1 christos while (categoryvalue[0] != '\0' && categoryvalue[0] != ':') 715 1.1 christos *cp++ = *categoryvalue++; 716 1.1 christos *cp = '\0'; 717 1.1 christos 718 1.1 christos /* When this is a SUID binary we must not allow accessing files 719 1.1 christos outside the dedicated directories. */ 720 1.1 christos if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale)) 721 1.1 christos /* Ingore this entry. */ 722 1.1 christos continue; 723 1.1 christos } 724 1.1 christos 725 1.1 christos /* If the current locale value is C (or POSIX) we don't load a 726 1.1 christos domain. Return the MSGID. */ 727 1.1 christos if (strcmp (single_locale, "C") == 0 728 1.1 christos || strcmp (single_locale, "POSIX") == 0) 729 1.1 christos break; 730 1.1 christos 731 1.1 christos /* Find structure describing the message catalog matching the 732 1.1 christos DOMAINNAME and CATEGORY. */ 733 1.1 christos domain = _nl_find_domain (dirname, single_locale, xdomainname, binding); 734 1.1 christos 735 1.1 christos if (domain != NULL) 736 1.1 christos { 737 1.1 christos #if defined IN_LIBGLOCALE 738 1.1 christos retval = _nl_find_msg (domain, binding, encoding, msgid1, &retlen); 739 1.1 christos #else 740 1.1 christos retval = _nl_find_msg (domain, binding, msgid1, 1, &retlen); 741 1.1 christos #endif 742 1.1 christos 743 1.1 christos if (retval == NULL) 744 1.1 christos { 745 1.1 christos int cnt; 746 1.1 christos 747 1.1 christos for (cnt = 0; domain->successor[cnt] != NULL; ++cnt) 748 1.1 christos { 749 1.1 christos #if defined IN_LIBGLOCALE 750 1.1 christos retval = _nl_find_msg (domain->successor[cnt], binding, 751 1.1 christos encoding, msgid1, &retlen); 752 1.1 christos #else 753 1.1 christos retval = _nl_find_msg (domain->successor[cnt], binding, 754 1.1 christos msgid1, 1, &retlen); 755 1.1 christos #endif 756 1.1 christos 757 1.1 christos if (retval != NULL) 758 1.1 christos { 759 1.1 christos domain = domain->successor[cnt]; 760 1.1 christos break; 761 1.1 christos } 762 1.1 christos } 763 1.1 christos } 764 1.1 christos 765 1.1 christos /* Returning -1 means that some resource problem exists 766 1.1 christos (likely memory) and that the strings could not be 767 1.1 christos converted. Return the original strings. */ 768 1.1 christos if (__builtin_expect (retval == (char *) -1, 0)) 769 1.1 christos break; 770 1.1 christos 771 1.1 christos if (retval != NULL) 772 1.1 christos { 773 1.1 christos /* Found the translation of MSGID1 in domain DOMAIN: 774 1.1 christos starting at RETVAL, RETLEN bytes. */ 775 1.1 christos FREE_BLOCKS (block_list); 776 1.1 christos #if defined HAVE_TSEARCH || defined _LIBC 777 1.1 christos if (foundp == NULL) 778 1.1 christos { 779 1.1 christos /* Create a new entry and add it to the search tree. */ 780 1.1 christos size_t size; 781 1.1 christos struct known_translation_t *newp; 782 1.1 christos 783 1.1 christos size = offsetof (struct known_translation_t, msgid) 784 1.1 christos + msgid_len + domainname_len + 1; 785 1.1 christos # ifdef HAVE_PER_THREAD_LOCALE 786 1.1 christos size += strlen (localename) + 1; 787 1.1 christos # endif 788 1.1 christos newp = (struct known_translation_t *) malloc (size); 789 1.1 christos if (newp != NULL) 790 1.1 christos { 791 1.1 christos char *new_domainname; 792 1.1 christos # ifdef HAVE_PER_THREAD_LOCALE 793 1.1 christos char *new_localename; 794 1.1 christos # endif 795 1.1 christos 796 1.1 christos new_domainname = mempcpy (newp->msgid, msgid1, msgid_len); 797 1.1 christos memcpy (new_domainname, domainname, domainname_len + 1); 798 1.1 christos # ifdef HAVE_PER_THREAD_LOCALE 799 1.1 christos new_localename = new_domainname + domainname_len + 1; 800 1.1 christos strcpy (new_localename, localename); 801 1.1 christos # endif 802 1.1 christos newp->domainname = new_domainname; 803 1.1 christos newp->category = category; 804 1.1 christos # ifdef HAVE_PER_THREAD_LOCALE 805 1.1 christos newp->localename = new_localename; 806 1.1 christos # endif 807 1.1 christos # ifdef IN_LIBGLOCALE 808 1.1 christos newp->encoding = encoding; 809 1.1 christos # endif 810 1.1 christos newp->counter = _nl_msg_cat_cntr; 811 1.1 christos newp->domain = domain; 812 1.1 christos newp->translation = retval; 813 1.1 christos newp->translation_length = retlen; 814 1.1 christos 815 1.1 christos gl_rwlock_wrlock (tree_lock); 816 1.1 christos 817 1.1 christos /* Insert the entry in the search tree. */ 818 1.1 christos foundp = (struct known_translation_t **) 819 1.1 christos tsearch (newp, &root, transcmp); 820 1.1 christos 821 1.1 christos gl_rwlock_unlock (tree_lock); 822 1.1 christos 823 1.1 christos if (foundp == NULL 824 1.1 christos || __builtin_expect (*foundp != newp, 0)) 825 1.1 christos /* The insert failed. */ 826 1.1 christos free (newp); 827 1.1 christos } 828 1.1 christos } 829 1.1 christos else 830 1.1 christos { 831 1.1 christos /* We can update the existing entry. */ 832 1.1 christos (*foundp)->counter = _nl_msg_cat_cntr; 833 1.1 christos (*foundp)->domain = domain; 834 1.1 christos (*foundp)->translation = retval; 835 1.1 christos (*foundp)->translation_length = retlen; 836 1.1 christos } 837 1.1 christos #endif 838 1.1 christos __set_errno (saved_errno); 839 1.1 christos 840 1.1 christos /* Now deal with plural. */ 841 1.1 christos if (plural) 842 1.1 christos retval = plural_lookup (domain, n, retval, retlen); 843 1.1 christos 844 1.1 christos gl_rwlock_unlock (_nl_state_lock); 845 1.1 christos return retval; 846 1.1 christos } 847 1.1 christos } 848 1.1 christos } 849 1.1 christos 850 1.1 christos return_untranslated: 851 1.1 christos /* Return the untranslated MSGID. */ 852 1.1 christos FREE_BLOCKS (block_list); 853 1.1 christos gl_rwlock_unlock (_nl_state_lock); 854 1.1 christos #ifndef _LIBC 855 1.1 christos if (!ENABLE_SECURE) 856 1.1 christos { 857 1.1 christos extern void _nl_log_untranslated (const char *logfilename, 858 1.1 christos const char *domainname, 859 1.1 christos const char *msgid1, const char *msgid2, 860 1.1 christos int plural); 861 1.1 christos const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED"); 862 1.1 christos 863 1.1 christos if (logfilename != NULL && logfilename[0] != '\0') 864 1.1 christos _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural); 865 1.1 christos } 866 1.1 christos #endif 867 1.1 christos __set_errno (saved_errno); 868 1.1 christos return (plural == 0 869 1.1 christos ? (char *) msgid1 870 1.1 christos /* Use the Germanic plural rule. */ 871 1.1 christos : n == 1 ? (char *) msgid1 : (char *) msgid2); 872 1.1 christos } 873 1.1 christos 874 1.1 christos 875 1.1 christos /* Look up the translation of msgid within DOMAIN_FILE and DOMAINBINDING. 876 1.1 christos Return it if found. Return NULL if not found or in case of a conversion 877 1.1 christos failure (problem in the particular message catalog). Return (char *) -1 878 1.1 christos in case of a memory allocation failure during conversion (only if 879 1.1 christos ENCODING != NULL resp. CONVERT == true). */ 880 1.1 christos char * 881 1.1 christos internal_function 882 1.1 christos #ifdef IN_LIBGLOCALE 883 1.1 christos _nl_find_msg (struct loaded_l10nfile *domain_file, 884 1.1 christos struct binding *domainbinding, const char *encoding, 885 1.1 christos const char *msgid, 886 1.1 christos size_t *lengthp) 887 1.1 christos #else 888 1.1 christos _nl_find_msg (struct loaded_l10nfile *domain_file, 889 1.1 christos struct binding *domainbinding, 890 1.1 christos const char *msgid, int convert, 891 1.1 christos size_t *lengthp) 892 1.1 christos #endif 893 1.1 christos { 894 1.1 christos struct loaded_domain *domain; 895 1.1 christos nls_uint32 nstrings; 896 1.1 christos size_t act; 897 1.1 christos char *result; 898 1.1 christos size_t resultlen; 899 1.1 christos 900 1.1 christos if (domain_file->decided <= 0) 901 1.1 christos _nl_load_domain (domain_file, domainbinding); 902 1.1 christos 903 1.1 christos if (domain_file->data == NULL) 904 1.1 christos return NULL; 905 1.1 christos 906 1.1 christos domain = (struct loaded_domain *) domain_file->data; 907 1.1 christos 908 1.1 christos nstrings = domain->nstrings; 909 1.1 christos 910 1.1 christos /* Locate the MSGID and its translation. */ 911 1.1 christos if (domain->hash_tab != NULL) 912 1.1 christos { 913 1.1 christos /* Use the hashing table. */ 914 1.1 christos nls_uint32 len = strlen (msgid); 915 1.1 christos nls_uint32 hash_val = __hash_string (msgid); 916 1.1 christos nls_uint32 idx = hash_val % domain->hash_size; 917 1.1 christos nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2)); 918 1.1 christos 919 1.1 christos while (1) 920 1.1 christos { 921 1.1 christos nls_uint32 nstr = 922 1.1 christos W (domain->must_swap_hash_tab, domain->hash_tab[idx]); 923 1.1 christos 924 1.1 christos if (nstr == 0) 925 1.1 christos /* Hash table entry is empty. */ 926 1.1 christos return NULL; 927 1.1 christos 928 1.1 christos nstr--; 929 1.1 christos 930 1.1 christos /* Compare msgid with the original string at index nstr. 931 1.1 christos We compare the lengths with >=, not ==, because plural entries 932 1.1 christos are represented by strings with an embedded NUL. */ 933 1.1 christos if (nstr < nstrings 934 1.1 christos ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len 935 1.1 christos && (strcmp (msgid, 936 1.1 christos domain->data + W (domain->must_swap, 937 1.1 christos domain->orig_tab[nstr].offset)) 938 1.1 christos == 0) 939 1.1 christos : domain->orig_sysdep_tab[nstr - nstrings].length > len 940 1.1 christos && (strcmp (msgid, 941 1.1 christos domain->orig_sysdep_tab[nstr - nstrings].pointer) 942 1.1 christos == 0)) 943 1.1 christos { 944 1.1 christos act = nstr; 945 1.1 christos goto found; 946 1.1 christos } 947 1.1 christos 948 1.1 christos if (idx >= domain->hash_size - incr) 949 1.1 christos idx -= domain->hash_size - incr; 950 1.1 christos else 951 1.1 christos idx += incr; 952 1.1 christos } 953 1.1 christos /* NOTREACHED */ 954 1.1 christos } 955 1.1 christos else 956 1.1 christos { 957 1.1 christos /* Try the default method: binary search in the sorted array of 958 1.1 christos messages. */ 959 1.1 christos size_t top, bottom; 960 1.1 christos 961 1.1 christos bottom = 0; 962 1.1 christos top = nstrings; 963 1.1 christos while (bottom < top) 964 1.1 christos { 965 1.1 christos int cmp_val; 966 1.1 christos 967 1.1 christos act = (bottom + top) / 2; 968 1.1 christos cmp_val = strcmp (msgid, (domain->data 969 1.1 christos + W (domain->must_swap, 970 1.1 christos domain->orig_tab[act].offset))); 971 1.1 christos if (cmp_val < 0) 972 1.1 christos top = act; 973 1.1 christos else if (cmp_val > 0) 974 1.1 christos bottom = act + 1; 975 1.1 christos else 976 1.1 christos goto found; 977 1.1 christos } 978 1.1 christos /* No translation was found. */ 979 1.1 christos return NULL; 980 1.1 christos } 981 1.1 christos 982 1.1 christos found: 983 1.1 christos /* The translation was found at index ACT. If we have to convert the 984 1.1 christos string to use a different character set, this is the time. */ 985 1.1 christos if (act < nstrings) 986 1.1 christos { 987 1.1 christos result = (char *) 988 1.1 christos (domain->data + W (domain->must_swap, domain->trans_tab[act].offset)); 989 1.1 christos resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1; 990 1.1 christos } 991 1.1 christos else 992 1.1 christos { 993 1.1 christos result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer; 994 1.1 christos resultlen = domain->trans_sysdep_tab[act - nstrings].length; 995 1.1 christos } 996 1.1 christos 997 1.1 christos #if defined _LIBC || HAVE_ICONV 998 1.1 christos # ifdef IN_LIBGLOCALE 999 1.1 christos if (encoding != NULL) 1000 1.1 christos # else 1001 1.1 christos if (convert) 1002 1.1 christos # endif 1003 1.1 christos { 1004 1.1 christos /* We are supposed to do a conversion. */ 1005 1.1 christos # ifndef IN_LIBGLOCALE 1006 1.1 christos const char *encoding = get_output_charset (domainbinding); 1007 1.1 christos # endif 1008 1.1 christos 1009 1.1 christos /* Search whether a table with converted translations for this 1010 1.1 christos encoding has already been allocated. */ 1011 1.1 christos size_t nconversions = domain->nconversions; 1012 1.1 christos struct converted_domain *convd = NULL; 1013 1.1 christos size_t i; 1014 1.1 christos 1015 1.1 christos for (i = nconversions; i > 0; ) 1016 1.1 christos { 1017 1.1 christos i--; 1018 1.1 christos if (strcmp (domain->conversions[i].encoding, encoding) == 0) 1019 1.1 christos { 1020 1.1 christos convd = &domain->conversions[i]; 1021 1.1 christos break; 1022 1.1 christos } 1023 1.1 christos } 1024 1.1 christos 1025 1.1 christos if (convd == NULL) 1026 1.1 christos { 1027 1.1 christos /* Allocate a table for the converted translations for this 1028 1.1 christos encoding. */ 1029 1.1 christos struct converted_domain *new_conversions = 1030 1.1 christos (struct converted_domain *) 1031 1.1 christos (domain->conversions != NULL 1032 1.1 christos ? realloc (domain->conversions, 1033 1.1 christos (nconversions + 1) * sizeof (struct converted_domain)) 1034 1.1 christos : malloc ((nconversions + 1) * sizeof (struct converted_domain))); 1035 1.1 christos 1036 1.1 christos if (__builtin_expect (new_conversions == NULL, 0)) 1037 1.1 christos /* Nothing we can do, no more memory. We cannot use the 1038 1.1 christos translation because it might be encoded incorrectly. */ 1039 1.1 christos return (char *) -1; 1040 1.1 christos 1041 1.1 christos domain->conversions = new_conversions; 1042 1.1 christos 1043 1.1 christos /* Copy the 'encoding' string to permanent storage. */ 1044 1.1 christos encoding = strdup (encoding); 1045 1.1 christos if (__builtin_expect (encoding == NULL, 0)) 1046 1.1 christos /* Nothing we can do, no more memory. We cannot use the 1047 1.1 christos translation because it might be encoded incorrectly. */ 1048 1.1 christos return (char *) -1; 1049 1.1 christos 1050 1.1 christos convd = &new_conversions[nconversions]; 1051 1.1 christos convd->encoding = encoding; 1052 1.1 christos 1053 1.1 christos /* Find out about the character set the file is encoded with. 1054 1.1 christos This can be found (in textual form) in the entry "". If this 1055 1.1 christos entry does not exist or if this does not contain the 'charset=' 1056 1.1 christos information, we will assume the charset matches the one the 1057 1.1 christos current locale and we don't have to perform any conversion. */ 1058 1.1 christos # ifdef _LIBC 1059 1.1 christos convd->conv = (__gconv_t) -1; 1060 1.1 christos # else 1061 1.1 christos # if HAVE_ICONV 1062 1.1 christos convd->conv = (iconv_t) -1; 1063 1.1 christos # endif 1064 1.1 christos # endif 1065 1.1 christos { 1066 1.1 christos char *nullentry; 1067 1.1 christos size_t nullentrylen; 1068 1.1 christos 1069 1.1 christos /* Get the header entry. This is a recursion, but it doesn't 1070 1.1 christos reallocate domain->conversions because we pass 1071 1.1 christos encoding = NULL or convert = 0, respectively. */ 1072 1.1 christos nullentry = 1073 1.1 christos # ifdef IN_LIBGLOCALE 1074 1.1 christos _nl_find_msg (domain_file, domainbinding, NULL, "", 1075 1.1 christos &nullentrylen); 1076 1.1 christos # else 1077 1.1 christos _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen); 1078 1.1 christos # endif 1079 1.1 christos 1080 1.1 christos if (nullentry != NULL) 1081 1.1 christos { 1082 1.1 christos const char *charsetstr; 1083 1.1 christos 1084 1.1 christos charsetstr = strstr (nullentry, "charset="); 1085 1.1 christos if (charsetstr != NULL) 1086 1.1 christos { 1087 1.1 christos size_t len; 1088 1.1 christos char *charset; 1089 1.1 christos const char *outcharset; 1090 1.1 christos 1091 1.1 christos charsetstr += strlen ("charset="); 1092 1.1 christos len = strcspn (charsetstr, " \t\n"); 1093 1.1 christos 1094 1.1 christos charset = (char *) alloca (len + 1); 1095 1.1 christos # if defined _LIBC || HAVE_MEMPCPY 1096 1.1 christos *((char *) mempcpy (charset, charsetstr, len)) = '\0'; 1097 1.1 christos # else 1098 1.1 christos memcpy (charset, charsetstr, len); 1099 1.1 christos charset[len] = '\0'; 1100 1.1 christos # endif 1101 1.1 christos 1102 1.1 christos outcharset = encoding; 1103 1.1 christos 1104 1.1 christos # ifdef _LIBC 1105 1.1 christos /* We always want to use transliteration. */ 1106 1.1 christos outcharset = norm_add_slashes (outcharset, "TRANSLIT"); 1107 1.1 christos charset = norm_add_slashes (charset, ""); 1108 1.1 christos int r = __gconv_open (outcharset, charset, &convd->conv, 1109 1.1 christos GCONV_AVOID_NOCONV); 1110 1.1 christos if (__builtin_expect (r != __GCONV_OK, 0)) 1111 1.1 christos { 1112 1.1 christos /* If the output encoding is the same there is 1113 1.1 christos nothing to do. Otherwise do not use the 1114 1.1 christos translation at all. */ 1115 1.1 christos if (__builtin_expect (r != __GCONV_NOCONV, 1)) 1116 1.1 christos return NULL; 1117 1.1 christos 1118 1.1 christos convd->conv = (__gconv_t) -1; 1119 1.1 christos } 1120 1.1 christos # else 1121 1.1 christos # if HAVE_ICONV 1122 1.1 christos /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5, 1123 1.1 christos we want to use transliteration. */ 1124 1.1 christos # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \ 1125 1.1 christos || _LIBICONV_VERSION >= 0x0105 1126 1.1 christos if (strchr (outcharset, '/') == NULL) 1127 1.1 christos { 1128 1.1 christos char *tmp; 1129 1.1 christos 1130 1.1 christos len = strlen (outcharset); 1131 1.1 christos tmp = (char *) alloca (len + 10 + 1); 1132 1.1 christos memcpy (tmp, outcharset, len); 1133 1.1 christos memcpy (tmp + len, "//TRANSLIT", 10 + 1); 1134 1.1 christos outcharset = tmp; 1135 1.1 christos 1136 1.1 christos convd->conv = iconv_open (outcharset, charset); 1137 1.1 christos 1138 1.1 christos freea (outcharset); 1139 1.1 christos } 1140 1.1 christos else 1141 1.1 christos # endif 1142 1.1 christos convd->conv = iconv_open (outcharset, charset); 1143 1.1 christos # endif 1144 1.1 christos # endif 1145 1.1 christos 1146 1.1 christos freea (charset); 1147 1.1 christos } 1148 1.1 christos } 1149 1.1 christos } 1150 1.1 christos convd->conv_tab = NULL; 1151 1.1 christos /* Here domain->conversions is still == new_conversions. */ 1152 1.1 christos domain->nconversions++; 1153 1.1 christos } 1154 1.1 christos 1155 1.1 christos if ( 1156 1.1 christos # ifdef _LIBC 1157 1.1 christos convd->conv != (__gconv_t) -1 1158 1.1 christos # else 1159 1.1 christos # if HAVE_ICONV 1160 1.1 christos convd->conv != (iconv_t) -1 1161 1.1 christos # endif 1162 1.1 christos # endif 1163 1.1 christos ) 1164 1.1 christos { 1165 1.1 christos /* We are supposed to do a conversion. First allocate an 1166 1.1 christos appropriate table with the same structure as the table 1167 1.1 christos of translations in the file, where we can put the pointers 1168 1.1 christos to the converted strings in. 1169 1.1 christos There is a slight complication with plural entries. They 1170 1.1 christos are represented by consecutive NUL terminated strings. We 1171 1.1 christos handle this case by converting RESULTLEN bytes, including 1172 1.1 christos NULs. */ 1173 1.1 christos 1174 1.1 christos if (convd->conv_tab == NULL 1175 1.1 christos && ((convd->conv_tab = 1176 1.1 christos (char **) calloc (nstrings + domain->n_sysdep_strings, 1177 1.1 christos sizeof (char *))) 1178 1.1 christos == NULL)) 1179 1.1 christos /* Mark that we didn't succeed allocating a table. */ 1180 1.1 christos convd->conv_tab = (char **) -1; 1181 1.1 christos 1182 1.1 christos if (__builtin_expect (convd->conv_tab == (char **) -1, 0)) 1183 1.1 christos /* Nothing we can do, no more memory. We cannot use the 1184 1.1 christos translation because it might be encoded incorrectly. */ 1185 1.1 christos return (char *) -1; 1186 1.1 christos 1187 1.1 christos if (convd->conv_tab[act] == NULL) 1188 1.1 christos { 1189 1.1 christos /* We haven't used this string so far, so it is not 1190 1.1 christos translated yet. Do this now. */ 1191 1.1 christos /* We use a bit more efficient memory handling. 1192 1.1 christos We allocate always larger blocks which get used over 1193 1.1 christos time. This is faster than many small allocations. */ 1194 1.1 christos __libc_lock_define_initialized (static, lock) 1195 1.1 christos # define INITIAL_BLOCK_SIZE 4080 1196 1.1 christos static unsigned char *freemem; 1197 1.1 christos static size_t freemem_size; 1198 1.1 christos 1199 1.1 christos const unsigned char *inbuf; 1200 1.1 christos unsigned char *outbuf; 1201 1.1 christos int malloc_count; 1202 1.1 christos # ifndef _LIBC 1203 1.1 christos transmem_block_t *transmem_list = NULL; 1204 1.1 christos # endif 1205 1.1 christos 1206 1.1 christos __libc_lock_lock (lock); 1207 1.1 christos 1208 1.1 christos inbuf = (const unsigned char *) result; 1209 1.1 christos outbuf = freemem + sizeof (size_t); 1210 1.1 christos 1211 1.1 christos malloc_count = 0; 1212 1.1 christos while (1) 1213 1.1 christos { 1214 1.1 christos transmem_block_t *newmem; 1215 1.1 christos # ifdef _LIBC 1216 1.1 christos size_t non_reversible; 1217 1.1 christos int res; 1218 1.1 christos 1219 1.1 christos if (freemem_size < sizeof (size_t)) 1220 1.1 christos goto resize_freemem; 1221 1.1 christos 1222 1.1 christos res = __gconv (convd->conv, 1223 1.1 christos &inbuf, inbuf + resultlen, 1224 1.1 christos &outbuf, 1225 1.1 christos outbuf + freemem_size - sizeof (size_t), 1226 1.1 christos &non_reversible); 1227 1.1 christos 1228 1.1 christos if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT) 1229 1.1 christos break; 1230 1.1 christos 1231 1.1 christos if (res != __GCONV_FULL_OUTPUT) 1232 1.1 christos { 1233 1.1 christos /* We should not use the translation at all, it 1234 1.1 christos is incorrectly encoded. */ 1235 1.1 christos __libc_lock_unlock (lock); 1236 1.1 christos return NULL; 1237 1.1 christos } 1238 1.1 christos 1239 1.1 christos inbuf = (const unsigned char *) result; 1240 1.1 christos # else 1241 1.1 christos # if HAVE_ICONV 1242 1.1 christos const char *inptr = (const char *) inbuf; 1243 1.1 christos size_t inleft = resultlen; 1244 1.1 christos char *outptr = (char *) outbuf; 1245 1.1 christos size_t outleft; 1246 1.1 christos 1247 1.1 christos if (freemem_size < sizeof (size_t)) 1248 1.1 christos goto resize_freemem; 1249 1.1 christos 1250 1.1 christos outleft = freemem_size - sizeof (size_t); 1251 1.1 christos if (iconv (convd->conv, 1252 1.1 christos (ICONV_CONST char **) &inptr, &inleft, 1253 1.1 christos &outptr, &outleft) 1254 1.1 christos != (size_t) (-1)) 1255 1.1 christos { 1256 1.1 christos outbuf = (unsigned char *) outptr; 1257 1.1 christos break; 1258 1.1 christos } 1259 1.1 christos if (errno != E2BIG) 1260 1.1 christos { 1261 1.1 christos __libc_lock_unlock (lock); 1262 1.1 christos return NULL; 1263 1.1 christos } 1264 1.1 christos # endif 1265 1.1 christos # endif 1266 1.1 christos 1267 1.1 christos resize_freemem: 1268 1.1 christos /* We must allocate a new buffer or resize the old one. */ 1269 1.1 christos if (malloc_count > 0) 1270 1.1 christos { 1271 1.1 christos ++malloc_count; 1272 1.1 christos freemem_size = malloc_count * INITIAL_BLOCK_SIZE; 1273 1.1 christos newmem = (transmem_block_t *) realloc (transmem_list, 1274 1.1 christos freemem_size); 1275 1.1 christos # ifdef _LIBC 1276 1.1 christos if (newmem != NULL) 1277 1.1 christos transmem_list = transmem_list->next; 1278 1.1 christos else 1279 1.1 christos { 1280 1.1 christos struct transmem_list *old = transmem_list; 1281 1.1 christos 1282 1.1 christos transmem_list = transmem_list->next; 1283 1.1 christos free (old); 1284 1.1 christos } 1285 1.1 christos # endif 1286 1.1 christos } 1287 1.1 christos else 1288 1.1 christos { 1289 1.1 christos malloc_count = 1; 1290 1.1 christos freemem_size = INITIAL_BLOCK_SIZE; 1291 1.1 christos newmem = (transmem_block_t *) malloc (freemem_size); 1292 1.1 christos } 1293 1.1 christos if (__builtin_expect (newmem == NULL, 0)) 1294 1.1 christos { 1295 1.1 christos freemem = NULL; 1296 1.1 christos freemem_size = 0; 1297 1.1 christos __libc_lock_unlock (lock); 1298 1.1 christos return (char *) -1; 1299 1.1 christos } 1300 1.1 christos 1301 1.1 christos # ifdef _LIBC 1302 1.1 christos /* Add the block to the list of blocks we have to free 1303 1.1 christos at some point. */ 1304 1.1 christos newmem->next = transmem_list; 1305 1.1 christos transmem_list = newmem; 1306 1.1 christos 1307 1.1 christos freemem = (unsigned char *) newmem->data; 1308 1.1 christos freemem_size -= offsetof (struct transmem_list, data); 1309 1.1 christos # else 1310 1.1 christos transmem_list = newmem; 1311 1.1 christos freemem = newmem; 1312 1.1 christos # endif 1313 1.1 christos 1314 1.1 christos outbuf = freemem + sizeof (size_t); 1315 1.1 christos } 1316 1.1 christos 1317 1.1 christos /* We have now in our buffer a converted string. Put this 1318 1.1 christos into the table of conversions. */ 1319 1.1 christos *(size_t *) freemem = outbuf - freemem - sizeof (size_t); 1320 1.1 christos convd->conv_tab[act] = (char *) freemem; 1321 1.1 christos /* Shrink freemem, but keep it aligned. */ 1322 1.1 christos freemem_size -= outbuf - freemem; 1323 1.1 christos freemem = outbuf; 1324 1.1 christos freemem += freemem_size & (alignof (size_t) - 1); 1325 1.1 christos freemem_size = freemem_size & ~ (alignof (size_t) - 1); 1326 1.1 christos 1327 1.1 christos __libc_lock_unlock (lock); 1328 1.1 christos } 1329 1.1 christos 1330 1.1 christos /* Now convd->conv_tab[act] contains the translation of all 1331 1.1 christos the plural variants. */ 1332 1.1 christos result = convd->conv_tab[act] + sizeof (size_t); 1333 1.1 christos resultlen = *(size_t *) convd->conv_tab[act]; 1334 1.1 christos } 1335 1.1 christos } 1336 1.1 christos 1337 1.1 christos /* The result string is converted. */ 1338 1.1 christos 1339 1.1 christos #endif /* _LIBC || HAVE_ICONV */ 1340 1.1 christos 1341 1.1 christos *lengthp = resultlen; 1342 1.1 christos return result; 1343 1.1 christos } 1344 1.1 christos 1345 1.1 christos 1346 1.1 christos /* Look up a plural variant. */ 1347 1.1 christos static char * 1348 1.1 christos internal_function 1349 1.1 christos plural_lookup (struct loaded_l10nfile *domain, unsigned long int n, 1350 1.1 christos const char *translation, size_t translation_len) 1351 1.1 christos { 1352 1.1 christos struct loaded_domain *domaindata = (struct loaded_domain *) domain->data; 1353 1.1 christos unsigned long int index; 1354 1.1 christos const char *p; 1355 1.1 christos 1356 1.1 christos index = plural_eval (domaindata->plural, n); 1357 1.1 christos if (index >= domaindata->nplurals) 1358 1.1 christos /* This should never happen. It means the plural expression and the 1359 1.1 christos given maximum value do not match. */ 1360 1.1 christos index = 0; 1361 1.1 christos 1362 1.1 christos /* Skip INDEX strings at TRANSLATION. */ 1363 1.1 christos p = translation; 1364 1.1 christos while (index-- > 0) 1365 1.1 christos { 1366 1.1 christos #ifdef _LIBC 1367 1.1 christos p = __rawmemchr (p, '\0'); 1368 1.1 christos #else 1369 1.1 christos p = strchr (p, '\0'); 1370 1.1 christos #endif 1371 1.1 christos /* And skip over the NUL byte. */ 1372 1.1 christos p++; 1373 1.1 christos 1374 1.1 christos if (p >= translation + translation_len) 1375 1.1 christos /* This should never happen. It means the plural expression 1376 1.1 christos evaluated to a value larger than the number of variants 1377 1.1 christos available for MSGID1. */ 1378 1.1 christos return (char *) translation; 1379 1.1 christos } 1380 1.1 christos return (char *) p; 1381 1.1 christos } 1382 1.1 christos 1383 1.1 christos #ifndef _LIBC 1384 1.1 christos /* Return string representation of locale CATEGORY. */ 1385 1.1 christos static const char * 1386 1.1 christos internal_function 1387 1.1 christos category_to_name (int category) 1388 1.1 christos { 1389 1.1 christos const char *retval; 1390 1.1 christos 1391 1.1 christos switch (category) 1392 1.1 christos { 1393 1.1 christos #ifdef LC_COLLATE 1394 1.1 christos case LC_COLLATE: 1395 1.1 christos retval = "LC_COLLATE"; 1396 1.1 christos break; 1397 1.1 christos #endif 1398 1.1 christos #ifdef LC_CTYPE 1399 1.1 christos case LC_CTYPE: 1400 1.1 christos retval = "LC_CTYPE"; 1401 1.1 christos break; 1402 1.1 christos #endif 1403 1.1 christos #ifdef LC_MONETARY 1404 1.1 christos case LC_MONETARY: 1405 1.1 christos retval = "LC_MONETARY"; 1406 1.1 christos break; 1407 1.1 christos #endif 1408 1.1 christos #ifdef LC_NUMERIC 1409 1.1 christos case LC_NUMERIC: 1410 1.1 christos retval = "LC_NUMERIC"; 1411 1.1 christos break; 1412 1.1 christos #endif 1413 1.1 christos #ifdef LC_TIME 1414 1.1 christos case LC_TIME: 1415 1.1 christos retval = "LC_TIME"; 1416 1.1 christos break; 1417 1.1 christos #endif 1418 1.1 christos #ifdef LC_MESSAGES 1419 1.1 christos case LC_MESSAGES: 1420 1.1 christos retval = "LC_MESSAGES"; 1421 1.1 christos break; 1422 1.1 christos #endif 1423 1.1 christos #ifdef LC_RESPONSE 1424 1.1 christos case LC_RESPONSE: 1425 1.1 christos retval = "LC_RESPONSE"; 1426 1.1 christos break; 1427 1.1 christos #endif 1428 1.1 christos #ifdef LC_ALL 1429 1.1 christos case LC_ALL: 1430 1.1 christos /* This might not make sense but is perhaps better than any other 1431 1.1 christos value. */ 1432 1.1 christos retval = "LC_ALL"; 1433 1.1 christos break; 1434 1.1 christos #endif 1435 1.1 christos default: 1436 1.1 christos /* If you have a better idea for a default value let me know. */ 1437 1.1 christos retval = "LC_XXX"; 1438 1.1 christos } 1439 1.1 christos 1440 1.1 christos return retval; 1441 1.1 christos } 1442 1.1 christos #endif 1443 1.1 christos 1444 1.1 christos /* Guess value of current locale from value of the environment variables 1445 1.1 christos or system-dependent defaults. */ 1446 1.1 christos static const char * 1447 1.1 christos internal_function 1448 1.1 christos #ifdef IN_LIBGLOCALE 1449 1.1 christos guess_category_value (int category, const char *categoryname, 1450 1.1 christos const char *locale) 1451 1.1 christos 1452 1.1 christos #else 1453 1.1 christos guess_category_value (int category, const char *categoryname) 1454 1.1 christos #endif 1455 1.1 christos { 1456 1.1 christos const char *language; 1457 1.1 christos #ifndef IN_LIBGLOCALE 1458 1.1 christos const char *locale; 1459 1.1 christos # ifndef _LIBC 1460 1.1 christos const char *language_default; 1461 1.1 christos int locale_defaulted; 1462 1.1 christos # endif 1463 1.1 christos #endif 1464 1.1 christos 1465 1.1 christos /* We use the settings in the following order: 1466 1.1 christos 1. The value of the environment variable 'LANGUAGE'. This is a GNU 1467 1.1 christos extension. Its value can be a colon-separated list of locale names. 1468 1.1 christos 2. The value of the environment variable 'LC_ALL', 'LC_xxx', or 'LANG'. 1469 1.1 christos More precisely, the first among these that is set to a non-empty value. 1470 1.1 christos This is how POSIX specifies it. The value is a single locale name. 1471 1.1 christos 3. A system-dependent preference list of languages. Its value can be a 1472 1.1 christos colon-separated list of locale names. 1473 1.1 christos 4. A system-dependent default locale name. 1474 1.1 christos This way: 1475 1.1 christos - System-dependent settings can be overridden by environment variables. 1476 1.1 christos - If the system provides both a list of languages and a default locale, 1477 1.1 christos the former is used. */ 1478 1.1 christos 1479 1.1 christos #ifndef IN_LIBGLOCALE 1480 1.1 christos /* Fetch the locale name, through the POSIX method of looking to `LC_ALL', 1481 1.1 christos `LC_xxx', and `LANG'. On some systems this can be done by the 1482 1.1 christos `setlocale' function itself. */ 1483 1.1 christos # ifdef _LIBC 1484 1.1 christos locale = __current_locale_name (category); 1485 1.1 christos # else 1486 1.1 christos # if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS 1487 1.1 christos /* The __names field is not public glibc API and must therefore not be used 1488 1.1 christos in code that is installed in public locations. */ 1489 1.1 christos locale_t thread_locale = uselocale (NULL); 1490 1.1 christos if (thread_locale != LC_GLOBAL_LOCALE) 1491 1.1 christos { 1492 1.1 christos locale = thread_locale->__names[category]; 1493 1.1 christos locale_defaulted = 0; 1494 1.1 christos } 1495 1.1 christos else 1496 1.1 christos # endif 1497 1.1 christos { 1498 1.1 christos locale = _nl_locale_name_posix (category, categoryname); 1499 1.1 christos locale_defaulted = 0; 1500 1.1 christos if (locale == NULL) 1501 1.1 christos { 1502 1.1 christos locale = _nl_locale_name_default (); 1503 1.1 christos locale_defaulted = 1; 1504 1.1 christos } 1505 1.1 christos } 1506 1.1 christos # endif 1507 1.1 christos #endif 1508 1.1 christos 1509 1.1 christos /* Ignore LANGUAGE and its system-dependent analogon if the locale is set 1510 1.1 christos to "C" because 1511 1.1 christos 1. "C" locale usually uses the ASCII encoding, and most international 1512 1.1 christos messages use non-ASCII characters. These characters get displayed 1513 1.1 christos as question marks (if using glibc's iconv()) or as invalid 8-bit 1514 1.1 christos characters (because other iconv()s refuse to convert most non-ASCII 1515 1.1 christos characters to ASCII). In any case, the output is ugly. 1516 1.1 christos 2. The precise output of some programs in the "C" locale is specified 1517 1.1 christos by POSIX and should not depend on environment variables like 1518 1.1 christos "LANGUAGE" or system-dependent information. We allow such programs 1519 1.1 christos to use gettext(). */ 1520 1.1 christos if (strcmp (locale, "C") == 0) 1521 1.1 christos return locale; 1522 1.1 christos 1523 1.1 christos /* The highest priority value is the value of the 'LANGUAGE' environment 1524 1.1 christos variable. */ 1525 1.1 christos language = getenv ("LANGUAGE"); 1526 1.1 christos if (language != NULL && language[0] != '\0') 1527 1.1 christos return language; 1528 1.1 christos #if !defined IN_LIBGLOCALE && !defined _LIBC 1529 1.1 christos /* The next priority value is the locale name, if not defaulted. */ 1530 1.1 christos if (locale_defaulted) 1531 1.1 christos { 1532 1.1 christos /* The next priority value is the default language preferences list. */ 1533 1.1 christos language_default = _nl_language_preferences_default (); 1534 1.1 christos if (language_default != NULL) 1535 1.1 christos return language_default; 1536 1.1 christos } 1537 1.1 christos /* The least priority value is the locale name, if defaulted. */ 1538 1.1 christos #endif 1539 1.1 christos return locale; 1540 1.1 christos } 1541 1.1 christos 1542 1.1 christos #if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE 1543 1.1 christos /* Returns the output charset. */ 1544 1.1 christos static const char * 1545 1.1 christos internal_function 1546 1.1 christos get_output_charset (struct binding *domainbinding) 1547 1.1 christos { 1548 1.1 christos /* The output charset should normally be determined by the locale. But 1549 1.1 christos sometimes the locale is not used or not correctly set up, so we provide 1550 1.1 christos a possibility for the user to override this: the OUTPUT_CHARSET 1551 1.1 christos environment variable. Moreover, the value specified through 1552 1.1 christos bind_textdomain_codeset overrides both. */ 1553 1.1 christos if (domainbinding != NULL && domainbinding->codeset != NULL) 1554 1.1 christos return domainbinding->codeset; 1555 1.1 christos else 1556 1.1 christos { 1557 1.1 christos /* For speed reasons, we look at the value of OUTPUT_CHARSET only 1558 1.1 christos once. This is a user variable that is not supposed to change 1559 1.1 christos during a program run. */ 1560 1.1 christos static char *output_charset_cache; 1561 1.1 christos static int output_charset_cached; 1562 1.1 christos 1563 1.1 christos if (!output_charset_cached) 1564 1.1 christos { 1565 1.1 christos const char *value = getenv ("OUTPUT_CHARSET"); 1566 1.1 christos 1567 1.1 christos if (value != NULL && value[0] != '\0') 1568 1.1 christos { 1569 1.1 christos size_t len = strlen (value) + 1; 1570 1.1 christos char *value_copy = (char *) malloc (len); 1571 1.1 christos 1572 1.1 christos if (value_copy != NULL) 1573 1.1 christos memcpy (value_copy, value, len); 1574 1.1 christos output_charset_cache = value_copy; 1575 1.1 christos } 1576 1.1 christos output_charset_cached = 1; 1577 1.1 christos } 1578 1.1 christos 1579 1.1 christos if (output_charset_cache != NULL) 1580 1.1 christos return output_charset_cache; 1581 1.1 christos else 1582 1.1 christos { 1583 1.1 christos # ifdef _LIBC 1584 1.1 christos return _NL_CURRENT (LC_CTYPE, CODESET); 1585 1.1 christos # else 1586 1.1 christos # if HAVE_ICONV 1587 1.1 christos extern const char *locale_charset (void); 1588 1.1 christos return locale_charset (); 1589 1.1 christos # endif 1590 1.1 christos # endif 1591 1.1 christos } 1592 1.1 christos } 1593 1.1 christos } 1594 1.1 christos #endif 1595 1.1 christos 1596 1.1 christos /* @@ begin of epilog @@ */ 1597 1.1 christos 1598 1.1 christos /* We don't want libintl.a to depend on any other library. So we 1599 1.1 christos avoid the non-standard function stpcpy. In GNU C Library this 1600 1.1 christos function is available, though. Also allow the symbol HAVE_STPCPY 1601 1.1 christos to be defined. */ 1602 1.1 christos #if !_LIBC && !HAVE_STPCPY 1603 1.1 christos static char * 1604 1.1 christos stpcpy (char *dest, const char *src) 1605 1.1 christos { 1606 1.1 christos while ((*dest++ = *src++) != '\0') 1607 1.1 christos /* Do nothing. */ ; 1608 1.1 christos return dest - 1; 1609 1.1 christos } 1610 1.1 christos #endif 1611 1.1 christos 1612 1.1 christos #if !_LIBC && !HAVE_MEMPCPY 1613 1.1 christos static void * 1614 1.1 christos mempcpy (void *dest, const void *src, size_t n) 1615 1.1 christos { 1616 1.1 christos return (void *) ((char *) memcpy (dest, src, n) + n); 1617 1.1 christos } 1618 1.1 christos #endif 1619 1.1 christos 1620 1.1 christos 1621 1.1 christos #ifdef _LIBC 1622 1.1 christos /* If we want to free all resources we have to do some work at 1623 1.1 christos program's end. */ 1624 1.1 christos libc_freeres_fn (free_mem) 1625 1.1 christos { 1626 1.1 christos void *old; 1627 1.1 christos 1628 1.1 christos while (_nl_domain_bindings != NULL) 1629 1.1 christos { 1630 1.1 christos struct binding *oldp = _nl_domain_bindings; 1631 1.1 christos _nl_domain_bindings = _nl_domain_bindings->next; 1632 1.1 christos if (oldp->dirname != _nl_default_dirname) 1633 1.1 christos /* Yes, this is a pointer comparison. */ 1634 1.1 christos free (oldp->dirname); 1635 1.1 christos free (oldp->codeset); 1636 1.1 christos free (oldp); 1637 1.1 christos } 1638 1.1 christos 1639 1.1 christos if (_nl_current_default_domain != _nl_default_default_domain) 1640 1.1 christos /* Yes, again a pointer comparison. */ 1641 1.1 christos free ((char *) _nl_current_default_domain); 1642 1.1 christos 1643 1.1 christos /* Remove the search tree with the known translations. */ 1644 1.1 christos __tdestroy (root, free); 1645 1.1 christos root = NULL; 1646 1.1 christos 1647 1.1 christos while (transmem_list != NULL) 1648 1.1 christos { 1649 1.1 christos old = transmem_list; 1650 1.1 christos transmem_list = transmem_list->next; 1651 1.1 christos free (old); 1652 1.1 christos } 1653 1.1 christos } 1654 1.1 christos #endif 1655