1*36ac495dSmrg /* Expression parsing for plural form selection.
2*36ac495dSmrg Copyright (C) 2000, 2001 Free Software Foundation, Inc.
3*36ac495dSmrg Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
4*36ac495dSmrg
5*36ac495dSmrg This program is free software; you can redistribute it and/or modify it
6*36ac495dSmrg under the terms of the GNU Library General Public License as published
7*36ac495dSmrg by the Free Software Foundation; either version 2, or (at your option)
8*36ac495dSmrg any later version.
9*36ac495dSmrg
10*36ac495dSmrg This program is distributed in the hope that it will be useful,
11*36ac495dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
12*36ac495dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13*36ac495dSmrg Library General Public License for more details.
14*36ac495dSmrg
15*36ac495dSmrg You should have received a copy of the GNU Library General Public
16*36ac495dSmrg License along with this program; if not, write to the Free Software
17*36ac495dSmrg Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301,
18*36ac495dSmrg USA. */
19*36ac495dSmrg
20*36ac495dSmrg #ifdef HAVE_CONFIG_H
21*36ac495dSmrg # include <config.h>
22*36ac495dSmrg #endif
23*36ac495dSmrg
24*36ac495dSmrg #include <ctype.h>
25*36ac495dSmrg #include <stdlib.h>
26*36ac495dSmrg #include <string.h>
27*36ac495dSmrg
28*36ac495dSmrg #include "plural-exp.h"
29*36ac495dSmrg
30*36ac495dSmrg #if (defined __GNUC__ && !defined __APPLE_CC__) \
31*36ac495dSmrg || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
32*36ac495dSmrg
33*36ac495dSmrg /* These structs are the constant expression for the germanic plural
34*36ac495dSmrg form determination. It represents the expression "n != 1". */
35*36ac495dSmrg static const struct expression plvar =
36*36ac495dSmrg {
37*36ac495dSmrg .nargs = 0,
38*36ac495dSmrg .operation = var,
39*36ac495dSmrg };
40*36ac495dSmrg static const struct expression plone =
41*36ac495dSmrg {
42*36ac495dSmrg .nargs = 0,
43*36ac495dSmrg .operation = num,
44*36ac495dSmrg .val =
45*36ac495dSmrg {
46*36ac495dSmrg .num = 1
47*36ac495dSmrg }
48*36ac495dSmrg };
49*36ac495dSmrg struct expression GERMANIC_PLURAL =
50*36ac495dSmrg {
51*36ac495dSmrg .nargs = 2,
52*36ac495dSmrg .operation = not_equal,
53*36ac495dSmrg .val =
54*36ac495dSmrg {
55*36ac495dSmrg .args =
56*36ac495dSmrg {
57*36ac495dSmrg [0] = (struct expression *) &plvar,
58*36ac495dSmrg [1] = (struct expression *) &plone
59*36ac495dSmrg }
60*36ac495dSmrg }
61*36ac495dSmrg };
62*36ac495dSmrg
63*36ac495dSmrg # define INIT_GERMANIC_PLURAL()
64*36ac495dSmrg
65*36ac495dSmrg #else
66*36ac495dSmrg
67*36ac495dSmrg /* For compilers without support for ISO C 99 struct/union initializers:
68*36ac495dSmrg Initialization at run-time. */
69*36ac495dSmrg
70*36ac495dSmrg static struct expression plvar;
71*36ac495dSmrg static struct expression plone;
72*36ac495dSmrg struct expression GERMANIC_PLURAL;
73*36ac495dSmrg
74*36ac495dSmrg static void
init_germanic_plural()75*36ac495dSmrg init_germanic_plural ()
76*36ac495dSmrg {
77*36ac495dSmrg if (plone.val.num == 0)
78*36ac495dSmrg {
79*36ac495dSmrg plvar.nargs = 0;
80*36ac495dSmrg plvar.operation = var;
81*36ac495dSmrg
82*36ac495dSmrg plone.nargs = 0;
83*36ac495dSmrg plone.operation = num;
84*36ac495dSmrg plone.val.num = 1;
85*36ac495dSmrg
86*36ac495dSmrg GERMANIC_PLURAL.nargs = 2;
87*36ac495dSmrg GERMANIC_PLURAL.operation = not_equal;
88*36ac495dSmrg GERMANIC_PLURAL.val.args[0] = &plvar;
89*36ac495dSmrg GERMANIC_PLURAL.val.args[1] = &plone;
90*36ac495dSmrg }
91*36ac495dSmrg }
92*36ac495dSmrg
93*36ac495dSmrg # define INIT_GERMANIC_PLURAL() init_germanic_plural ()
94*36ac495dSmrg
95*36ac495dSmrg #endif
96*36ac495dSmrg
97*36ac495dSmrg void
98*36ac495dSmrg internal_function
EXTRACT_PLURAL_EXPRESSION(nullentry,pluralp,npluralsp)99*36ac495dSmrg EXTRACT_PLURAL_EXPRESSION (nullentry, pluralp, npluralsp)
100*36ac495dSmrg const char *nullentry;
101*36ac495dSmrg struct expression **pluralp;
102*36ac495dSmrg unsigned long int *npluralsp;
103*36ac495dSmrg {
104*36ac495dSmrg if (nullentry != NULL)
105*36ac495dSmrg {
106*36ac495dSmrg const char *plural;
107*36ac495dSmrg const char *nplurals;
108*36ac495dSmrg
109*36ac495dSmrg plural = strstr (nullentry, "plural=");
110*36ac495dSmrg nplurals = strstr (nullentry, "nplurals=");
111*36ac495dSmrg if (plural == NULL || nplurals == NULL)
112*36ac495dSmrg goto no_plural;
113*36ac495dSmrg else
114*36ac495dSmrg {
115*36ac495dSmrg char *endp;
116*36ac495dSmrg unsigned long int n;
117*36ac495dSmrg struct parse_args args;
118*36ac495dSmrg
119*36ac495dSmrg /* First get the number. */
120*36ac495dSmrg nplurals += 9;
121*36ac495dSmrg while (*nplurals != '\0' && isspace ((unsigned char) *nplurals))
122*36ac495dSmrg ++nplurals;
123*36ac495dSmrg if (!(*nplurals >= '0' && *nplurals <= '9'))
124*36ac495dSmrg goto no_plural;
125*36ac495dSmrg #if defined HAVE_STRTOUL || defined _LIBC
126*36ac495dSmrg n = strtoul (nplurals, &endp, 10);
127*36ac495dSmrg #else
128*36ac495dSmrg for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
129*36ac495dSmrg n = n * 10 + (*endp - '0');
130*36ac495dSmrg #endif
131*36ac495dSmrg if (nplurals == endp)
132*36ac495dSmrg goto no_plural;
133*36ac495dSmrg *npluralsp = n;
134*36ac495dSmrg
135*36ac495dSmrg /* Due to the restrictions bison imposes onto the interface of the
136*36ac495dSmrg scanner function we have to put the input string and the result
137*36ac495dSmrg passed up from the parser into the same structure which address
138*36ac495dSmrg is passed down to the parser. */
139*36ac495dSmrg plural += 7;
140*36ac495dSmrg args.cp = plural;
141*36ac495dSmrg if (PLURAL_PARSE (&args) != 0)
142*36ac495dSmrg goto no_plural;
143*36ac495dSmrg *pluralp = args.res;
144*36ac495dSmrg }
145*36ac495dSmrg }
146*36ac495dSmrg else
147*36ac495dSmrg {
148*36ac495dSmrg /* By default we are using the Germanic form: singular form only
149*36ac495dSmrg for `one', the plural form otherwise. Yes, this is also what
150*36ac495dSmrg English is using since English is a Germanic language. */
151*36ac495dSmrg no_plural:
152*36ac495dSmrg INIT_GERMANIC_PLURAL ();
153*36ac495dSmrg *pluralp = &GERMANIC_PLURAL;
154*36ac495dSmrg *npluralsp = 2;
155*36ac495dSmrg }
156*36ac495dSmrg }
157