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