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