?? dcigettext.c
字號(hào):
#ifdef _LIBC/* List of blocks allocated for translations. */typedef struct transmem_list{ struct transmem_list *next; char data[ZERO];} transmem_block_t;static struct transmem_list *transmem_list;#elsetypedef unsigned char transmem_block_t;#endif/* Names for the libintl functions are a problem. They must not clash with existing names and they should follow ANSI C. But this source code is also used in GNU C Library where the names have a __ prefix. So we have to make a difference here. */#ifdef _LIBC# define DCIGETTEXT __dcigettext#else# define DCIGETTEXT libintl_dcigettext#endif/* Lock variable to protect the global data in the gettext implementation. */gl_rwlock_define_initialized (, _nl_state_lock attribute_hidden)/* Checking whether the binaries runs SUID must be done and glibc provides easier methods therefore we make a difference here. */#ifdef _LIBC# define ENABLE_SECURE __libc_enable_secure# define DETERMINE_SECURE#else# ifndef HAVE_GETUID# define getuid() 0# endif# ifndef HAVE_GETGID# define getgid() 0# endif# ifndef HAVE_GETEUID# define geteuid() getuid()# endif# ifndef HAVE_GETEGID# define getegid() getgid()# endifstatic int enable_secure;# define ENABLE_SECURE (enable_secure == 1)# define DETERMINE_SECURE \ if (enable_secure == 0) \ { \ if (getuid () != geteuid () || getgid () != getegid ()) \ enable_secure = 1; \ else \ enable_secure = -1; \ }#endif/* Get the function to evaluate the plural expression. */#include "eval-plural.h"/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY locale and, if PLURAL is nonzero, search over string depending on the plural form determined by N. */#ifdef IN_LIBGLOCALEchar *gl_dcigettext (const char *domainname, const char *msgid1, const char *msgid2, int plural, unsigned long int n, int category, const char *localename, const char *encoding)#elsechar *DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, int plural, unsigned long int n, int category)#endif{#ifndef HAVE_ALLOCA struct block_list *block_list = NULL;#endif struct loaded_l10nfile *domain; struct binding *binding; const char *categoryname; const char *categoryvalue; const char *dirname; char *xdomainname; char *single_locale; char *retval; size_t retlen; int saved_errno;#if defined HAVE_TSEARCH || defined _LIBC struct known_translation_t *search; struct known_translation_t **foundp = NULL; size_t msgid_len;# if defined HAVE_PER_THREAD_LOCALE && !defined IN_LIBGLOCALE const char *localename;# endif#endif size_t domainname_len; /* If no real MSGID is given return NULL. */ if (msgid1 == NULL) return NULL;#ifdef _LIBC if (category < 0 || category >= __LC_LAST || category == LC_ALL) /* Bogus. */ return (plural == 0 ? (char *) msgid1 /* Use the Germanic plural rule. */ : n == 1 ? (char *) msgid1 : (char *) msgid2);#endif gl_rwlock_rdlock (_nl_state_lock); /* If DOMAINNAME is NULL, we are interested in the default domain. If CATEGORY is not LC_MESSAGES this might not make much sense but the definition left this undefined. */ if (domainname == NULL) domainname = _nl_current_default_domain; /* OS/2 specific: backward compatibility with older libintl versions */#ifdef LC_MESSAGES_COMPAT if (category == LC_MESSAGES_COMPAT) category = LC_MESSAGES;#endif#if defined HAVE_TSEARCH || defined _LIBC msgid_len = strlen (msgid1) + 1; /* Try to find the translation among those which we found at some time. */ search = (struct known_translation_t *) alloca (offsetof (struct known_translation_t, msgid) + msgid_len); memcpy (search->msgid, msgid1, msgid_len); search->domainname = domainname; search->category = category;# ifdef HAVE_PER_THREAD_LOCALE# ifndef IN_LIBGLOCALE# ifdef _LIBC localename = __current_locale_name (category);# else# if HAVE_NL_LOCALE_NAME /* NL_LOCALE_NAME is public glibc API introduced in glibc-2.4. */ localename = nl_langinfo (NL_LOCALE_NAME (category));# else# if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS /* The __names field is not public glibc API and must therefore not be used in code that is installed in public locations. */ { locale_t thread_locale = uselocale (NULL); if (thread_locale != LC_GLOBAL_LOCALE) localename = thread_locale->__names[category]; else localename = ""; }# endif# endif# endif# endif search->localename = localename;# ifdef IN_LIBGLOCALE search->encoding = encoding;# endif# endif /* Since tfind/tsearch manage a balanced tree, concurrent tfind and tsearch calls can be fatal. */ gl_rwlock_rdlock (tree_lock); foundp = (struct known_translation_t **) tfind (search, &root, transcmp); gl_rwlock_unlock (tree_lock); freea (search); if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr) { /* Now deal with plural. */ if (plural) retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation, (*foundp)->translation_length); else retval = (char *) (*foundp)->translation; gl_rwlock_unlock (_nl_state_lock); return retval; }#endif /* Preserve the `errno' value. */ saved_errno = errno; /* See whether this is a SUID binary or not. */ DETERMINE_SECURE; /* First find matching binding. */#ifdef IN_LIBGLOCALE /* We can use a trivial binding, since _nl_find_msg will ignore it anyway, and _nl_load_domain and _nl_find_domain just pass it through. */ binding = NULL; dirname = bindtextdomain (domainname, NULL);#else for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) { int compare = strcmp (domainname, binding->domainname); if (compare == 0) /* We found it! */ break; if (compare < 0) { /* It is not in the list. */ binding = NULL; break; } } if (binding == NULL) dirname = _nl_default_dirname; else { dirname = binding->dirname;#endif if (!IS_ABSOLUTE_PATH (dirname)) { /* We have a relative path. Make it absolute now. */ size_t dirname_len = strlen (dirname) + 1; size_t path_max; char *resolved_dirname; char *ret; path_max = (unsigned int) PATH_MAX; path_max += 2; /* The getcwd docs say to do this. */ for (;;) { resolved_dirname = (char *) alloca (path_max + dirname_len); ADD_BLOCK (block_list, tmp_dirname); __set_errno (0); ret = getcwd (resolved_dirname, path_max); if (ret != NULL || errno != ERANGE) break; path_max += path_max / 2; path_max += PATH_INCR; } if (ret == NULL) /* We cannot get the current working directory. Don't signal an error but simply return the default string. */ goto return_untranslated; stpcpy (stpcpy (strchr (resolved_dirname, '\0'), "/"), dirname); dirname = resolved_dirname; }#ifndef IN_LIBGLOCALE }#endif /* Now determine the symbolic name of CATEGORY and its value. */ categoryname = category_to_name (category);#ifdef IN_LIBGLOCALE categoryvalue = guess_category_value (category, categoryname, localename);#else categoryvalue = guess_category_value (category, categoryname);#endif domainname_len = strlen (domainname); xdomainname = (char *) alloca (strlen (categoryname) + domainname_len + 5); ADD_BLOCK (block_list, xdomainname); stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"), domainname, domainname_len), ".mo"); /* Creating working area. */ single_locale = (char *) alloca (strlen (categoryvalue) + 1); ADD_BLOCK (block_list, single_locale); /* Search for the given string. This is a loop because we perhaps got an ordered list of languages to consider for the translation. */ while (1) { /* Make CATEGORYVALUE point to the next element of the list. */ while (categoryvalue[0] != '\0' && categoryvalue[0] == ':') ++categoryvalue; if (categoryvalue[0] == '\0') { /* The whole contents of CATEGORYVALUE has been searched but no valid entry has been found. We solve this situation by implicitly appending a "C" entry, i.e. no translation will take place. */ single_locale[0] = 'C'; single_locale[1] = '\0'; } else { char *cp = single_locale; while (categoryvalue[0] != '\0' && categoryvalue[0] != ':') *cp++ = *categoryvalue++; *cp = '\0'; /* When this is a SUID binary we must not allow accessing files outside the dedicated directories. */ if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale)) /* Ingore this entry. */ continue; } /* If the current locale value is C (or POSIX) we don't load a domain. Return the MSGID. */ if (strcmp (single_locale, "C") == 0 || strcmp (single_locale, "POSIX") == 0) break; /* Find structure describing the message catalog matching the DOMAINNAME and CATEGORY. */ domain = _nl_find_domain (dirname, single_locale, xdomainname, binding); if (domain != NULL) {#if defined IN_LIBGLOCALE retval = _nl_find_msg (domain, binding, encoding, msgid1, &retlen);#else retval = _nl_find_msg (domain, binding, msgid1, 1, &retlen);#endif if (retval == NULL) { int cnt; for (cnt = 0; domain->successor[cnt] != NULL; ++cnt) {#if defined IN_LIBGLOCALE retval = _nl_find_msg (domain->successor[cnt], binding, encoding, msgid1, &retlen);#else retval = _nl_find_msg (domain->successor[cnt], binding, msgid1, 1, &retlen);#endif if (retval != NULL) { domain = domain->successor[cnt]; break; } } } /* Returning -1 means that some resource problem exists (likely memory) and that the strings could not be converted. Return the original strings. */ if (__builtin_expect (retval == (char *) -1, 0)) break; if (retval != NULL) { /* Found the translation of MSGID1 in domain DOMAIN: starting at RETVAL, RETLEN bytes. */ FREE_BLOCKS (block_list);#if defined HAVE_TSEARCH || defined _LIBC if (foundp == NULL) { /* Create a new entry and add it to the search tree. */ size_t size; struct known_translation_t *newp; size = offsetof (struct known_translation_t, msgid) + msgid_len + domainname_len + 1;# ifdef HAVE_PER_THREAD_LOCALE size += strlen (localename) + 1;# endif newp = (struct known_translation_t *) malloc (size); if (newp != NULL) { char *new_domainname;# ifdef HAVE_PER_THREAD_LOCALE char *new_localename;# endif new_domainname = mempcpy (newp->msgid, msgid1, msgid_len); memcpy (new_domainname, domainname, domainname_len + 1);# ifdef HAVE_PER_THREAD_LOCALE new_localename = new_domainname + domainname_len + 1; strcpy (new_localename, localename);# endif newp->domainname = new_domainname; newp->category = category;# ifdef HAVE_PER_THREAD_LOCALE newp->localename = new_localename;# endif# ifdef IN_LIBGLOCALE newp->encoding = encoding;# endif newp->counter = _nl_msg_cat_cntr; newp->domain = domain; newp->translation = retval; newp->translation_length = retlen; gl_rwlock_wrlock (tree_lock); /* Insert the entry in the search tree. */ foundp = (struct known_translation_t **) tsearch (newp, &root, transcmp); gl_rwlock_unlock (tree_lock); if (foundp == NULL || __builtin_expect (*foundp != newp, 0)) /* The insert failed. */ free (newp); } }
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -