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