📄 dcigettext.c
字号:
/* Implementation of the internal dcigettext function. Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Tell glibc's <string.h> to provide a prototype for mempcpy(). This must come before <config.h> because <config.h> may include <features.h>, and once <features.h> has been included, it's too late. */#ifndef _GNU_SOURCE# define _GNU_SOURCE 1#endif#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <sys/types.h>#ifdef __GNUC__# define alloca __builtin_alloca# define HAVE_ALLOCA 1#else# if defined HAVE_ALLOCA_H || defined _LIBC# include <alloca.h># else# ifdef _AIX #pragma alloca# else# ifndef allocachar *alloca ();# endif# endif# endif#endif#include <errno.h>#ifndef errnoextern int errno;#endif#ifndef __set_errno# define __set_errno(val) errno = (val)#endif#include <stddef.h>#include <stdlib.h>#include <string.h>#if !HAVE_STRCHR && !defined _LIBC# ifndef strchr# define strchr index# endif#endif#if defined HAVE_UNISTD_H || defined _LIBC# include <unistd.h>#endif#include <locale.h>#if defined HAVE_SYS_PARAM_H || defined _LIBC# include <sys/param.h>#endif#include "gettextP.h"#ifdef _LIBC# include <libintl.h>#else# include "libgnuintl.h"#endif#include "hash-string.h"/* Thread safetyness. */#ifdef _LIBC# include <bits/libc-lock.h>#else/* Provide dummy implementation if this is outside glibc. */# define __libc_lock_define_initialized(CLASS, NAME)# define __libc_lock_lock(NAME)# define __libc_lock_unlock(NAME)# define __libc_rwlock_define_initialized(CLASS, NAME)# define __libc_rwlock_rdlock(NAME)# define __libc_rwlock_unlock(NAME)#endif/* Alignment of types. */#if defined __GNUC__ && __GNUC__ >= 2# define alignof(TYPE) __alignof__ (TYPE)#else# define alignof(TYPE) \ ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)#endif/* The internal variables in the standalone libintl.a must have different names than the internal variables in GNU libc, otherwise programs using libintl.a cannot be linked statically. */#if !defined _LIBC# define _nl_default_default_domain _nl_default_default_domain__# define _nl_current_default_domain _nl_current_default_domain__# define _nl_default_dirname _nl_default_dirname__# define _nl_domain_bindings _nl_domain_bindings__#endif/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */#ifndef offsetof# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))#endif/* @@ end of prolog @@ */#ifdef _LIBC/* Rename the non ANSI C functions. This is required by the standard because some ANSI C functions will require linking with this object file and the name space must not be polluted. */# define getcwd __getcwd# ifndef stpcpy# define stpcpy __stpcpy# endif# define tfind __tfind#else# if !defined HAVE_GETCWDchar *getwd ();# define getcwd(buf, max) getwd (buf)# elsechar *getcwd ();# endif# ifndef HAVE_STPCPYstatic char *stpcpy PARAMS ((char *dest, const char *src));# endif# ifndef HAVE_MEMPCPYstatic void *mempcpy PARAMS ((void *dest, const void *src, size_t n));# endif#endif/* Amount to increase buffer size by in each try. */#define PATH_INCR 32/* The following is from pathmax.h. *//* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define PATH_MAX but might cause redefinition warnings when sys/param.h is later included (as on MORE/BSD 4.3). */#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)# include <limits.h>#endif#ifndef _POSIX_PATH_MAX# define _POSIX_PATH_MAX 255#endif#if !defined PATH_MAX && defined _PC_PATH_MAX# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))#endif/* Don't include sys/param.h if it already has been. */#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN# include <sys/param.h>#endif#if !defined PATH_MAX && defined MAXPATHLEN# define PATH_MAX MAXPATHLEN#endif#ifndef PATH_MAX# define PATH_MAX _POSIX_PATH_MAX#endif/* Pathname support. ISSLASH(C) tests whether C is a directory separator character. IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not, it may be concatenated to a directory pathname. IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. */#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ /* Win32, OS/2, DOS */# define ISSLASH(C) ((C) == '/' || (C) == '\\')# define HAS_DEVICE(P) \ ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ && (P)[1] == ':')# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))# define IS_PATH_WITH_DIR(P) \ (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))#else /* Unix */# define ISSLASH(C) ((C) == '/')# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)#endif/* XPG3 defines the result of `setlocale (category, NULL)' as: ``Directs `setlocale()' to query `category' and return the current setting of `local'.'' However it does not specify the exact format. Neither do SUSV2 and ISO C 99. So we can use this feature only on selected systems (e.g. those using GNU C Library). */#if defined _LIBC || (defined __GNU_LIBRARY__ && __GNU_LIBRARY__ >= 2)# define HAVE_LOCALE_NULL#endif/* This is the type used for the search tree where known translations are stored. */struct known_translation_t{ /* Domain in which to search. */ char *domainname; /* The category. */ int category; /* State of the catalog counter at the point the string was found. */ int counter; /* Catalog where the string was found. */ struct loaded_l10nfile *domain; /* And finally the translation. */ const char *translation; size_t translation_length; /* Pointer to the string in question. */ char msgid[ZERO];};/* Root of the search tree with known translations. We can use this only if the system provides the `tsearch' function family. */#if defined HAVE_TSEARCH || defined _LIBC# include <search.h>static void *root;# ifdef _LIBC# define tsearch __tsearch# endif/* Function to compare two entries in the table of known translations. */static int transcmp PARAMS ((const void *p1, const void *p2));static inttranscmp (p1, p2) const void *p1; const void *p2;{ const struct known_translation_t *s1; const struct known_translation_t *s2; int result; s1 = (const struct known_translation_t *) p1; s2 = (const struct known_translation_t *) p2; result = strcmp (s1->msgid, s2->msgid); if (result == 0) { result = strcmp (s1->domainname, s2->domainname); if (result == 0) /* We compare the category last (though this is the cheapest operation) since it is hopefully always the same (namely LC_MESSAGES). */ result = s1->category - s2->category; } return result;}#endif/* Name of the default domain used for gettext(3) prior any call to textdomain(3). The default value for this is "messages". */const char _nl_default_default_domain[] = "messages";/* Value used as the default domain for gettext(3). */const char *_nl_current_default_domain = _nl_default_default_domain;/* Contains the default location of the message catalogs. */const char _nl_default_dirname[] = LOCALEDIR;/* List with bindings of specific domains created by bindtextdomain() calls. */struct binding *_nl_domain_bindings;/* Prototypes for local functions. */static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain, unsigned long int n, const char *translation, size_t translation_len)) internal_function;static unsigned long int plural_eval PARAMS ((struct expression *pexp, unsigned long int n)) internal_function;static const char *category_to_name PARAMS ((int category)) internal_function;static const char *guess_category_value PARAMS ((int category, const char *categoryname)) internal_function;/* For those loosing systems which don't have `alloca' we have to add some additional code emulating it. */#ifdef HAVE_ALLOCA/* Nothing has to be done. */# define ADD_BLOCK(list, address) /* nothing */# define FREE_BLOCKS(list) /* nothing */#elsestruct block_list{ void *address; struct block_list *next;};# define ADD_BLOCK(list, addr) \ do { \ struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \ /* If we cannot get a free block we cannot add the new element to \ the list. */ \ if (newp != NULL) { \ newp->address = (addr); \ newp->next = (list); \ (list) = newp; \ } \ } while (0)# define FREE_BLOCKS(list) \ do { \ while (list != NULL) { \ struct block_list *old = list; \ list = list->next; \ free (old); \ } \ } while (0)# undef alloca# define alloca(size) (malloc (size))#endif /* have alloca */#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 dcigettext__#endif/* Lock variable to protect the global data in the gettext implementation. */#ifdef _LIBC__libc_rwlock_define_initialized (, _nl_state_lock)#endif/* 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/* 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. */char *DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category) const char *domainname; const char *msgid1; const char *msgid2; int plural; unsigned long int n; int category;{#ifndef HAVE_ALLOCA struct block_list *block_list = NULL;#endif struct loaded_l10nfile *domain; struct binding *binding; const char *categoryname; const char *categoryvalue; char *dirname, *xdomainname; char *single_locale; char *retval; size_t retlen;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -