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