xref: /netbsd-src/external/gpl3/gcc.old/dist/intl/plural-exp.c (revision 36ac495d2b3ea2b9d96377b2143ebfedac224b92)
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