00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _GNU_SOURCE
00023 # define _GNU_SOURCE 1
00024 #endif
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #include <sys/types.h>
00031
00032 #ifdef __GNUC__
00033 # define alloca __builtin_alloca
00034 # define HAVE_ALLOCA 1
00035 #else
00036 # ifdef _MSC_VER
00037 # include <malloc.h>
00038 # define alloca _alloca
00039 # else
00040 # if defined HAVE_ALLOCA_H || defined _LIBC
00041 # include <alloca.h>
00042 # else
00043 # ifdef _AIX
00044 #pragma alloca
00045 # else
00046 # ifndef alloca
00047 char *alloca ();
00048 # endif
00049 # endif
00050 # endif
00051 # endif
00052 #endif
00053
00054 #include <errno.h>
00055 #ifndef errno
00056 extern int errno;
00057 #endif
00058 #ifndef __set_errno
00059 # define __set_errno(val) errno = (val)
00060 #endif
00061
00062 #include <stddef.h>
00063 #include <stdlib.h>
00064 #include <string.h>
00065
00066 #if defined HAVE_UNISTD_H || defined _LIBC
00067 # include <unistd.h>
00068 #endif
00069
00070 #include <locale.h>
00071
00072 #ifdef _LIBC
00073
00074
00075 # if defined __alpha__ || defined __arm__ || defined __i386__ \
00076 || defined __m68k__ || defined __s390__
00077 # define INTDIV0_RAISES_SIGFPE 1
00078 # else
00079 # define INTDIV0_RAISES_SIGFPE 0
00080 # endif
00081 #endif
00082 #if !INTDIV0_RAISES_SIGFPE
00083 # include <signal.h>
00084 #endif
00085
00086 #if defined HAVE_SYS_PARAM_H || defined _LIBC
00087 # include <sys/param.h>
00088 #endif
00089
00090 #include "gettextP.h"
00091 #include "plural-exp.h"
00092 #ifdef _LIBC
00093 # include <libintl.h>
00094 #else
00095 # include "libgnuintl.h"
00096 #endif
00097 #include "hash-string.h"
00098
00099
00100 #ifdef _LIBC
00101 # include <bits/libc-lock.h>
00102 #else
00103
00104 # define __libc_lock_define_initialized(CLASS, NAME)
00105 # define __libc_lock_lock(NAME)
00106 # define __libc_lock_unlock(NAME)
00107 # define __libc_rwlock_define_initialized(CLASS, NAME)
00108 # define __libc_rwlock_rdlock(NAME)
00109 # define __libc_rwlock_unlock(NAME)
00110 #endif
00111
00112
00113 #if defined __GNUC__ && __GNUC__ >= 2
00114 # define alignof(TYPE) __alignof__ (TYPE)
00115 #else
00116 # define alignof(TYPE) \
00117 ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
00118 #endif
00119
00120
00121
00122
00123 #if !defined _LIBC
00124 # define _nl_default_default_domain libintl_nl_default_default_domain
00125 # define _nl_current_default_domain libintl_nl_current_default_domain
00126 # define _nl_default_dirname libintl_nl_default_dirname
00127 # define _nl_domain_bindings libintl_nl_domain_bindings
00128 #endif
00129
00130
00131 #ifndef offsetof
00132 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
00133 #endif
00134
00135
00136
00137 #ifdef _LIBC
00138
00139
00140
00141 # define getcwd __getcwd
00142 # ifndef stpcpy
00143 # define stpcpy __stpcpy
00144 # endif
00145 # define tfind __tfind
00146 #else
00147 # if !defined HAVE_GETCWD
00148 char *getwd ();
00149 # define getcwd(buf, max) getwd (buf)
00150 # else
00151 char *getcwd ();
00152 # endif
00153 # ifndef HAVE_STPCPY
00154 static char *stpcpy PARAMS ((char *dest, const char *src));
00155 # endif
00156 # ifndef HAVE_MEMPCPY
00157 static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
00158 # endif
00159 #endif
00160
00161
00162 #define PATH_INCR 32
00163
00164
00165
00166
00167
00168 #if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
00169 # include <limits.h>
00170 #endif
00171
00172 #ifndef _POSIX_PATH_MAX
00173 # define _POSIX_PATH_MAX 255
00174 #endif
00175
00176 #if !defined PATH_MAX && defined _PC_PATH_MAX
00177 # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
00178 #endif
00179
00180
00181 #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
00182 # include <sys/param.h>
00183 #endif
00184
00185 #if !defined PATH_MAX && defined MAXPATHLEN
00186 # define PATH_MAX MAXPATHLEN
00187 #endif
00188
00189 #ifndef PATH_MAX
00190 # define PATH_MAX _POSIX_PATH_MAX
00191 #endif
00192
00193
00194
00195
00196
00197
00198
00199 #if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
00200
00201 # define ISSLASH(C) ((C) == '/' || (C) == '\\')
00202 # define HAS_DEVICE(P) \
00203 ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
00204 && (P)[1] == ':')
00205 # define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
00206 # define IS_PATH_WITH_DIR(P) \
00207 (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
00208 #else
00209
00210 # define ISSLASH(C) ((C) == '/')
00211 # define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
00212 # define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
00213 #endif
00214
00215
00216
00217 struct known_translation_t
00218 {
00219
00220 char *domainname;
00221
00222
00223 int category;
00224
00225
00226 int counter;
00227
00228
00229 struct loaded_l10nfile *domain;
00230
00231
00232 const char *translation;
00233 size_t translation_length;
00234
00235
00236 char msgid[ZERO];
00237 };
00238
00239
00240
00241 #if defined HAVE_TSEARCH || defined _LIBC
00242 # include <search.h>
00243
00244 static void *root;
00245
00246 # ifdef _LIBC
00247 # define tsearch __tsearch
00248 # endif
00249
00250
00251 static int transcmp PARAMS ((const void *p1, const void *p2));
00252 static int
00253 transcmp (p1, p2)
00254 const void *p1;
00255 const void *p2;
00256 {
00257 const struct known_translation_t *s1;
00258 const struct known_translation_t *s2;
00259 int result;
00260
00261 s1 = (const struct known_translation_t *) p1;
00262 s2 = (const struct known_translation_t *) p2;
00263
00264 result = strcmp (s1->msgid, s2->msgid);
00265 if (result == 0)
00266 {
00267 result = strcmp (s1->domainname, s2->domainname);
00268 if (result == 0)
00269
00270
00271
00272 result = s1->category - s2->category;
00273 }
00274
00275 return result;
00276 }
00277 #endif
00278
00279 #ifndef INTVARDEF
00280 # define INTVARDEF(name)
00281 #endif
00282 #ifndef INTUSE
00283 # define INTUSE(name) name
00284 #endif
00285
00286
00287
00288 const char _nl_default_default_domain[] attribute_hidden = "messages";
00289
00290
00291 const char *_nl_current_default_domain attribute_hidden
00292 = _nl_default_default_domain;
00293
00294
00295 #if defined __EMX__
00296 extern const char _nl_default_dirname[];
00297 #else
00298 const char _nl_default_dirname[] = LOCALEDIR;
00299 INTVARDEF (_nl_default_dirname)
00300 #endif
00301
00302
00303
00304 struct binding *_nl_domain_bindings;
00305
00306
00307 static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain,
00308 unsigned long int n,
00309 const char *translation,
00310 size_t translation_len))
00311 internal_function;
00312 static const char *guess_category_value PARAMS ((int category,
00313 const char *categoryname))
00314 internal_function;
00315 #ifdef _LIBC
00316 # include "../locale/localeinfo.h"
00317 # define category_to_name(category) _nl_category_names[category]
00318 #else
00319 static const char *category_to_name PARAMS ((int category)) internal_function;
00320 #endif
00321
00322
00323
00324
00325 #ifdef HAVE_ALLOCA
00326
00327 # define freea(p)
00328 # define ADD_BLOCK(list, address)
00329 # define FREE_BLOCKS(list)
00330 #else
00331 struct block_list
00332 {
00333 void *address;
00334 struct block_list *next;
00335 };
00336 # define ADD_BLOCK(list, addr) \
00337 do { \
00338 struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
00339
00340 \
00341 if (newp != NULL) { \
00342 newp->address = (addr); \
00343 newp->next = (list); \
00344 (list) = newp; \
00345 } \
00346 } while (0)
00347 # define FREE_BLOCKS(list) \
00348 do { \
00349 while (list != NULL) { \
00350 struct block_list *old = list; \
00351 list = list->next; \
00352 free (old->address); \
00353 free (old); \
00354 } \
00355 } while (0)
00356 # undef alloca
00357 # define alloca(size) (malloc (size))
00358 # define freea(p) free (p)
00359 #endif
00360
00361
00362 #ifdef _LIBC
00363
00364 typedef struct transmem_list
00365 {
00366 struct transmem_list *next;
00367 char data[ZERO];
00368 } transmem_block_t;
00369 static struct transmem_list *transmem_list;
00370 #else
00371 typedef unsigned char transmem_block_t;
00372 #endif
00373
00374
00375
00376
00377
00378
00379 #ifdef _LIBC
00380 # define DCIGETTEXT __dcigettext
00381 #else
00382 # define DCIGETTEXT libintl_dcigettext
00383 #endif
00384
00385
00386 #ifdef _LIBC
00387 __libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
00388 #endif
00389
00390
00391
00392 #ifdef _LIBC
00393 # define ENABLE_SECURE __libc_enable_secure
00394 # define DETERMINE_SECURE
00395 #else
00396 # ifndef HAVE_GETUID
00397 # define getuid() 0
00398 # endif
00399 # ifndef HAVE_GETGID
00400 # define getgid() 0
00401 # endif
00402 # ifndef HAVE_GETEUID
00403 # define geteuid() getuid()
00404 # endif
00405 # ifndef HAVE_GETEGID
00406 # define getegid() getgid()
00407 # endif
00408 static int enable_secure;
00409 # define ENABLE_SECURE (enable_secure == 1)
00410 # define DETERMINE_SECURE \
00411 if (enable_secure == 0) \
00412 { \
00413 if (getuid () != geteuid () || getgid () != getegid ()) \
00414 enable_secure = 1; \
00415 else \
00416 enable_secure = -1; \
00417 }
00418 #endif
00419
00420
00421 #include "eval-plural.h"
00422
00423
00424
00425
00426 char *
00427 DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
00428 const char *domainname;
00429 const char *msgid1;
00430 const char *msgid2;
00431 int plural;
00432 unsigned long int n;
00433 int category;
00434 {
00435 #ifndef HAVE_ALLOCA
00436 struct block_list *block_list = NULL;
00437 #endif
00438 struct loaded_l10nfile *domain;
00439 struct binding *binding;
00440 const char *categoryname;
00441 const char *categoryvalue;
00442 char *dirname, *xdomainname;
00443 char *single_locale;
00444 char *retval;
00445 size_t retlen;
00446 int saved_errno;
00447 #if defined HAVE_TSEARCH || defined _LIBC
00448 struct known_translation_t *search;
00449 struct known_translation_t **foundp = NULL;
00450 size_t msgid_len;
00451 #endif
00452 size_t domainname_len;
00453
00454
00455 if (msgid1 == NULL)
00456 return NULL;
00457
00458 #ifdef _LIBC
00459 if (category < 0 || category >= __LC_LAST || category == LC_ALL)
00460
00461 return (plural == 0
00462 ? (char *) msgid1
00463
00464 : n == 1 ? (char *) msgid1 : (char *) msgid2);
00465 #endif
00466
00467 __libc_rwlock_rdlock (_nl_state_lock);
00468
00469
00470
00471
00472 if (domainname == NULL)
00473 domainname = _nl_current_default_domain;
00474
00475
00476 #ifdef LC_MESSAGES_COMPAT
00477 if (category == LC_MESSAGES_COMPAT)
00478 category = LC_MESSAGES;
00479 #endif
00480
00481 #if defined HAVE_TSEARCH || defined _LIBC
00482 msgid_len = strlen (msgid1) + 1;
00483
00484
00485
00486 search = (struct known_translation_t *)
00487 alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
00488 memcpy (search->msgid, msgid1, msgid_len);
00489 search->domainname = (char *) domainname;
00490 search->category = category;
00491
00492 foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
00493 freea (search);
00494 if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
00495 {
00496
00497 if (plural)
00498 retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
00499 (*foundp)->translation_length);
00500 else
00501 retval = (char *) (*foundp)->translation;
00502
00503 __libc_rwlock_unlock (_nl_state_lock);
00504 return retval;
00505 }
00506 #endif
00507
00508
00509 saved_errno = errno;
00510
00511
00512 DETERMINE_SECURE;
00513
00514
00515 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
00516 {
00517 int compare = strcmp (domainname, binding->domainname);
00518 if (compare == 0)
00519
00520 break;
00521 if (compare < 0)
00522 {
00523
00524 binding = NULL;
00525 break;
00526 }
00527 }
00528
00529 if (binding == NULL)
00530 dirname = (char *) INTUSE(_nl_default_dirname);
00531 else if (IS_ABSOLUTE_PATH (binding->dirname))
00532 dirname = binding->dirname;
00533 else
00534 {
00535
00536 size_t dirname_len = strlen (binding->dirname) + 1;
00537 size_t path_max;
00538 char *ret;
00539
00540 path_max = (unsigned int) PATH_MAX;
00541 path_max += 2;
00542
00543 for (;;)
00544 {
00545 dirname = (char *) alloca (path_max + dirname_len);
00546 ADD_BLOCK (block_list, dirname);
00547
00548 __set_errno (0);
00549 ret = getcwd (dirname, path_max);
00550 if (ret != NULL || errno != ERANGE)
00551 break;
00552
00553 path_max += path_max / 2;
00554 path_max += PATH_INCR;
00555 }
00556
00557 if (ret == NULL)
00558
00559
00560 goto return_untranslated;
00561
00562 stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
00563 }
00564
00565
00566 categoryname = category_to_name (category);
00567 categoryvalue = guess_category_value (category, categoryname);
00568
00569 domainname_len = strlen (domainname);
00570 xdomainname = (char *) alloca (strlen (categoryname)
00571 + domainname_len + 5);
00572 ADD_BLOCK (block_list, xdomainname);
00573
00574 stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
00575 domainname, domainname_len),
00576 ".mo");
00577
00578
00579 single_locale = (char *) alloca (strlen (categoryvalue) + 1);
00580 ADD_BLOCK (block_list, single_locale);
00581
00582
00583
00584
00585 while (1)
00586 {
00587
00588 while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
00589 ++categoryvalue;
00590 if (categoryvalue[0] == '\0')
00591 {
00592
00593
00594
00595
00596 single_locale[0] = 'C';
00597 single_locale[1] = '\0';
00598 }
00599 else
00600 {
00601 char *cp = single_locale;
00602 while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
00603 *cp++ = *categoryvalue++;
00604 *cp = '\0';
00605
00606
00607
00608 if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale))
00609
00610 continue;
00611 }
00612
00613
00614
00615 if (strcmp (single_locale, "C") == 0
00616 || strcmp (single_locale, "POSIX") == 0)
00617 break;
00618
00619
00620
00621 domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
00622
00623 if (domain != NULL)
00624 {
00625 retval = _nl_find_msg (domain, binding, msgid1, &retlen);
00626
00627 if (retval == NULL)
00628 {
00629 int cnt;
00630
00631 for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
00632 {
00633 retval = _nl_find_msg (domain->successor[cnt], binding,
00634 msgid1, &retlen);
00635
00636 if (retval != NULL)
00637 {
00638 domain = domain->successor[cnt];
00639 break;
00640 }
00641 }
00642 }
00643
00644 if (retval != NULL)
00645 {
00646
00647
00648 FREE_BLOCKS (block_list);
00649 #if defined HAVE_TSEARCH || defined _LIBC
00650 if (foundp == NULL)
00651 {
00652
00653 struct known_translation_t *newp;
00654
00655 newp = (struct known_translation_t *)
00656 malloc (offsetof (struct known_translation_t, msgid)
00657 + msgid_len + domainname_len + 1);
00658 if (newp != NULL)
00659 {
00660 newp->domainname =
00661 mempcpy (newp->msgid, msgid1, msgid_len);
00662 memcpy (newp->domainname, domainname, domainname_len + 1);
00663 newp->category = category;
00664 newp->counter = _nl_msg_cat_cntr;
00665 newp->domain = domain;
00666 newp->translation = retval;
00667 newp->translation_length = retlen;
00668
00669
00670 foundp = (struct known_translation_t **)
00671 tsearch (newp, &root, transcmp);
00672 if (foundp == NULL
00673 || __builtin_expect (*foundp != newp, 0))
00674
00675 free (newp);
00676 }
00677 }
00678 else
00679 {
00680
00681 (*foundp)->counter = _nl_msg_cat_cntr;
00682 (*foundp)->domain = domain;
00683 (*foundp)->translation = retval;
00684 (*foundp)->translation_length = retlen;
00685 }
00686 #endif
00687 __set_errno (saved_errno);
00688
00689
00690 if (plural)
00691 retval = plural_lookup (domain, n, retval, retlen);
00692
00693 __libc_rwlock_unlock (_nl_state_lock);
00694 return retval;
00695 }
00696 }
00697 }
00698
00699 return_untranslated:
00700
00701 FREE_BLOCKS (block_list);
00702 __libc_rwlock_unlock (_nl_state_lock);
00703 #ifndef _LIBC
00704 if (!ENABLE_SECURE)
00705 {
00706 extern void _nl_log_untranslated PARAMS ((const char *logfilename,
00707 const char *domainname,
00708 const char *msgid1,
00709 const char *msgid2,
00710 int plural));
00711 const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED");
00712
00713 if (logfilename != NULL && logfilename[0] != '\0')
00714 _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural);
00715 }
00716 #endif
00717 __set_errno (saved_errno);
00718 return (plural == 0
00719 ? (char *) msgid1
00720
00721 : n == 1 ? (char *) msgid1 : (char *) msgid2);
00722 }
00723
00724
00725 char *
00726 internal_function
00727 _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
00728 struct loaded_l10nfile *domain_file;
00729 struct binding *domainbinding;
00730 const char *msgid;
00731 size_t *lengthp;
00732 {
00733 struct loaded_domain *domain;
00734 nls_uint32 nstrings;
00735 size_t act;
00736 char *result;
00737 size_t resultlen;
00738
00739 if (domain_file->decided == 0)
00740 _nl_load_domain (domain_file, domainbinding);
00741
00742 if (domain_file->data == NULL)
00743 return NULL;
00744
00745 domain = (struct loaded_domain *) domain_file->data;
00746
00747 nstrings = domain->nstrings;
00748
00749
00750 if (domain->hash_tab != NULL)
00751 {
00752
00753 nls_uint32 len = strlen (msgid);
00754 nls_uint32 hash_val = hash_string (msgid);
00755 nls_uint32 idx = hash_val % domain->hash_size;
00756 nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
00757
00758 while (1)
00759 {
00760 nls_uint32 nstr =
00761 W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
00762
00763 if (nstr == 0)
00764
00765 return NULL;
00766
00767 nstr--;
00768
00769
00770
00771
00772 if (nstr < nstrings
00773 ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
00774 && (strcmp (msgid,
00775 domain->data + W (domain->must_swap,
00776 domain->orig_tab[nstr].offset))
00777 == 0)
00778 : domain->orig_sysdep_tab[nstr - nstrings].length > len
00779 && (strcmp (msgid,
00780 domain->orig_sysdep_tab[nstr - nstrings].pointer)
00781 == 0))
00782 {
00783 act = nstr;
00784 goto found;
00785 }
00786
00787 if (idx >= domain->hash_size - incr)
00788 idx -= domain->hash_size - incr;
00789 else
00790 idx += incr;
00791 }
00792
00793 }
00794 else
00795 {
00796
00797
00798 size_t top, bottom;
00799
00800 bottom = 0;
00801 top = nstrings;
00802 while (bottom < top)
00803 {
00804 int cmp_val;
00805
00806 act = (bottom + top) / 2;
00807 cmp_val = strcmp (msgid, (domain->data
00808 + W (domain->must_swap,
00809 domain->orig_tab[act].offset)));
00810 if (cmp_val < 0)
00811 top = act;
00812 else if (cmp_val > 0)
00813 bottom = act + 1;
00814 else
00815 goto found;
00816 }
00817
00818 return NULL;
00819 }
00820
00821 found:
00822
00823
00824 if (act < nstrings)
00825 {
00826 result = (char *)
00827 (domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
00828 resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
00829 }
00830 else
00831 {
00832 result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
00833 resultlen = domain->trans_sysdep_tab[act - nstrings].length;
00834 }
00835
00836 #if defined _LIBC || HAVE_ICONV
00837 if (domain->codeset_cntr
00838 != (domainbinding != NULL ? domainbinding->codeset_cntr : 0))
00839 {
00840
00841
00842
00843 _nl_free_domain_conv (domain);
00844 _nl_init_domain_conv (domain_file, domain, domainbinding);
00845 }
00846
00847 if (
00848 # ifdef _LIBC
00849 domain->conv != (__gconv_t) -1
00850 # else
00851 # if HAVE_ICONV
00852 domain->conv != (iconv_t) -1
00853 # endif
00854 # endif
00855 )
00856 {
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866 if (domain->conv_tab == NULL
00867 && ((domain->conv_tab =
00868 (char **) calloc (nstrings + domain->n_sysdep_strings,
00869 sizeof (char *)))
00870 == NULL))
00871
00872 domain->conv_tab = (char **) -1;
00873
00874 if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
00875
00876 goto converted;
00877
00878 if (domain->conv_tab[act] == NULL)
00879 {
00880
00881
00882
00883
00884
00885 __libc_lock_define_initialized (static, lock)
00886 # define INITIAL_BLOCK_SIZE 4080
00887 static unsigned char *freemem;
00888 static size_t freemem_size;
00889
00890 const unsigned char *inbuf;
00891 unsigned char *outbuf;
00892 int malloc_count;
00893 # ifndef _LIBC
00894 transmem_block_t *transmem_list = NULL;
00895 # endif
00896
00897 __libc_lock_lock (lock);
00898
00899 inbuf = (const unsigned char *) result;
00900 outbuf = freemem + sizeof (size_t);
00901
00902 malloc_count = 0;
00903 while (1)
00904 {
00905 transmem_block_t *newmem;
00906 # ifdef _LIBC
00907 size_t non_reversible;
00908 int res;
00909
00910 if (freemem_size < sizeof (size_t))
00911 goto resize_freemem;
00912
00913 res = __gconv (domain->conv,
00914 &inbuf, inbuf + resultlen,
00915 &outbuf,
00916 outbuf + freemem_size - sizeof (size_t),
00917 &non_reversible);
00918
00919 if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
00920 break;
00921
00922 if (res != __GCONV_FULL_OUTPUT)
00923 {
00924 __libc_lock_unlock (lock);
00925 goto converted;
00926 }
00927
00928 inbuf = result;
00929 # else
00930 # if HAVE_ICONV
00931 const char *inptr = (const char *) inbuf;
00932 size_t inleft = resultlen;
00933 char *outptr = (char *) outbuf;
00934 size_t outleft;
00935
00936 if (freemem_size < sizeof (size_t))
00937 goto resize_freemem;
00938
00939 outleft = freemem_size - sizeof (size_t);
00940 if (iconv (domain->conv,
00941 (ICONV_CONST char **) &inptr, &inleft,
00942 &outptr, &outleft)
00943 != (size_t) (-1))
00944 {
00945 outbuf = (unsigned char *) outptr;
00946 break;
00947 }
00948 if (errno != E2BIG)
00949 {
00950 __libc_lock_unlock (lock);
00951 goto converted;
00952 }
00953 # endif
00954 # endif
00955
00956 resize_freemem:
00957
00958 if (malloc_count > 0)
00959 {
00960 ++malloc_count;
00961 freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
00962 newmem = (transmem_block_t *) realloc (transmem_list,
00963 freemem_size);
00964 # ifdef _LIBC
00965 if (newmem != NULL)
00966 transmem_list = transmem_list->next;
00967 else
00968 {
00969 struct transmem_list *old = transmem_list;
00970
00971 transmem_list = transmem_list->next;
00972 free (old);
00973 }
00974 # endif
00975 }
00976 else
00977 {
00978 malloc_count = 1;
00979 freemem_size = INITIAL_BLOCK_SIZE;
00980 newmem = (transmem_block_t *) malloc (freemem_size);
00981 }
00982 if (__builtin_expect (newmem == NULL, 0))
00983 {
00984 freemem = NULL;
00985 freemem_size = 0;
00986 __libc_lock_unlock (lock);
00987 goto converted;
00988 }
00989
00990 # ifdef _LIBC
00991
00992
00993 newmem->next = transmem_list;
00994 transmem_list = newmem;
00995
00996 freemem = newmem->data;
00997 freemem_size -= offsetof (struct transmem_list, data);
00998 # else
00999 transmem_list = newmem;
01000 freemem = newmem;
01001 # endif
01002
01003 outbuf = freemem + sizeof (size_t);
01004 }
01005
01006
01007
01008 *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
01009 domain->conv_tab[act] = (char *) freemem;
01010
01011 freemem_size -= outbuf - freemem;
01012 freemem = outbuf;
01013 freemem += freemem_size & (alignof (size_t) - 1);
01014 freemem_size = freemem_size & ~ (alignof (size_t) - 1);
01015
01016 __libc_lock_unlock (lock);
01017 }
01018
01019
01020
01021 result = domain->conv_tab[act] + sizeof (size_t);
01022 resultlen = *(size_t *) domain->conv_tab[act];
01023 }
01024
01025 converted:
01026
01027
01028 #endif
01029
01030 *lengthp = resultlen;
01031 return result;
01032 }
01033
01034
01035
01036 static char *
01037 internal_function
01038 plural_lookup (domain, n, translation, translation_len)
01039 struct loaded_l10nfile *domain;
01040 unsigned long int n;
01041 const char *translation;
01042 size_t translation_len;
01043 {
01044 struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
01045 unsigned long int index;
01046 const char *p;
01047
01048 index = plural_eval (domaindata->plural, n);
01049 if (index >= domaindata->nplurals)
01050
01051
01052 index = 0;
01053
01054
01055 p = translation;
01056 while (index-- > 0)
01057 {
01058 #ifdef _LIBC
01059 p = __rawmemchr (p, '\0');
01060 #else
01061 p = strchr (p, '\0');
01062 #endif
01063
01064 p++;
01065
01066 if (p >= translation + translation_len)
01067
01068
01069
01070 return (char *) translation;
01071 }
01072 return (char *) p;
01073 }
01074
01075 #ifndef _LIBC
01076
01077 static const char *
01078 internal_function
01079 category_to_name (category)
01080 int category;
01081 {
01082 const char *retval;
01083
01084 switch (category)
01085 {
01086 #ifdef LC_COLLATE
01087 case LC_COLLATE:
01088 retval = "LC_COLLATE";
01089 break;
01090 #endif
01091 #ifdef LC_CTYPE
01092 case LC_CTYPE:
01093 retval = "LC_CTYPE";
01094 break;
01095 #endif
01096 #ifdef LC_MONETARY
01097 case LC_MONETARY:
01098 retval = "LC_MONETARY";
01099 break;
01100 #endif
01101 #ifdef LC_NUMERIC
01102 case LC_NUMERIC:
01103 retval = "LC_NUMERIC";
01104 break;
01105 #endif
01106 #ifdef LC_TIME
01107 case LC_TIME:
01108 retval = "LC_TIME";
01109 break;
01110 #endif
01111 #ifdef LC_MESSAGES
01112 case LC_MESSAGES:
01113 retval = "LC_MESSAGES";
01114 break;
01115 #endif
01116 #ifdef LC_RESPONSE
01117 case LC_RESPONSE:
01118 retval = "LC_RESPONSE";
01119 break;
01120 #endif
01121 #ifdef LC_ALL
01122 case LC_ALL:
01123
01124
01125 retval = "LC_ALL";
01126 break;
01127 #endif
01128 default:
01129
01130 retval = "LC_XXX";
01131 }
01132
01133 return retval;
01134 }
01135 #endif
01136
01137
01138 static const char *
01139 internal_function
01140 guess_category_value (category, categoryname)
01141 int category;
01142 const char *categoryname;
01143 {
01144 const char *language;
01145 const char *retval;
01146
01147
01148
01149
01150 language = getenv ("LANGUAGE");
01151 if (language != NULL && language[0] == '\0')
01152 language = NULL;
01153
01154
01155
01156
01157 #ifdef _LIBC
01158 retval = __current_locale_name (category);
01159 #else
01160 retval = _nl_locale_name (category, categoryname);
01161 #endif
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172 return language != NULL && strcmp (retval, "C") != 0 ? language : retval;
01173 }
01174
01175
01176
01177
01178
01179
01180
01181 #if !_LIBC && !HAVE_STPCPY
01182 static char *
01183 stpcpy (dest, src)
01184 char *dest;
01185 const char *src;
01186 {
01187 while ((*dest++ = *src++) != '\0')
01188 ;
01189 return dest - 1;
01190 }
01191 #endif
01192
01193 #if !_LIBC && !HAVE_MEMPCPY
01194 static void *
01195 mempcpy (dest, src, n)
01196 void *dest;
01197 const void *src;
01198 size_t n;
01199 {
01200 return (void *) ((char *) memcpy (dest, src, n) + n);
01201 }
01202 #endif
01203
01204
01205 #ifdef _LIBC
01206
01207
01208 libc_freeres_fn (free_mem)
01209 {
01210 void *old;
01211
01212 while (_nl_domain_bindings != NULL)
01213 {
01214 struct binding *oldp = _nl_domain_bindings;
01215 _nl_domain_bindings = _nl_domain_bindings->next;
01216 if (oldp->dirname != INTUSE(_nl_default_dirname))
01217
01218 free (oldp->dirname);
01219 free (oldp->codeset);
01220 free (oldp);
01221 }
01222
01223 if (_nl_current_default_domain != _nl_default_default_domain)
01224
01225 free ((char *) _nl_current_default_domain);
01226
01227
01228 __tdestroy (root, free);
01229 root = NULL;
01230
01231 while (transmem_list != NULL)
01232 {
01233 old = transmem_list;
01234 transmem_list = transmem_list->next;
01235 free (old);
01236 }
01237 }
01238 #endif