1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Updated to 0.12.1

This commit is contained in:
Werner Koch 2003-10-25 16:34:36 +00:00
parent 8ed48ad2f8
commit d30da9ebdc
24 changed files with 2608 additions and 1309 deletions

View file

@ -1,5 +1,5 @@
/* Implementation of the internal dcigettext function.
Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
Copyright (C) 1995-1999, 2000-2003 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
@ -33,14 +33,19 @@
# define alloca __builtin_alloca
# define HAVE_ALLOCA 1
#else
# if defined HAVE_ALLOCA_H || defined _LIBC
# include <alloca.h>
# ifdef _MSC_VER
# include <malloc.h>
# define alloca _alloca
# else
# ifdef _AIX
#pragma alloca
# if defined HAVE_ALLOCA_H || defined _LIBC
# include <alloca.h>
# else
# ifndef alloca
# ifdef _AIX
#pragma alloca
# else
# ifndef alloca
char *alloca ();
# endif
# endif
# endif
# endif
@ -56,13 +61,7 @@ extern int errno;
#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>
@ -70,11 +69,26 @@ extern int errno;
#include <locale.h>
#ifdef _LIBC
/* Guess whether integer division by zero raises signal SIGFPE.
Set to 1 only if you know for sure. In case of doubt, set to 0. */
# if defined __alpha__ || defined __arm__ || defined __i386__ \
|| defined __m68k__ || defined __s390__
# define INTDIV0_RAISES_SIGFPE 1
# else
# define INTDIV0_RAISES_SIGFPE 0
# endif
#endif
#if !INTDIV0_RAISES_SIGFPE
# include <signal.h>
#endif
#if defined HAVE_SYS_PARAM_H || defined _LIBC
# include <sys/param.h>
#endif
#include "gettextP.h"
#include "plural-exp.h"
#ifdef _LIBC
# include <libintl.h>
#else
@ -107,10 +121,10 @@ extern int errno;
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__
# define _nl_default_default_domain libintl_nl_default_default_domain
# define _nl_current_default_domain libintl_nl_current_default_domain
# define _nl_default_dirname libintl_nl_default_dirname
# define _nl_domain_bindings libintl_nl_domain_bindings
#endif
/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
@ -198,16 +212,6 @@ static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
# 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
@ -272,15 +276,28 @@ transcmp (p1, p2)
}
#endif
#ifndef INTVARDEF
# define INTVARDEF(name)
#endif
#ifndef INTUSE
# define INTUSE(name) name
#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";
const char _nl_default_default_domain[] attribute_hidden = "messages";
/* Value used as the default domain for gettext(3). */
const char *_nl_current_default_domain = _nl_default_default_domain;
const char *_nl_current_default_domain attribute_hidden
= _nl_default_default_domain;
/* Contains the default location of the message catalogs. */
#if defined __EMX__
extern const char _nl_default_dirname[];
#else
const char _nl_default_dirname[] = LOCALEDIR;
INTVARDEF (_nl_default_dirname)
#endif
/* List with bindings of specific domains created by bindtextdomain()
calls. */
@ -292,19 +309,22 @@ static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain,
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;
#ifdef _LIBC
# include "../locale/localeinfo.h"
# define category_to_name(category) _nl_category_names[category]
#else
static const char *category_to_name PARAMS ((int category)) internal_function;
#endif
/* 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 freea(p) /* nothing */
# define ADD_BLOCK(list, address) /* nothing */
# define FREE_BLOCKS(list) /* nothing */
#else
@ -329,11 +349,13 @@ struct block_list
while (list != NULL) { \
struct block_list *old = list; \
list = list->next; \
free (old->address); \
free (old); \
} \
} while (0)
# undef alloca
# define alloca(size) (malloc (size))
# define freea(p) free (p)
#endif /* have alloca */
@ -357,12 +379,12 @@ typedef unsigned char transmem_block_t;
#ifdef _LIBC
# define DCIGETTEXT __dcigettext
#else
# define DCIGETTEXT dcigettext__
# define DCIGETTEXT libintl_dcigettext
#endif
/* Lock variable to protect the global data in the gettext implementation. */
#ifdef _LIBC
__libc_rwlock_define_initialized (, _nl_state_lock)
__libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
#endif
/* Checking whether the binaries runs SUID must be done and glibc provides
@ -395,6 +417,9 @@ static int enable_secure;
}
#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. */
@ -430,6 +455,15 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
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
__libc_rwlock_rdlock (_nl_state_lock);
/* If DOMAINNAME is NULL, we are interested in the default domain. If
@ -438,6 +472,12 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
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;
@ -450,6 +490,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
search->category = category;
foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
freea (search);
if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
{
/* Now deal with plural. */
@ -486,7 +527,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
}
if (binding == NULL)
dirname = (char *) _nl_default_dirname;
dirname = (char *) INTUSE(_nl_default_dirname);
else if (IS_ABSOLUTE_PATH (binding->dirname))
dirname = binding->dirname;
else
@ -514,17 +555,9 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
}
if (ret == NULL)
{
/* We cannot get the current working directory. Don't signal an
error but simply return the default string. */
FREE_BLOCKS (block_list);
__libc_rwlock_unlock (_nl_state_lock);
__set_errno (saved_errno);
return (plural == 0
? (char *) msgid1
/* Use the Germanic plural rule. */
: n == 1 ? (char *) msgid1 : (char *) msgid2);
}
/* We cannot get the current working directory. Don't signal an
error but simply return the default string. */
goto return_untranslated;
stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
}
@ -581,16 +614,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
domain. Return the MSGID. */
if (strcmp (single_locale, "C") == 0
|| strcmp (single_locale, "POSIX") == 0)
{
FREE_BLOCKS (block_list);
__libc_rwlock_unlock (_nl_state_lock);
__set_errno (saved_errno);
return (plural == 0
? (char *) msgid1
/* Use the Germanic plural rule. */
: n == 1 ? (char *) msgid1 : (char *) msgid2);
}
break;
/* Find structure describing the message catalog matching the
DOMAINNAME and CATEGORY. */
@ -622,7 +646,6 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
/* Found the translation of MSGID1 in domain DOMAIN:
starting at RETVAL, RETLEN bytes. */
FREE_BLOCKS (block_list);
__set_errno (saved_errno);
#if defined HAVE_TSEARCH || defined _LIBC
if (foundp == NULL)
{
@ -661,6 +684,8 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
(*foundp)->translation_length = retlen;
}
#endif
__set_errno (saved_errno);
/* Now deal with plural. */
if (plural)
retval = plural_lookup (domain, n, retval, retlen);
@ -670,7 +695,30 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
}
}
}
/* NOTREACHED */
return_untranslated:
/* Return the untranslated MSGID. */
FREE_BLOCKS (block_list);
__libc_rwlock_unlock (_nl_state_lock);
#ifndef _LIBC
if (!ENABLE_SECURE)
{
extern void _nl_log_untranslated PARAMS ((const char *logfilename,
const char *domainname,
const char *msgid1,
const char *msgid2,
int plural));
const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED");
if (logfilename != NULL && logfilename[0] != '\0')
_nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural);
}
#endif
__set_errno (saved_errno);
return (plural == 0
? (char *) msgid1
/* Use the Germanic plural rule. */
: n == 1 ? (char *) msgid1 : (char *) msgid2);
}
@ -683,6 +731,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
size_t *lengthp;
{
struct loaded_domain *domain;
nls_uint32 nstrings;
size_t act;
char *result;
size_t resultlen;
@ -695,8 +744,10 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
domain = (struct loaded_domain *) domain_file->data;
nstrings = domain->nstrings;
/* Locate the MSGID and its translation. */
if (domain->hash_size > 2 && domain->hash_tab != NULL)
if (domain->hash_tab != NULL)
{
/* Use the hashing table. */
nls_uint32 len = strlen (msgid);
@ -706,22 +757,30 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
while (1)
{
nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
nls_uint32 nstr =
W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
if (nstr == 0)
/* Hash table entry is empty. */
return NULL;
/* Compare msgid with the original string at index nstr-1.
nstr--;
/* Compare msgid with the original string at index nstr.
We compare the lengths with >=, not ==, because plural entries
are represented by strings with an embedded NUL. */
if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) >= len
&& (strcmp (msgid,
domain->data + W (domain->must_swap,
domain->orig_tab[nstr - 1].offset))
== 0))
if (nstr < nstrings
? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
&& (strcmp (msgid,
domain->data + W (domain->must_swap,
domain->orig_tab[nstr].offset))
== 0)
: domain->orig_sysdep_tab[nstr - nstrings].length > len
&& (strcmp (msgid,
domain->orig_sysdep_tab[nstr - nstrings].pointer)
== 0))
{
act = nstr - 1;
act = nstr;
goto found;
}
@ -739,7 +798,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
size_t top, bottom;
bottom = 0;
top = domain->nstrings;
top = nstrings;
while (bottom < top)
{
int cmp_val;
@ -762,9 +821,17 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
found:
/* The translation was found at index ACT. If we have to convert the
string to use a different character set, this is the time. */
result = ((char *) domain->data
+ W (domain->must_swap, domain->trans_tab[act].offset));
resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
if (act < nstrings)
{
result = (char *)
(domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
}
else
{
result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
resultlen = domain->trans_sysdep_tab[act - nstrings].length;
}
#if defined _LIBC || HAVE_ICONV
if (domain->codeset_cntr
@ -797,8 +864,9 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
NULs. */
if (domain->conv_tab == NULL
&& ((domain->conv_tab = (char **) calloc (domain->nstrings,
sizeof (char *)))
&& ((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;
@ -974,18 +1042,18 @@ plural_lookup (domain, n, translation, translation_len)
size_t translation_len;
{
struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
unsigned long int ind; /* gnupg */
unsigned long int index;
const char *p;
ind = plural_eval (domaindata->plural, n); /* gnupg */
if (ind >= domaindata->nplurals) /* gnupg */
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. */
ind = 0; /* gnupg */
index = 0;
/* Skip INDEX strings at TRANSLATION. */
p = translation;
while (ind-- > 0) /* gnupg */
while (index-- > 0)
{
#ifdef _LIBC
p = __rawmemchr (p, '\0');
@ -1004,88 +1072,7 @@ plural_lookup (domain, n, translation, translation_len)
return (char *) p;
}
/* Function to evaluate the plural expression and return an index value. */
static unsigned long int
internal_function
plural_eval (pexp, n)
struct expression *pexp;
unsigned long int n;
{
switch (pexp->nargs)
{
case 0:
switch (pexp->operation)
{
case var:
return n;
case num:
return pexp->val.num;
default:
break;
}
/* NOTREACHED */
break;
case 1:
{
/* pexp->operation must be lnot. */
unsigned long int arg = plural_eval (pexp->val.args[0], n);
return ! arg;
}
case 2:
{
unsigned long int leftarg = plural_eval (pexp->val.args[0], n);
if (pexp->operation == lor)
return leftarg || plural_eval (pexp->val.args[1], n);
else if (pexp->operation == land)
return leftarg && plural_eval (pexp->val.args[1], n);
else
{
unsigned long int rightarg = plural_eval (pexp->val.args[1], n);
switch (pexp->operation)
{
case mult:
return leftarg * rightarg;
case divide:
return leftarg / rightarg;
case module:
return leftarg % rightarg;
case plus:
return leftarg + rightarg;
case minus:
return leftarg - rightarg;
case less_than:
return leftarg < rightarg;
case greater_than:
return leftarg > rightarg;
case less_or_equal:
return leftarg <= rightarg;
case greater_or_equal:
return leftarg >= rightarg;
case equal:
return leftarg == rightarg;
case not_equal:
return leftarg != rightarg;
default:
break;
}
}
/* NOTREACHED */
break;
}
case 3:
{
/* pexp->operation must be qmop. */
unsigned long int boolarg = plural_eval (pexp->val.args[0], n);
return plural_eval (pexp->val.args[boolarg ? 1 : 2], n);
}
}
/* NOTREACHED */
return 0;
}
#ifndef _LIBC
/* Return string representation of locale CATEGORY. */
static const char *
internal_function
@ -1145,6 +1132,7 @@ category_to_name (category)
return retval;
}
#endif
/* Guess value of current locale from value of the environment variables. */
static const char *
@ -1166,27 +1154,21 @@ guess_category_value (category, categoryname)
/* We have to proceed with the POSIX methods of looking to `LC_ALL',
`LC_xxx', and `LANG'. On some systems this can be done by the
`setlocale' function itself. */
#if defined _LIBC || (defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL)
retval = setlocale (category, NULL);
#ifdef _LIBC
retval = __current_locale_name (category);
#else
/* Setting of LC_ALL overwrites all other. */
retval = getenv ("LC_ALL");
if (retval == NULL || retval[0] == '\0')
{
/* Next comes the name of the desired category. */
retval = getenv (categoryname);
if (retval == NULL || retval[0] == '\0')
{
/* Last possibility is the LANG environment variable. */
retval = getenv ("LANG");
if (retval == NULL || retval[0] == '\0')
/* We use C as the default domain. POSIX says this is
implementation defined. */
return "C";
}
}
retval = _nl_locale_name (category, categoryname);
#endif
/* Ignore LANGUAGE 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". We allow such programs to use gettext(). */
return language != NULL && strcmp (retval, "C") != 0 ? language : retval;
}
@ -1223,8 +1205,7 @@ mempcpy (dest, src, n)
#ifdef _LIBC
/* If we want to free all resources we have to do some work at
program's end. */
static void __attribute__ ((unused))
free_mem (void)
libc_freeres_fn (free_mem)
{
void *old;
@ -1232,7 +1213,7 @@ free_mem (void)
{
struct binding *oldp = _nl_domain_bindings;
_nl_domain_bindings = _nl_domain_bindings->next;
if (oldp->dirname != _nl_default_dirname)
if (oldp->dirname != INTUSE(_nl_default_dirname))
/* Yes, this is a pointer comparison. */
free (oldp->dirname);
free (oldp->codeset);
@ -1254,6 +1235,4 @@ free_mem (void)
free (old);
}
}
text_set_element (__libc_subfreeres, free_mem);
#endif