1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include "lint.h"
28 #include <ctype.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include "libc.h"
32 #include "gettext.h"
33
34 #include "plural_parser.h"
35
36 /*
37 * 31 28 24 20 16 12 8 4 0
38 * +-----+-----+-----+-----+-----+-----+-----+-----+
39 * |opnum| priority | operator |
40 * +-----+-----+-----+-----+-----+-----+-----+-----+
41 */
42 static const unsigned int operator[] = {
43 0x00000000, /* NULL */
44 0x00000001, /* INIT */
45 0x00100002, /* EXP */
46 0x00200003, /* NUM */
47 0x00300004, /* VAR */
48 0x30400005, /* CONDC */
49 0x30500006, /* CONDQ */
50 0x20600007, /* OR */
51 0x20700008, /* AND */
52 0x20800009, /* EQ */
53 0x2080000a, /* NEQ */
54 0x2090000b, /* GT */
55 0x2090000c, /* LT */
56 0x2090000d, /* GE */
57 0x2090000e, /* LE */
58 0x20a0000f, /* ADD */
59 0x20a00010, /* SUB */
60 0x20b00011, /* MUL */
61 0x20b00012, /* DIV */
62 0x20b00013, /* MOD */
63 0x10c00014, /* NOT */
64 0x00d00015, /* LPAR */
65 0x00e00016, /* RPAR */
66 0x00000017 /* ERR */
67 };
68
69 #define STACKFREE \
70 { \
71 while (stk->index > 0) \
72 freeexpr(stk->ptr[--stk->index]); \
73 free(stk->ptr); \
74 }
75
76 #ifdef PARSE_DEBUG
77 static const char *type_name[] = {
78 "T_NULL",
79 "T_INIT", "T_EXP", "T_NUM", "T_VAR", "T_CONDC", "T_CONDQ",
80 "T_LOR", "T_LAND", "T_EQ", "T_NEQ", "T_GT", "T_LT", "T_GE", "T_LE",
81 "T_ADD", "T_SUB", "T_MUL", "T_DIV", "T_MOD", "T_LNOT", "T_LPAR",
82 "T_RPAR", "T_ERR"
83 };
84 #endif
85
86 static void freeexpr(struct expr *);
87
88 static struct expr *
stack_push(struct stack * stk,struct expr * exp)89 stack_push(struct stack *stk, struct expr *exp)
90 {
91 #ifdef PARSE_DEBUG
92 printf("--- stack_push ---\n");
93 printf(" type: %s\n", type_name[GETTYPE(exp->op)]);
94 printf(" flag: %s\n", type_name[GETTYPE(exp->flag)]);
95 printf("------------------\n");
96 #endif
97 stk->ptr[stk->index++] = exp;
98 if (stk->index == MAX_STACK_SIZE) {
99 /* overflow */
100 freeexpr(exp);
101 STACKFREE;
102 return (NULL);
103 }
104
105 return (exp);
106 }
107
108 static struct expr *
stack_pop(struct stack * stk,struct expr * exp_a,struct expr * exp_b)109 stack_pop(struct stack *stk, struct expr *exp_a, struct expr *exp_b)
110 {
111 if (stk->index == 0) {
112 /* no item */
113 if (exp_a)
114 freeexpr(exp_a);
115 if (exp_b)
116 freeexpr(exp_b);
117 STACKFREE;
118 return (NULL);
119 }
120 #ifdef PARSE_DEBUG
121 printf("--- stack_pop ---\n");
122 printf(" type: %s\n",
123 type_name[GETTYPE((stk->ptr[stk->index - 1])->op)]);
124 printf(" flag: %s\n",
125 type_name[GETTYPE((stk->ptr[stk->index - 1])->flag)]);
126 printf("-----------------\n");
127 #endif
128 return (stk->ptr[--stk->index]);
129 }
130
131 static void
freeexpr(struct expr * e)132 freeexpr(struct expr *e)
133 {
134 #ifdef PARSE_DEBUG
135 printf("--- freeexpr ---\n");
136 printf(" type: %s\n", type_name[GETTYPE(e->op)]);
137 printf("----------------\n");
138 #endif
139 switch (GETOPNUM(e->op)) {
140 case TRINARY:
141 if (e->nodes[2])
142 freeexpr(e->nodes[2]);
143 /* FALLTHROUGH */
144 case BINARY:
145 if (e->nodes[1])
146 freeexpr(e->nodes[1]);
147 /* FALLTHROUGH */
148 case UNARY:
149 if (e->nodes[0])
150 freeexpr(e->nodes[0]);
151 /* FALLTHROUGH */
152 default:
153 break;
154 }
155 free(e);
156 }
157
158 static struct expr *
setop1(unsigned int op,unsigned int num,struct stack * stk,unsigned int flag)159 setop1(unsigned int op, unsigned int num,
160 struct stack *stk, unsigned int flag)
161 {
162 struct expr *newitem;
163 unsigned int type;
164
165 type = GETTYPE(op);
166
167 #ifdef PARSE_DEBUG
168 printf("---setop1---\n");
169 printf(" op type: %s\n", type_name[type]);
170 printf("-----------\n");
171 #endif
172
173 newitem = (struct expr *)calloc(1, sizeof (struct expr));
174 if (!newitem) {
175 STACKFREE;
176 return (NULL);
177 }
178 newitem->op = op;
179 if (type == T_NUM)
180 newitem->num = num;
181 newitem->flag = flag;
182 return (newitem);
183 }
184
185 static struct expr *
setop_reduce(unsigned int n,unsigned int op,struct stack * stk,struct expr * exp1,struct expr * exp2,struct expr * exp3)186 setop_reduce(unsigned int n, unsigned int op, struct stack *stk,
187 struct expr *exp1, struct expr *exp2, struct expr *exp3)
188 {
189 struct expr *newitem;
190 #ifdef PARSE_DEBUG
191 unsigned int type;
192
193 type = GETTYPE(op);
194 printf("---setop_reduce---\n");
195 printf(" n: %d\n", n);
196 printf(" op type: %s\n", type_name[type]);
197 switch (n) {
198 case TRINARY:
199 printf(" exp3 type: %s\n", type_name[GETTYPE(exp3->op)]);
200 case BINARY:
201 printf(" exp2 type: %s\n", type_name[GETTYPE(exp2->op)]);
202 case UNARY:
203 printf(" exp1 type: %s\n", type_name[GETTYPE(exp1->op)]);
204 case NARY:
205 break;
206 }
207 printf("-----------\n");
208 #endif
209
210 newitem = (struct expr *)calloc(1, sizeof (struct expr));
211 if (!newitem) {
212 if (exp1)
213 freeexpr(exp1);
214 if (exp2)
215 freeexpr(exp2);
216 if (exp3)
217 freeexpr(exp3);
218 STACKFREE;
219 return (NULL);
220 }
221 newitem->op = op;
222
223 switch (n) {
224 case TRINARY:
225 newitem->nodes[2] = exp3;
226 /* FALLTHROUGH */
227 case BINARY:
228 newitem->nodes[1] = exp2;
229 /* FALLTHROUGH */
230 case UNARY:
231 newitem->nodes[0] = exp1;
232 /* FALLTHROUGH */
233 case NARY:
234 break;
235 }
236 return (newitem);
237 }
238
239 static int
reduce(struct expr ** nexp,unsigned int n,struct expr * exp,struct stack * stk)240 reduce(struct expr **nexp, unsigned int n, struct expr *exp, struct stack *stk)
241 {
242 struct expr *exp_op, *exp1, *exp2, *exp3;
243 unsigned int tmp_flag;
244 unsigned int oop;
245 #ifdef PARSE_DEBUG
246 printf("---reduce---\n");
247 printf(" n: %d\n", n);
248 printf("-----------\n");
249 #endif
250
251 switch (n) {
252 case UNARY:
253 /* unary operator */
254 exp1 = exp;
255 exp_op = stack_pop(stk, exp1, NULL);
256 if (!exp_op)
257 return (1);
258 tmp_flag = exp_op->flag;
259 oop = exp_op->op;
260 freeexpr(exp_op);
261 *nexp = setop_reduce(UNARY, oop, stk, exp1, NULL, NULL);
262 if (!*nexp)
263 return (-1);
264 (*nexp)->flag = tmp_flag;
265 return (0);
266 case BINARY:
267 /* binary operator */
268 exp2 = exp;
269 exp_op = stack_pop(stk, exp2, NULL);
270 if (!exp_op)
271 return (1);
272 exp1 = stack_pop(stk, exp_op, exp2);
273 if (!exp1)
274 return (1);
275 tmp_flag = exp1->flag;
276 oop = exp_op->op;
277 freeexpr(exp_op);
278 *nexp = setop_reduce(BINARY, oop, stk, exp1, exp2, NULL);
279 if (!*nexp)
280 return (-1);
281 (*nexp)->flag = tmp_flag;
282 return (0);
283 case TRINARY:
284 /* trinary operator: conditional */
285 exp3 = exp;
286 exp_op = stack_pop(stk, exp3, NULL);
287 if (!exp_op)
288 return (1);
289 freeexpr(exp_op);
290 exp2 = stack_pop(stk, exp3, NULL);
291 if (!exp2)
292 return (1);
293 exp_op = stack_pop(stk, exp2, exp3);
294 if (!exp_op)
295 return (1);
296 if (GETTYPE(exp_op->op) != T_CONDQ) {
297 /* parse failed */
298 freeexpr(exp_op);
299 freeexpr(exp2);
300 freeexpr(exp3);
301 STACKFREE;
302 return (1);
303 }
304 oop = exp_op->op;
305 freeexpr(exp_op);
306 exp1 = stack_pop(stk, exp2, exp3);
307 if (!exp1)
308 return (1);
309
310 tmp_flag = exp1->flag;
311 *nexp = setop_reduce(TRINARY, oop, stk, exp1, exp2, exp3);
312 if (!*nexp)
313 return (-1);
314 (*nexp)->flag = tmp_flag;
315 return (0);
316 }
317 /* NOTREACHED */
318 return (0); /* keep gcc happy */
319 }
320
321 static unsigned int
gettoken(const char ** pstr,unsigned int * num,int which)322 gettoken(const char **pstr, unsigned int *num, int which)
323 {
324 unsigned char *sp = *(unsigned char **)pstr;
325 unsigned int n;
326 unsigned int ret;
327
328 while (*sp && ((*sp == ' ') || (*sp == '\t')))
329 sp++;
330 if (!*sp) {
331 if (which == GET_TOKEN)
332 *pstr = (const char *)sp;
333 return (T_NULL);
334 }
335
336 if (isdigit(*sp)) {
337 n = *sp - '0';
338 sp++;
339 while (isdigit(*sp)) {
340 n *= 10;
341 n += *sp - '0';
342 sp++;
343 }
344 *num = n;
345 ret = T_NUM;
346 } else if (*sp == 'n') {
347 sp++;
348 ret = T_VAR;
349 } else if (*sp == '(') {
350 sp++;
351 ret = T_LPAR;
352 } else if (*sp == ')') {
353 sp++;
354 ret = T_RPAR;
355 } else if (*sp == '!') {
356 sp++;
357 if (*sp == '=') {
358 sp++;
359 ret = T_NEQ;
360 } else {
361 ret = T_LNOT;
362 }
363 } else if (*sp == '*') {
364 sp++;
365 ret = T_MUL;
366 } else if (*sp == '/') {
367 sp++;
368 ret = T_DIV;
369 } else if (*sp == '%') {
370 sp++;
371 ret = T_MOD;
372 } else if (*sp == '+') {
373 sp++;
374 ret = T_ADD;
375 } else if (*sp == '-') {
376 sp++;
377 ret = T_SUB;
378 } else if (*sp == '<') {
379 sp++;
380 if (*sp == '=') {
381 sp++;
382 ret = T_LE;
383 } else {
384 ret = T_LT;
385 }
386 } else if (*sp == '>') {
387 sp++;
388 if (*sp == '=') {
389 sp++;
390 ret = T_GE;
391 } else {
392 ret = T_GT;
393 }
394 } else if (*sp == '=') {
395 sp++;
396 if (*sp == '=') {
397 sp++;
398 ret = T_EQ;
399 } else {
400 ret = T_ERR;
401 }
402 } else if (*sp == '&') {
403 sp++;
404 if (*sp == '&') {
405 sp++;
406 ret = T_LAND;
407 } else {
408 ret = T_ERR;
409 }
410 } else if (*sp == '|') {
411 sp++;
412 if (*sp == '|') {
413 sp++;
414 ret = T_LOR;
415 } else {
416 ret = T_ERR;
417 }
418 } else if (*sp == '?') {
419 sp++;
420 ret = T_CONDQ;
421 } else if (*sp == ':') {
422 sp++;
423 ret = T_CONDC;
424 } else if ((*sp == '\n') || (*sp == ';')) {
425 ret = T_NULL;
426 } else {
427 ret = T_ERR;
428 }
429 if (which == GET_TOKEN)
430 *pstr = (const char *)sp;
431 return (operator[ret]);
432 }
433
434 /*
435 * plural_expr
436 *
437 * INPUT
438 * str: string to parse
439 *
440 * OUTPUT
441 * e: parsed expression
442 *
443 * RETURN
444 * -1: Error happend (malloc failed)
445 * 1: Parse failed (invalid expression)
446 * 0: Parse succeeded
447 */
448 int
plural_expr(struct expr ** e,const char * plural_string)449 plural_expr(struct expr **e, const char *plural_string)
450 {
451 const char *pstr = plural_string;
452 struct stack *stk, stkbuf;
453 struct expr *exp, *nexp, *exp_op, *ret;
454 int par, result;
455 unsigned int flag, ftype, fprio, fopnum, tmp_flag;
456 unsigned int ntype, nprio, ptype, popnum;
457 unsigned int op, nop, num, type, opnum;
458
459 stk = &stkbuf;
460 stk->index = 0;
461 stk->ptr = malloc(sizeof (struct expr *) * MAX_STACK_SIZE);
462 if (!stk->ptr) {
463 /* malloc failed */
464 return (-1);
465 }
466
467 flag = operator[T_INIT];
468 par = 0;
469 while ((op = gettoken(&pstr, &num, GET_TOKEN)) != T_NULL) {
470 type = GETTYPE(op);
471 opnum = GETOPNUM(op);
472 ftype = GETTYPE(flag);
473
474 #ifdef PARSE_DEBUG
475 printf("*** %s ***\n", type_name[type]);
476 printf(" flag: %s\n", type_name[ftype]);
477 printf(" par: %d\n", par);
478 printf("***********\n");
479 #endif
480 if (type == T_ERR) {
481 /* parse failed */
482 STACKFREE;
483 return (1);
484 }
485 if (opnum == BINARY) {
486 /* binary operation */
487 if (ftype != T_EXP) {
488 /* parse failed */
489 #ifdef PARSE_DEBUG
490 printf("ERR: T_EXP is not followed by %s\n",
491 type_name[type]);
492 #endif
493 STACKFREE;
494 return (1);
495 }
496 exp = setop1(op, 0, stk, flag);
497 if (!exp)
498 return (-1);
499 ret = stack_push(stk, exp);
500 if (!ret)
501 return (1);
502 flag = op;
503 continue; /* while-loop */
504 }
505
506 if (type == T_CONDQ) {
507 /* conditional operation: '?' */
508 if (ftype != T_EXP) {
509 /* parse failed */
510 #ifdef PARSE_DEBUG
511 printf("ERR: T_EXP is not followed by %s\n",
512 type_name[type]);
513 #endif
514 STACKFREE;
515 return (1);
516 }
517 exp = setop1(op, 0, stk, flag);
518 if (!exp)
519 return (-1);
520 ret = stack_push(stk, exp);
521 if (!ret)
522 return (1);
523 flag = op;
524 continue; /* while-loop */
525 }
526 if (type == T_CONDC) {
527 /* conditional operation: ':' */
528 if (ftype != T_EXP) {
529 /* parse failed */
530 #ifdef PARSE_DEBUG
531 printf("ERR: T_EXP is not followed by %s\n",
532 type_name[type]);
533 #endif
534 STACKFREE;
535 return (1);
536 }
537 exp = setop1(op, 0, stk, flag);
538 if (!exp)
539 return (-1);
540 ret = stack_push(stk, exp);
541 if (!ret)
542 return (1);
543 flag = op;
544 continue; /* while-loop */
545 }
546
547 if (type == T_LPAR) {
548 /* left parenthesis */
549 if (ftype == T_EXP) {
550 /* parse failed */
551 #ifdef PARSE_DEBUG
552 printf("ERR: T_EXP is followed by %s\n",
553 type_name[type]);
554 #endif
555 STACKFREE;
556 return (1);
557 }
558 exp = setop1(op, 0, stk, flag);
559 if (!exp)
560 return (-1);
561 ret = stack_push(stk, exp);
562 if (!ret)
563 return (1);
564 par++;
565 flag = op;
566 continue; /* while-loop */
567 }
568 if (type == T_RPAR) {
569 /* right parenthesis */
570 if (ftype != T_EXP) {
571 /* parse failed */
572 #ifdef PARSE_DEBUG
573 printf("ERR: T_EXP is not followed by %s\n",
574 type_name[type]);
575 #endif
576 STACKFREE;
577 return (1);
578 }
579 par--;
580 if (par < 0) {
581 /* parse failed */
582 #ifdef PARSE_DEBUG
583 printf("ERR: too much T_RPAR\n");
584 #endif
585 STACKFREE;
586 return (1);
587 }
588 exp = stack_pop(stk, NULL, NULL);
589 if (!exp)
590 return (1);
591
592 #ifdef PARSE_DEBUG
593 printf("======================== RPAR for loop in\n");
594 #endif
595 for (; ; ) {
596 ptype = GETTYPE(exp->flag);
597 popnum = GETOPNUM(exp->flag);
598
599 #ifdef PARSE_DEBUG
600 printf("=========== exp->flag: %s\n",
601 type_name[ptype]);
602 #endif
603 if (ptype == T_LPAR) {
604 exp_op = stack_pop(stk, exp, NULL);
605 if (!exp_op)
606 return (1);
607
608 tmp_flag = exp_op->flag;
609 freeexpr(exp_op);
610
611 exp->flag = tmp_flag;
612 flag = tmp_flag;
613 break; /* break from for-loop */
614 }
615
616 if ((popnum == BINARY) ||
617 (ptype == T_LNOT) ||
618 (ptype == T_CONDC)) {
619 result = reduce(&nexp, popnum,
620 exp, stk);
621 if (result)
622 return (result);
623 exp = nexp;
624 continue; /* for-loop */
625 }
626 /* parse failed */
627 freeexpr(exp);
628 STACKFREE;
629 return (1);
630 } /* for-loop */
631
632 #ifdef PARSE_DEBUG
633 printf("========================= RPAR for loop out\n");
634 #endif
635 /*
636 * Needs to check if exp can be reduced or not
637 */
638 goto exp_check;
639 }
640
641 if (type == T_LNOT) {
642 if (ftype == T_EXP) {
643 /* parse failed */
644 #ifdef PARSE_DEBUG
645 printf("ERR: T_EXP is followed by %s\n",
646 type_name[type]);
647 #endif
648 STACKFREE;
649 return (1);
650 }
651 exp = setop1(op, 0, stk, flag);
652 if (!exp)
653 return (-1);
654 ret = stack_push(stk, exp);
655 if (!ret)
656 return (1);
657 flag = op;
658 continue; /* while-loop */
659 }
660 if ((type == T_NUM) || (type == T_VAR)) {
661 exp = setop1(op, type == T_NUM ? num : 0, stk, flag);
662 if (!exp)
663 return (-1);
664 exp_check:
665 ftype = GETTYPE(flag);
666 if ((ftype == T_INIT) || (ftype == T_LPAR)) {
667 /*
668 * if this NUM/VAR is the first EXP,
669 * just push this
670 */
671 exp->flag = flag;
672 ret = stack_push(stk, exp);
673 if (!ret)
674 return (1);
675 flag = operator[T_EXP];
676 continue; /* while-loop */
677 }
678 if (ftype == T_EXP) {
679 /*
680 * parse failed
681 * NUM/VAR cannot be seen just after
682 * T_EXP
683 */
684 freeexpr(exp);
685 STACKFREE;
686 return (1);
687 }
688
689 nop = gettoken(&pstr, &num, PEEK_TOKEN);
690 if (nop != T_NULL) {
691 ntype = GETTYPE(nop);
692 nprio = GETPRIO(nop);
693 } else {
694 (void) gettoken(&pstr, &num, GET_TOKEN);
695 ntype = T_INIT;
696 nprio = 0;
697 }
698 #ifdef PARSE_DEBUG
699 printf("========================== T_NUM/T_VAR for loop in\n");
700 #endif
701 for (; ; ) {
702 ftype = GETTYPE(flag);
703 fopnum = GETOPNUM(flag);
704 fprio = GETPRIO(flag);
705 #ifdef PARSE_DEBUG
706 printf("========= flag: %s\n",
707 type_name[ftype]);
708 #endif
709 if ((ftype == T_INIT) || (ftype == T_LPAR)) {
710 exp->flag = flag;
711 ret = stack_push(stk, exp);
712 if (!ret)
713 return (1);
714 flag = operator[T_EXP];
715 break; /* exit from for-loop */
716 }
717
718 if (ftype == T_LNOT) {
719 /* LNOT is the strongest */
720 result = reduce(&nexp, UNARY, exp, stk);
721 if (result)
722 return (result);
723 exp = nexp;
724 flag = nexp->flag;
725 continue; /* for-loop */
726 }
727
728 if (fopnum == BINARY) {
729 /*
730 * binary operation
731 * T_MUL, T_ADD, T_CMP,
732 * T_EQ, T_LAND, T_LOR
733 */
734 if ((ntype == T_RPAR) ||
735 (nprio <= fprio)) {
736 /* reduce */
737 result = reduce(&nexp, BINARY,
738 exp, stk);
739 if (result)
740 return (result);
741 exp = nexp;
742 flag = nexp->flag;
743 continue; /* for-loop */
744 }
745 /* shift */
746 exp->flag = flag;
747 ret = stack_push(stk, exp);
748 if (!ret)
749 return (1);
750 flag = operator[T_EXP];
751 break; /* exit from for loop */
752 }
753
754 if (ftype == T_CONDQ) {
755 /*
756 * CONDQ is the weakest
757 * always shift
758 */
759 exp->flag = flag;
760 ret = stack_push(stk, exp);
761 if (!ret)
762 return (1);
763 flag = operator[T_EXP];
764 break; /* exit from for loop */
765 }
766 if (ftype == T_CONDC) {
767 if (nprio <= fprio) {
768 /* reduce */
769 result = reduce(&nexp, TRINARY,
770 exp, stk);
771 if (result)
772 return (result);
773 exp = nexp;
774 flag = nexp->flag;
775 continue; /* for-loop */
776 }
777 /* shift */
778 exp->flag = flag;
779 ret = stack_push(stk, exp);
780 if (!ret)
781 return (1);
782 flag = operator[T_EXP];
783 break; /* exit from for-loop */
784 }
785 /* parse failed */
786 freeexpr(exp);
787 STACKFREE;
788 return (1);
789 }
790
791 #ifdef PARSE_DEBUG
792 printf("======================= T_NUM/T_VAR for loop out\n");
793 #endif
794 continue; /* while-loop */
795 }
796 /* parse failed */
797 STACKFREE;
798 return (1);
799 } /* while-loop */
800
801 if (GETTYPE(flag) != T_EXP) {
802 /* parse failed */
803 #ifdef PARSE_DEBUG
804 printf("XXXX ERROR: flag is not T_INIT\n");
805 printf("========= flag: %s\n", type_name[GETTYPE(flag)]);
806 #endif
807 STACKFREE;
808 return (1);
809 } else {
810 exp = stack_pop(stk, NULL, NULL);
811 if (!exp)
812 return (1);
813
814 if (GETTYPE(exp->flag) != T_INIT) {
815 /* parse failed */
816 #ifdef PARSE_DEBUG
817 printf("ERR: flag for the result is not T_INIT\n");
818 printf(" %s observed\n",
819 type_name[GETTYPE(exp->flag)]);
820 #endif
821 freeexpr(exp);
822 STACKFREE;
823 return (1);
824 }
825 if (stk->index > 0) {
826 /*
827 * exp still remains in stack.
828 * parse failed
829 */
830 while ((nexp = stack_pop(stk, NULL, NULL)) != NULL)
831 freeexpr(nexp);
832 freeexpr(exp);
833 return (1);
834 }
835
836 /* parse succeeded */
837 *e = exp;
838 STACKFREE;
839 return (0);
840 }
841 }
842
843 unsigned int
plural_eval(struct expr * exp,unsigned int n)844 plural_eval(struct expr *exp, unsigned int n)
845 {
846 unsigned int e1, e2;
847 unsigned int type, opnum;
848 #ifdef GETTEXT_DEBUG
849 (void) printf("*************** plural_eval(%p, %d)\n", exp, n);
850 printexpr(exp, 0);
851 #endif
852
853 type = GETTYPE(exp->op);
854 opnum = GETOPNUM(exp->op);
855
856 switch (opnum) {
857 case NARY:
858 if (type == T_NUM) {
859 return (exp->num);
860 } else if (type == T_VAR) {
861 return (n);
862 }
863 break;
864 case UNARY:
865 /* T_LNOT */
866 e1 = plural_eval(exp->nodes[0], n);
867 return (!e1);
868 case BINARY:
869 e1 = plural_eval(exp->nodes[0], n);
870 /* optimization for T_LOR and T_LAND */
871 if (type == T_LOR) {
872 return (e1 || plural_eval(exp->nodes[1], n));
873 } else if (type == T_LAND) {
874 return (e1 && plural_eval(exp->nodes[1], n));
875 }
876 e2 = plural_eval(exp->nodes[1], n);
877 switch (type) {
878 case T_EQ:
879 return (e1 == e2);
880 case T_NEQ:
881 return (e1 != e2);
882 case T_GT:
883 return (e1 > e2);
884 case T_LT:
885 return (e1 < e2);
886 case T_GE:
887 return (e1 >= e2);
888 case T_LE:
889 return (e1 <= e2);
890 case T_ADD:
891 return (e1 + e2);
892 case T_SUB:
893 return (e1 - e2);
894 case T_MUL:
895 return (e1 * e2);
896 case T_DIV:
897 if (e2 != 0)
898 return (e1 / e2);
899 break;
900 case T_MOD:
901 if (e2 != 0)
902 return (e1 % e2);
903 break;
904 }
905 break;
906 case TRINARY:
907 /* T_CONDQ */
908 e1 = plural_eval(exp->nodes[0], n);
909 if (e1) {
910 return (plural_eval(exp->nodes[1], n));
911 } else {
912 return (plural_eval(exp->nodes[2], n));
913 }
914 }
915 /* should not be here */
916 return (0);
917 }
918