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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 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 "synonyms.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 * 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 * 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 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 * 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 * 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 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 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 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 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