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