xref: /netbsd-src/external/gpl2/grep/dist/intl/plural-exp.c (revision a8fa202a6440953be7b92a8960a811bff58203f4)
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