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 * 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 * 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 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 * 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 * 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 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 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 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 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