📄 dcigettext.c
字号:
domain->conv != (__gconv_t) -1# else# if HAVE_ICONV domain->conv != (iconv_t) -1# endif# endif ) { /* We are supposed to do a conversion. First allocate an appropriate table with the same structure as the table of translations in the file, where we can put the pointers to the converted strings in. There is a slight complication with plural entries. They are represented by consecutive NUL terminated strings. We handle this case by converting RESULTLEN bytes, including NULs. */ if (domain->conv_tab == NULL && ((domain->conv_tab = (char **) calloc (nstrings + domain->n_sysdep_strings, sizeof (char *))) == NULL)) /* Mark that we didn't succeed allocating a table. */ domain->conv_tab = (char **) -1; if (__builtin_expect (domain->conv_tab == (char **) -1, 0)) /* Nothing we can do, no more memory. */ goto converted; if (domain->conv_tab[act] == NULL) { /* We haven't used this string so far, so it is not translated yet. Do this now. */ /* We use a bit more efficient memory handling. We allocate always larger blocks which get used over time. This is faster than many small allocations. */ __libc_lock_define_initialized (static, lock)# define INITIAL_BLOCK_SIZE 4080 static unsigned char *freemem; static size_t freemem_size; const unsigned char *inbuf; unsigned char *outbuf; int malloc_count;# ifndef _LIBC transmem_block_t *transmem_list = NULL;# endif __libc_lock_lock (lock); inbuf = (const unsigned char *) result; outbuf = freemem + sizeof (size_t); malloc_count = 0; while (1) { transmem_block_t *newmem;# ifdef _LIBC size_t non_reversible; int res; if (freemem_size < sizeof (size_t)) goto resize_freemem; res = __gconv (domain->conv, &inbuf, inbuf + resultlen, &outbuf, outbuf + freemem_size - sizeof (size_t), &non_reversible); if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT) break; if (res != __GCONV_FULL_OUTPUT) { __libc_lock_unlock (lock); goto converted; } inbuf = result;# else# if HAVE_ICONV const char *inptr = (const char *) inbuf; size_t inleft = resultlen; char *outptr = (char *) outbuf; size_t outleft; if (freemem_size < sizeof (size_t)) goto resize_freemem; outleft = freemem_size - sizeof (size_t); if (iconv (domain->conv, (ICONV_CONST char **) &inptr, &inleft, &outptr, &outleft) != (size_t) (-1)) { outbuf = (unsigned char *) outptr; break; } if (errno != E2BIG) { __libc_lock_unlock (lock); goto converted; }# endif# endif resize_freemem: /* We must allocate a new buffer or resize the old one. */ if (malloc_count > 0) { ++malloc_count; freemem_size = malloc_count * INITIAL_BLOCK_SIZE; newmem = (transmem_block_t *) realloc (transmem_list, freemem_size);# ifdef _LIBC if (newmem != NULL) transmem_list = transmem_list->next; else { struct transmem_list *old = transmem_list; transmem_list = transmem_list->next; free (old); }# endif } else { malloc_count = 1; freemem_size = INITIAL_BLOCK_SIZE; newmem = (transmem_block_t *) malloc (freemem_size); } if (__builtin_expect (newmem == NULL, 0)) { freemem = NULL; freemem_size = 0; __libc_lock_unlock (lock); goto converted; }# ifdef _LIBC /* Add the block to the list of blocks we have to free at some point. */ newmem->next = transmem_list; transmem_list = newmem; freemem = newmem->data; freemem_size -= offsetof (struct transmem_list, data);# else transmem_list = newmem; freemem = newmem;# endif outbuf = freemem + sizeof (size_t); } /* We have now in our buffer a converted string. Put this into the table of conversions. */ *(size_t *) freemem = outbuf - freemem - sizeof (size_t); domain->conv_tab[act] = (char *) freemem; /* Shrink freemem, but keep it aligned. */ freemem_size -= outbuf - freemem; freemem = outbuf; freemem += freemem_size & (alignof (size_t) - 1); freemem_size = freemem_size & ~ (alignof (size_t) - 1); __libc_lock_unlock (lock); } /* Now domain->conv_tab[act] contains the translation of all the plural variants. */ result = domain->conv_tab[act] + sizeof (size_t); resultlen = *(size_t *) domain->conv_tab[act]; } converted: /* The result string is converted. */#endif /* _LIBC || HAVE_ICONV */ *lengthp = resultlen; return result;}/* Look up a plural variant. */static char *internal_functionplural_lookup (struct loaded_l10nfile *domain, unsigned long int n, const char *translation, size_t translation_len){ struct loaded_domain *domaindata = (struct loaded_domain *) domain->data; unsigned long int index; const char *p; index = plural_eval (domaindata->plural, n); if (index >= domaindata->nplurals) /* This should never happen. It means the plural expression and the given maximum value do not match. */ index = 0; /* Skip INDEX strings at TRANSLATION. */ p = translation; while (index-- > 0) {#ifdef _LIBC p = __rawmemchr (p, '\0');#else p = strchr (p, '\0');#endif /* And skip over the NUL byte. */ p++; if (p >= translation + translation_len) /* This should never happen. It means the plural expression evaluated to a value larger than the number of variants available for MSGID1. */ return (char *) translation; } return (char *) p;}#ifndef _LIBC/* Return string representation of locale CATEGORY. */static const char *internal_functioncategory_to_name (int category){ const char *retval; switch (category) {#ifdef LC_COLLATE case LC_COLLATE: retval = "LC_COLLATE"; break;#endif#ifdef LC_CTYPE case LC_CTYPE: retval = "LC_CTYPE"; break;#endif#ifdef LC_MONETARY case LC_MONETARY: retval = "LC_MONETARY"; break;#endif#ifdef LC_NUMERIC case LC_NUMERIC: retval = "LC_NUMERIC"; break;#endif#ifdef LC_TIME case LC_TIME: retval = "LC_TIME"; break;#endif#ifdef LC_MESSAGES case LC_MESSAGES: retval = "LC_MESSAGES"; break;#endif#ifdef LC_RESPONSE case LC_RESPONSE: retval = "LC_RESPONSE"; break;#endif#ifdef LC_ALL case LC_ALL: /* This might not make sense but is perhaps better than any other value. */ retval = "LC_ALL"; break;#endif default: /* If you have a better idea for a default value let me know. */ retval = "LC_XXX"; } return retval;}#endif/* Guess value of current locale from value of the environment variables or system-dependent defaults. */static const char *internal_functionguess_category_value (int category, const char *categoryname){ const char *language; const char *locale;#ifndef _LIBC const char *language_default; int locale_defaulted;#endif /* We use the settings in the following order: 1. The value of the environment variable 'LANGUAGE'. This is a GNU extension. Its value can be a colon-separated list of locale names. 2. The value of the environment variable 'LC_ALL', 'LC_xxx', or 'LANG'. More precisely, the first among these that is set to a non-empty value. This is how POSIX specifies it. The value is a single locale name. 3. A system-dependent preference list of languages. Its value can be a colon-separated list of locale names. 4. A system-dependent default locale name. This way: - System-dependent settings can be overridden by environment variables. - If the system provides both a list of languages and a default locale, the former is used. */ /* Fetch the locale name, through the POSIX method of looking to `LC_ALL', `LC_xxx', and `LANG'. On some systems this can be done by the `setlocale' function itself. */#ifdef _LIBC locale = __current_locale_name (category);#else locale = _nl_locale_name_posix (category, categoryname); locale_defaulted = 0; if (locale == NULL) { locale = _nl_locale_name_default (); locale_defaulted = 1; }#endif /* Ignore LANGUAGE and its system-dependent analogon if the locale is set to "C" because 1. "C" locale usually uses the ASCII encoding, and most international messages use non-ASCII characters. These characters get displayed as question marks (if using glibc's iconv()) or as invalid 8-bit characters (because other iconv()s refuse to convert most non-ASCII characters to ASCII). In any case, the output is ugly. 2. The precise output of some programs in the "C" locale is specified by POSIX and should not depend on environment variables like "LANGUAGE" or system-dependent information. We allow such programs to use gettext(). */ if (strcmp (locale, "C") == 0) return locale; /* The highest priority value is the value of the 'LANGUAGE' environment variable. */ language = getenv ("LANGUAGE"); if (language != NULL && language[0] != '\0') return language;#ifndef _LIBC /* The next priority value is the locale name, if not defaulted. */ if (locale_defaulted) { /* The next priority value is the default language preferences list. */ language_default = _nl_language_preferences_default (); if (language_default != NULL) return language_default; } /* The least priority value is the locale name, if defaulted. */#endif return locale;}/* @@ begin of epilog @@ *//* We don't want libintl.a to depend on any other library. So we avoid the non-standard function stpcpy. In GNU C Library this function is available, though. Also allow the symbol HAVE_STPCPY to be defined. */#if !_LIBC && !HAVE_STPCPYstatic char *stpcpy (char *dest, const char *src){ while ((*dest++ = *src++) != '\0') /* Do nothing. */ ; return dest - 1;}#endif#if !_LIBC && !HAVE_MEMPCPYstatic void *mempcpy (void *dest, const void *src, size_t n){ return (void *) ((char *) memcpy (dest, src, n) + n);}#endif#ifdef _LIBC/* If we want to free all resources we have to do some work at program's end. */libc_freeres_fn (free_mem){ void *old; while (_nl_domain_bindings != NULL) { struct binding *oldp = _nl_domain_bindings; _nl_domain_bindings = _nl_domain_bindings->next; if (oldp->dirname != INTUSE(_nl_default_dirname)) /* Yes, this is a pointer comparison. */ free (oldp->dirname); free (oldp->codeset); free (oldp); } if (_nl_current_default_domain != _nl_default_default_domain) /* Yes, again a pointer comparison. */ free ((char *) _nl_current_default_domain); /* Remove the search tree with the known translations. */ __tdestroy (root, free); root = NULL; while (transmem_list != NULL) { old = transmem_list; transmem_list = transmem_list->next; free (old); }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -