(set_binding_values): Initialize ->codeset_cntr to 0.
[kopensolaris-gnu/glibc.git] / intl / plural.y
1 %{
2 /* Expression parsing for plural form selection.
3    Copyright (C) 2000, 2001 Free Software Foundation, Inc.
4    Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public
17    License along with the GNU C Library; see the file COPYING.LIB.  If not,
18    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <stdlib.h>
26 #include "gettextP.h"
27
28 /* Names for the libintl functions are a problem.  They must not clash
29    with existing names and they should follow ANSI C.  But this source
30    code is also used in GNU C Library where the names have a __
31    prefix.  So we have to make a difference here.  */
32 #ifdef _LIBC
33 # define FREE_EXPRESSION __gettext_free_exp
34 #else
35 # define FREE_EXPRESSION gettext_free_exp__
36 # define __gettextparse gettextparse__
37 #endif
38
39 #define YYLEX_PARAM     &((struct parse_args *) arg)->cp
40 #define YYPARSE_PARAM   arg
41 %}
42 %pure_parser
43 %expect 10
44
45 %union {
46   unsigned long int num;
47   enum operator op;
48   struct expression *exp;
49 }
50
51 %{
52 /* Prototypes for local functions.  */
53 static struct expression *new_exp PARAMS ((int nargs, enum operator op,
54                                            struct expression * const *args));
55 static inline struct expression *new_exp_0 PARAMS ((enum operator op));
56 static inline struct expression *new_exp_1 PARAMS ((enum operator op,
57                                                    struct expression *right));
58 static struct expression *new_exp_2 PARAMS ((enum operator op,
59                                              struct expression *left,
60                                              struct expression *right));
61 static inline struct expression *new_exp_3 PARAMS ((enum operator op,
62                                                    struct expression *bexp,
63                                                    struct expression *tbranch,
64                                                    struct expression *fbranch));
65 static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
66 static void yyerror PARAMS ((const char *str));
67
68 /* Allocation of expressions.  */
69
70 static struct expression *
71 new_exp (nargs, op, args)
72      int nargs;
73      enum operator op;
74      struct expression * const *args;
75 {
76   int i;
77   struct expression *newp;
78
79   /* If any of the argument could not be malloc'ed, just return NULL.  */
80   for (i = nargs - 1; i >= 0; i--)
81     if (args[i] == NULL)
82       goto fail;
83
84   /* Allocate a new expression.  */
85   newp = (struct expression *) malloc (sizeof (*newp));
86   if (newp != NULL)
87     {
88       newp->nargs = nargs;
89       newp->operation = op;
90       for (i = nargs - 1; i >= 0; i--)
91         newp->val.args[i] = args[i];
92       return newp;
93     }
94
95  fail:
96   for (i = nargs - 1; i >= 0; i--)
97     FREE_EXPRESSION (args[i]);
98
99   return NULL;
100 }
101
102 static inline struct expression *
103 new_exp_0 (op)
104      enum operator op;
105 {
106   return new_exp (0, op, NULL);
107 }
108
109 static inline struct expression *
110 new_exp_1 (op, right)
111      enum operator op;
112      struct expression *right;
113 {
114   struct expression *args[1];
115
116   args[0] = right;
117   return new_exp (1, op, args);
118 }
119
120 static struct expression *
121 new_exp_2 (op, left, right)
122      enum operator op;
123      struct expression *left;
124      struct expression *right;
125 {
126   struct expression *args[2];
127
128   args[0] = left;
129   args[1] = right;
130   return new_exp (2, op, args);
131 }
132
133 static inline struct expression *
134 new_exp_3 (op, bexp, tbranch, fbranch)
135      enum operator op;
136      struct expression *bexp;
137      struct expression *tbranch;
138      struct expression *fbranch;
139 {
140   struct expression *args[3];
141
142   args[0] = bexp;
143   args[1] = tbranch;
144   args[2] = fbranch;
145   return new_exp (3, op, args);
146 }
147
148 %}
149
150 /* This declares that all operators have the same associativity and the
151    precedence order as in C.  See [Harbison, Steele: C, A Reference Manual].
152    There is no unary minus and no bitwise operators.
153    Operators with the same syntactic behaviour have been merged into a single
154    token, to save space in the array generated by bison.  */
155 %right '?'              /*   ?          */
156 %left '|'               /*   ||         */
157 %left '&'               /*   &&         */
158 %left EQUOP2            /*   == !=      */
159 %left CMPOP2            /*   < > <= >=  */
160 %left ADDOP2            /*   + -        */
161 %left MULOP2            /*   * / %      */
162 %right '!'              /*   !          */
163
164 %token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
165 %token <num> NUMBER
166 %type <exp> exp
167
168 %%
169
170 start:    exp
171           {
172             if ($1 == NULL)
173               YYABORT;
174             ((struct parse_args *) arg)->res = $1;
175           }
176         ;
177
178 exp:      exp '?' exp ':' exp
179           {
180             $$ = new_exp_3 (qmop, $1, $3, $5);
181           }
182         | exp '|' exp
183           {
184             $$ = new_exp_2 (lor, $1, $3);
185           }
186         | exp '&' exp
187           {
188             $$ = new_exp_2 (land, $1, $3);
189           }
190         | exp EQUOP2 exp
191           {
192             $$ = new_exp_2 ($2, $1, $3);
193           }
194         | exp CMPOP2 exp
195           {
196             $$ = new_exp_2 ($2, $1, $3);
197           }
198         | exp ADDOP2 exp
199           {
200             $$ = new_exp_2 ($2, $1, $3);
201           }
202         | exp MULOP2 exp
203           {
204             $$ = new_exp_2 ($2, $1, $3);
205           }
206         | '!' exp
207           {
208             $$ = new_exp_1 (lnot, $2);
209           }
210         | 'n'
211           {
212             $$ = new_exp_0 (var);
213           }
214         | NUMBER
215           {
216             if (($$ = new_exp_0 (num)) != NULL)
217               $$->val.num = $1;
218           }
219         | '(' exp ')'
220           {
221             $$ = $2;
222           }
223         ;
224
225 %%
226
227 void
228 internal_function
229 FREE_EXPRESSION (exp)
230      struct expression *exp;
231 {
232   if (exp == NULL)
233     return;
234
235   /* Handle the recursive case.  */
236   switch (exp->nargs)
237     {
238     case 3:
239       FREE_EXPRESSION (exp->val.args[2]);
240       /* FALLTHROUGH */
241     case 2:
242       FREE_EXPRESSION (exp->val.args[1]);
243       /* FALLTHROUGH */
244     case 1:
245       FREE_EXPRESSION (exp->val.args[0]);
246       /* FALLTHROUGH */
247     default:
248       break;
249     }
250
251   free (exp);
252 }
253
254
255 static int
256 yylex (lval, pexp)
257      YYSTYPE *lval;
258      const char **pexp;
259 {
260   const char *exp = *pexp;
261   int result;
262
263   while (1)
264     {
265       if (exp[0] == '\0')
266         {
267           *pexp = exp;
268           return YYEOF;
269         }
270
271       if (exp[0] != ' ' && exp[0] != '\t')
272         break;
273
274       ++exp;
275     }
276
277   result = *exp++;
278   switch (result)
279     {
280     case '0': case '1': case '2': case '3': case '4':
281     case '5': case '6': case '7': case '8': case '9':
282       {
283         unsigned long int n = result - '0';
284         while (exp[0] >= '0' && exp[0] <= '9')
285           {
286             n *= 10;
287             n += exp[0] - '0';
288             ++exp;
289           }
290         lval->num = n;
291         result = NUMBER;
292       }
293       break;
294
295     case '=':
296       if (exp[0] == '=')
297         {
298           ++exp;
299           lval->op = equal;
300           result = EQUOP2;
301         }
302       else
303         result = YYERRCODE;
304       break;
305
306     case '!':
307       if (exp[0] == '=')
308         {
309           ++exp;
310           lval->op = not_equal;
311           result = EQUOP2;
312         }
313       break;
314
315     case '&':
316     case '|':
317       if (exp[0] == result)
318         ++exp;
319       else
320         result = YYERRCODE;
321       break;
322
323     case '<':
324       if (exp[0] == '=')
325         {
326           ++exp;
327           lval->op = less_or_equal;
328         }
329       else
330         lval->op = less_than;
331       result = CMPOP2;
332       break;
333
334     case '>':
335       if (exp[0] == '=')
336         {
337           ++exp;
338           lval->op = greater_or_equal;
339         }
340       else
341         lval->op = greater_than;
342       result = CMPOP2;
343       break;
344
345     case '*':
346       lval->op = mult;
347       result = MULOP2;
348       break;
349
350     case '/':
351       lval->op = divide;
352       result = MULOP2;
353       break;
354
355     case '%':
356       lval->op = module;
357       result = MULOP2;
358       break;
359
360     case '+':
361       lval->op = plus;
362       result = ADDOP2;
363       break;
364
365     case '-':
366       lval->op = minus;
367       result = ADDOP2;
368       break;
369
370     case 'n':
371     case '?':
372     case ':':
373     case '(':
374     case ')':
375       /* Nothing, just return the character.  */
376       break;
377
378     case ';':
379     case '\n':
380     case '\0':
381       /* Be safe and let the user call this function again.  */
382       --exp;
383       result = YYEOF;
384       break;
385
386     default:
387       result = YYERRCODE;
388 #if YYDEBUG != 0
389       --exp;
390 #endif
391       break;
392     }
393
394   *pexp = exp;
395
396   return result;
397 }
398
399
400 static void
401 yyerror (str)
402      const char *str;
403 {
404   /* Do nothing.  We don't print error messages here.  */
405 }