iconv: Bail out of the loop when an illegal sequence of bytes occurs.
[elinks/elinks-j605.git] / src / intl / gettext / plural.y
blobd63715d177c965358c2bbdf9aaaddc2a7860919f
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.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 This program 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
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 /* The bison generated parser uses alloca. AIX 3 forces us to put this
21 declaration at the beginning of the file. The declaration in bison's
22 skeleton file comes too late. This must come before <config.h>
23 because <config.h> may include arbitrary system headers. */
24 #if defined _AIX && !defined __GNUC__
25 #pragma alloca
26 #endif
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
32 #include <stdlib.h>
33 #include "intl/gettext/gettextP.h"
35 #define YYLEX_PARAM &((struct parse_args *) arg)->cp
36 #define YYPARSE_PARAM arg
38 %pure_parser
39 %expect 7
41 %union {
42 unsigned long int num;
43 enum operator op;
44 struct expression *exp;
48 /* Prototypes for local functions. */
49 static struct expression *new_exp(int nargs, enum operator op,
50 struct expression * const *args);
51 static inline struct expression *new_exp_0(enum operator op);
52 static inline struct expression *new_exp_1(enum operator op,
53 struct expression *right);
54 static struct expression *new_exp_2(enum operator op,
55 struct expression *left,
56 struct expression *right);
57 static inline struct expression *new_exp_3(enum operator op,
58 struct expression *bexp,
59 struct expression *tbranch,
60 struct expression *fbranch);
61 static int yylex(YYSTYPE *lval, const unsigned char **pexp);
62 static void yyerror(const unsigned char *str);
64 /* Allocation of expressions. */
66 static struct expression *
67 new_exp(int nargs, enum operator op, struct expression * const *args)
69 int i;
70 struct expression *newp;
72 /* If any of the argument could not be malloc'ed, just return NULL. */
73 for (i = nargs - 1; i >= 0; i--)
74 if (args[i] == NULL)
75 goto fail;
77 /* Allocate a new expression. */
78 newp = (struct expression *) malloc (sizeof (*newp));
79 if (newp != NULL)
81 newp->nargs = nargs;
82 newp->operation = op;
83 for (i = nargs - 1; i >= 0; i--)
84 newp->val.args[i] = args[i];
85 return newp;
88 fail:
89 for (i = nargs - 1; i >= 0; i--)
90 gettext_free_exp__ (args[i]);
92 return NULL;
95 static inline struct expression *
96 new_exp_0(enum operator op)
98 return new_exp (0, op, NULL);
101 static inline struct expression *
102 new_exp_1(enum operator op, struct expression *right)
104 struct expression *args[1];
106 args[0] = right;
107 return new_exp (1, op, args);
110 static struct expression *
111 new_exp_2(enum operator op, struct expression *left, struct expression *right)
113 struct expression *args[2];
115 args[0] = left;
116 args[1] = right;
117 return new_exp (2, op, args);
120 static inline struct expression *
121 new_exp_3(enum operator op, struct expression *bexp, struct expression *tbranch,
122 struct expression *fbranch)
124 struct expression *args[3];
126 args[0] = bexp;
127 args[1] = tbranch;
128 args[2] = fbranch;
129 return new_exp (3, op, args);
134 /* This declares that all operators have the same associativity and the
135 precedence order as in C. See [Harbison, Steele: C, A Reference Manual].
136 There is no unary minus and no bitwise operators.
137 Operators with the same syntactic behaviour have been merged into a single
138 token, to save space in the array generated by bison. */
139 %right '?' /* ? */
140 %left '|' /* || */
141 %left '&' /* && */
142 %left EQUOP2 /* == != */
143 %left CMPOP2 /* < > <= >= */
144 %left ADDOP2 /* + - */
145 %left MULOP2 /* * / % */
146 %right '!' /* ! */
148 %token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
149 %token <num> NUMBER
150 %type <exp> exp
154 start: exp
156 if ($1 == NULL)
157 YYABORT;
158 ((struct parse_args *) arg)->res = $1;
162 exp: exp '?' exp ':' exp
164 $$ = new_exp_3 (qmop, $1, $3, $5);
166 | exp '|' exp
168 $$ = new_exp_2 (lor, $1, $3);
170 | exp '&' exp
172 $$ = new_exp_2 (land, $1, $3);
174 | exp EQUOP2 exp
176 $$ = new_exp_2 ($2, $1, $3);
178 | exp CMPOP2 exp
180 $$ = new_exp_2 ($2, $1, $3);
182 | exp ADDOP2 exp
184 $$ = new_exp_2 ($2, $1, $3);
186 | exp MULOP2 exp
188 $$ = new_exp_2 ($2, $1, $3);
190 | '!' exp
192 $$ = new_exp_1 (lnot, $2);
194 | 'n'
196 $$ = new_exp_0 (var);
198 | NUMBER
200 if (($$ = new_exp_0 (num)) != NULL)
201 $$->val.num = $1;
203 | '(' exp ')'
205 $$ = $2;
211 void
212 gettext_free_exp__(struct expression *exp)
214 if (exp == NULL)
215 return;
217 /* Handle the recursive case. */
218 switch (exp->nargs)
220 case 3:
221 gettext_free_exp__ (exp->val.args[2]);
222 /* FALLTHROUGH */
223 case 2:
224 gettext_free_exp__ (exp->val.args[1]);
225 /* FALLTHROUGH */
226 case 1:
227 gettext_free_exp__ (exp->val.args[0]);
228 /* FALLTHROUGH */
229 default:
230 break;
233 free (exp);
237 static int
238 yylex(YYSTYPE *lval, const unsigned char **pexp)
240 const unsigned char *exp = *pexp;
241 int result;
243 while (1)
245 if (exp[0] == '\0')
247 *pexp = exp;
248 return YYEOF;
251 if (exp[0] != ' ' && exp[0] != '\t')
252 break;
254 ++exp;
257 result = *exp++;
258 switch (result)
260 case '0': case '1': case '2': case '3': case '4':
261 case '5': case '6': case '7': case '8': case '9':
263 unsigned long int n = result - '0';
264 while (exp[0] >= '0' && exp[0] <= '9')
266 n *= 10;
267 n += exp[0] - '0';
268 ++exp;
270 lval->num = n;
271 result = NUMBER;
273 break;
275 case '=':
276 if (exp[0] == '=')
278 ++exp;
279 lval->op = equal;
280 result = EQUOP2;
282 else
283 result = YYERRCODE;
284 break;
286 case '!':
287 if (exp[0] == '=')
289 ++exp;
290 lval->op = not_equal;
291 result = EQUOP2;
293 break;
295 case '&':
296 case '|':
297 if (exp[0] == result)
298 ++exp;
299 else
300 result = YYERRCODE;
301 break;
303 case '<':
304 if (exp[0] == '=')
306 ++exp;
307 lval->op = less_or_equal;
309 else
310 lval->op = less_than;
311 result = CMPOP2;
312 break;
314 case '>':
315 if (exp[0] == '=')
317 ++exp;
318 lval->op = greater_or_equal;
320 else
321 lval->op = greater_than;
322 result = CMPOP2;
323 break;
325 case '*':
326 lval->op = mult;
327 result = MULOP2;
328 break;
330 case '/':
331 lval->op = divide;
332 result = MULOP2;
333 break;
335 case '%':
336 lval->op = module;
337 result = MULOP2;
338 break;
340 case '+':
341 lval->op = plus;
342 result = ADDOP2;
343 break;
345 case '-':
346 lval->op = minus;
347 result = ADDOP2;
348 break;
350 case 'n':
351 case '?':
352 case ':':
353 case '(':
354 case ')':
355 /* Nothing, just return the character. */
356 break;
358 case ';':
359 case '\n':
360 case '\0':
361 /* Be safe and let the user call this function again. */
362 --exp;
363 result = YYEOF;
364 break;
366 default:
367 result = YYERRCODE;
368 #if YYDEBUG != 0
369 --exp;
370 #endif
371 break;
374 *pexp = exp;
376 return result;
380 static void
381 yyerror(const unsigned char *str)
383 /* Do nothing. We don't print error messages here. */