71 |
# undef HAVE_MMAP |
# undef HAVE_MMAP |
72 |
#endif |
#endif |
73 |
|
|
74 |
#include "gettext.h" |
#include "gmo.h" |
75 |
#include "gettextP.h" |
#include "gettextP.h" |
76 |
|
#include "plural-exp.h" |
77 |
|
|
78 |
#ifdef _LIBC |
#ifdef _LIBC |
79 |
# include "../locale/localeinfo.h" |
# include "../locale/localeinfo.h" |
92 |
# define munmap __munmap |
# define munmap __munmap |
93 |
#endif |
#endif |
94 |
|
|
|
/* 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 PLURAL_PARSE __gettextparse |
|
|
#else |
|
|
# define PLURAL_PARSE gettextparse__ |
|
|
#endif |
|
|
|
|
95 |
/* For those losing systems which don't have `alloca' we have to add |
/* For those losing systems which don't have `alloca' we have to add |
96 |
some additional code emulating it. */ |
some additional code emulating it. */ |
97 |
#ifdef HAVE_ALLOCA |
#ifdef HAVE_ALLOCA |
123 |
cached by one of GCC's features. */ |
cached by one of GCC's features. */ |
124 |
int _nl_msg_cat_cntr; |
int _nl_msg_cat_cntr; |
125 |
|
|
|
#if (defined __GNUC__ && !defined __APPLE_CC__) \ |
|
|
|| (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) |
|
|
|
|
|
/* These structs are the constant expression for the germanic plural |
|
|
form determination. It represents the expression "n != 1". */ |
|
|
static const struct expression plvar = |
|
|
{ |
|
|
.nargs = 0, |
|
|
.operation = var, |
|
|
}; |
|
|
static const struct expression plone = |
|
|
{ |
|
|
.nargs = 0, |
|
|
.operation = num, |
|
|
.val = |
|
|
{ |
|
|
.num = 1 |
|
|
} |
|
|
}; |
|
|
static struct expression germanic_plural = |
|
|
{ |
|
|
.nargs = 2, |
|
|
.operation = not_equal, |
|
|
.val = |
|
|
{ |
|
|
.args = |
|
|
{ |
|
|
[0] = (struct expression *) &plvar, |
|
|
[1] = (struct expression *) &plone |
|
|
} |
|
|
} |
|
|
}; |
|
|
|
|
|
# define INIT_GERMANIC_PLURAL() |
|
|
|
|
|
#else |
|
|
|
|
|
/* For compilers without support for ISO C 99 struct/union initializers: |
|
|
Initialization at run-time. */ |
|
|
|
|
|
static struct expression plvar; |
|
|
static struct expression plone; |
|
|
static struct expression germanic_plural; |
|
|
|
|
|
static void |
|
|
init_germanic_plural () |
|
|
{ |
|
|
if (plone.val.num == 0) |
|
|
{ |
|
|
plvar.nargs = 0; |
|
|
plvar.operation = var; |
|
|
|
|
|
plone.nargs = 0; |
|
|
plone.operation = num; |
|
|
plone.val.num = 1; |
|
|
|
|
|
germanic_plural.nargs = 2; |
|
|
germanic_plural.operation = not_equal; |
|
|
germanic_plural.val.args[0] = &plvar; |
|
|
germanic_plural.val.args[1] = &plone; |
|
|
} |
|
|
} |
|
|
|
|
|
# define INIT_GERMANIC_PLURAL() init_germanic_plural () |
|
|
|
|
|
#endif |
|
|
|
|
126 |
|
|
127 |
/* Initialize the codeset dependent parts of an opened message catalog. |
/* Initialize the codeset dependent parts of an opened message catalog. |
128 |
Return the header entry. */ |
Return the header entry. */ |
195 |
outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string; |
outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string; |
196 |
# else |
# else |
197 |
# if HAVE_ICONV |
# if HAVE_ICONV |
198 |
extern const char *locale_charset (void); |
extern const char *locale_charset PARAMS ((void)); |
199 |
outcharset = locale_charset (); |
outcharset = locale_charset (); |
200 |
# endif |
# endif |
201 |
# endif |
# endif |
212 |
domain->conv = (__gconv_t) -1; |
domain->conv = (__gconv_t) -1; |
213 |
# else |
# else |
214 |
# if HAVE_ICONV |
# if HAVE_ICONV |
215 |
/* When using GNU libiconv, we want to use transliteration. */ |
/* When using GNU libc >= 2.2 or GNU libiconv >= 1.5, |
216 |
# if _LIBICONV_VERSION >= 0x0105 |
we want to use transliteration. */ |
217 |
|
# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \ |
218 |
|
|| _LIBICONV_VERSION >= 0x0105 |
219 |
len = strlen (outcharset); |
len = strlen (outcharset); |
220 |
{ |
{ |
221 |
char *tmp = (char *) alloca (len + 10 + 1); |
char *tmp = (char *) alloca (len + 10 + 1); |
225 |
} |
} |
226 |
# endif |
# endif |
227 |
domain->conv = iconv_open (outcharset, charset); |
domain->conv = iconv_open (outcharset, charset); |
228 |
# if _LIBICONV_VERSION >= 0x0105 |
# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \ |
229 |
|
|| _LIBICONV_VERSION >= 0x0105 |
230 |
freea (outcharset); |
freea (outcharset); |
231 |
# endif |
# endif |
232 |
# endif |
# endif |
418 |
nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding); |
nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding); |
419 |
|
|
420 |
/* Also look for a plural specification. */ |
/* Also look for a plural specification. */ |
421 |
if (nullentry != NULL) |
EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals); |
|
{ |
|
|
const char *plural; |
|
|
const char *nplurals; |
|
|
|
|
|
plural = strstr (nullentry, "plural="); |
|
|
nplurals = strstr (nullentry, "nplurals="); |
|
|
if (plural == NULL || nplurals == NULL) |
|
|
goto no_plural; |
|
|
else |
|
|
{ |
|
|
/* First get the number. */ |
|
|
char *endp; |
|
|
unsigned long int n; |
|
|
struct parse_args args; |
|
|
|
|
|
nplurals += 9; |
|
|
while (*nplurals != '\0' && isspace (*nplurals)) |
|
|
++nplurals; |
|
|
#if defined HAVE_STRTOUL || defined _LIBC |
|
|
n = strtoul (nplurals, &endp, 10); |
|
|
#else |
|
|
for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++) |
|
|
n = n * 10 + (*endp - '0'); |
|
|
#endif |
|
|
domain->nplurals = n; |
|
|
if (nplurals == endp) |
|
|
goto no_plural; |
|
|
|
|
|
/* Due to the restrictions bison imposes onto the interface of the |
|
|
scanner function we have to put the input string and the result |
|
|
passed up from the parser into the same structure which address |
|
|
is passed down to the parser. */ |
|
|
plural += 7; |
|
|
args.cp = plural; |
|
|
if (PLURAL_PARSE (&args) != 0) |
|
|
goto no_plural; |
|
|
domain->plural = args.res; |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
/* By default we are using the Germanic form: singular form only |
|
|
for `one', the plural form otherwise. Yes, this is also what |
|
|
English is using since English is a Germanic language. */ |
|
|
no_plural: |
|
|
INIT_GERMANIC_PLURAL (); |
|
|
domain->plural = &germanic_plural; |
|
|
domain->nplurals = 2; |
|
|
} |
|
422 |
} |
} |
423 |
|
|
424 |
|
|
428 |
_nl_unload_domain (domain) |
_nl_unload_domain (domain) |
429 |
struct loaded_domain *domain; |
struct loaded_domain *domain; |
430 |
{ |
{ |
431 |
if (domain->plural != &germanic_plural) |
if (domain->plural != &__gettext_germanic_plural) |
432 |
__gettext_free_exp (domain->plural); |
__gettext_free_exp (domain->plural); |
433 |
|
|
434 |
_nl_free_domain_conv (domain); |
_nl_free_domain_conv (domain); |