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