10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*6812Sraf * Common Development and Distribution License (the "License").
6*6812Sraf * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*6812Sraf
220Sstevel@tonic-gate /*
23*6812Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
29*6812Sraf #include "lint.h"
300Sstevel@tonic-gate #include <ctype.h>
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <stdlib.h>
330Sstevel@tonic-gate #include "libc.h"
340Sstevel@tonic-gate #include "gettext.h"
350Sstevel@tonic-gate
360Sstevel@tonic-gate #include "plural_parser.h"
370Sstevel@tonic-gate
380Sstevel@tonic-gate /*
390Sstevel@tonic-gate * 31 28 24 20 16 12 8 4 0
400Sstevel@tonic-gate * +-----+-----+-----+-----+-----+-----+-----+-----+
410Sstevel@tonic-gate * |opnum| priority | operator |
420Sstevel@tonic-gate * +-----+-----+-----+-----+-----+-----+-----+-----+
430Sstevel@tonic-gate */
440Sstevel@tonic-gate static const unsigned int operator[] = {
450Sstevel@tonic-gate 0x00000000, /* NULL */
460Sstevel@tonic-gate 0x00000001, /* INIT */
470Sstevel@tonic-gate 0x00100002, /* EXP */
480Sstevel@tonic-gate 0x00200003, /* NUM */
490Sstevel@tonic-gate 0x00300004, /* VAR */
500Sstevel@tonic-gate 0x30400005, /* CONDC */
510Sstevel@tonic-gate 0x30500006, /* CONDQ */
520Sstevel@tonic-gate 0x20600007, /* OR */
530Sstevel@tonic-gate 0x20700008, /* AND */
540Sstevel@tonic-gate 0x20800009, /* EQ */
550Sstevel@tonic-gate 0x2080000a, /* NEQ */
560Sstevel@tonic-gate 0x2090000b, /* GT */
570Sstevel@tonic-gate 0x2090000c, /* LT */
580Sstevel@tonic-gate 0x2090000d, /* GE */
590Sstevel@tonic-gate 0x2090000e, /* LE */
600Sstevel@tonic-gate 0x20a0000f, /* ADD */
610Sstevel@tonic-gate 0x20a00010, /* SUB */
620Sstevel@tonic-gate 0x20b00011, /* MUL */
630Sstevel@tonic-gate 0x20b00012, /* DIV */
640Sstevel@tonic-gate 0x20b00013, /* MOD */
650Sstevel@tonic-gate 0x10c00014, /* NOT */
660Sstevel@tonic-gate 0x00d00015, /* LPAR */
670Sstevel@tonic-gate 0x00e00016, /* RPAR */
680Sstevel@tonic-gate 0x00000017 /* ERR */
690Sstevel@tonic-gate };
700Sstevel@tonic-gate
710Sstevel@tonic-gate #define STACKFREE \
720Sstevel@tonic-gate { \
730Sstevel@tonic-gate while (stk->index > 0) \
740Sstevel@tonic-gate freeexpr(stk->ptr[--stk->index]); \
750Sstevel@tonic-gate free(stk->ptr); \
760Sstevel@tonic-gate }
770Sstevel@tonic-gate
780Sstevel@tonic-gate #ifdef PARSE_DEBUG
790Sstevel@tonic-gate static const char *type_name[] = {
800Sstevel@tonic-gate "T_NULL",
810Sstevel@tonic-gate "T_INIT", "T_EXP", "T_NUM", "T_VAR", "T_CONDC", "T_CONDQ",
820Sstevel@tonic-gate "T_LOR", "T_LAND", "T_EQ", "T_NEQ", "T_GT", "T_LT", "T_GE", "T_LE",
830Sstevel@tonic-gate "T_ADD", "T_SUB", "T_MUL", "T_DIV", "T_MOD", "T_LNOT", "T_LPAR",
840Sstevel@tonic-gate "T_RPAR", "T_ERR"
850Sstevel@tonic-gate };
860Sstevel@tonic-gate #endif
870Sstevel@tonic-gate
880Sstevel@tonic-gate static void freeexpr(struct expr *);
890Sstevel@tonic-gate
900Sstevel@tonic-gate static struct expr *
stack_push(struct stack * stk,struct expr * exp)910Sstevel@tonic-gate stack_push(struct stack *stk, struct expr *exp)
920Sstevel@tonic-gate {
930Sstevel@tonic-gate #ifdef PARSE_DEBUG
940Sstevel@tonic-gate printf("--- stack_push ---\n");
950Sstevel@tonic-gate printf(" type: %s\n", type_name[GETTYPE(exp->op)]);
960Sstevel@tonic-gate printf(" flag: %s\n", type_name[GETTYPE(exp->flag)]);
970Sstevel@tonic-gate printf("------------------\n");
980Sstevel@tonic-gate #endif
990Sstevel@tonic-gate stk->ptr[stk->index++] = exp;
1000Sstevel@tonic-gate if (stk->index == MAX_STACK_SIZE) {
1010Sstevel@tonic-gate /* overflow */
1020Sstevel@tonic-gate freeexpr(exp);
1030Sstevel@tonic-gate STACKFREE;
1040Sstevel@tonic-gate return (NULL);
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate return (exp);
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate static struct expr *
stack_pop(struct stack * stk,struct expr * exp_a,struct expr * exp_b)1110Sstevel@tonic-gate stack_pop(struct stack *stk,
1120Sstevel@tonic-gate struct expr *exp_a, struct expr *exp_b)
1130Sstevel@tonic-gate {
1140Sstevel@tonic-gate if (stk->index == 0) {
1150Sstevel@tonic-gate /* no item */
1160Sstevel@tonic-gate if (exp_a)
1170Sstevel@tonic-gate freeexpr(exp_a);
1180Sstevel@tonic-gate if (exp_b)
1190Sstevel@tonic-gate freeexpr(exp_b);
1200Sstevel@tonic-gate STACKFREE;
1210Sstevel@tonic-gate return (NULL);
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate #ifdef PARSE_DEBUG
1240Sstevel@tonic-gate printf("--- stack_pop ---\n");
1250Sstevel@tonic-gate printf(" type: %s\n",
1260Sstevel@tonic-gate type_name[GETTYPE((stk->ptr[stk->index - 1])->op)]);
1270Sstevel@tonic-gate printf(" flag: %s\n",
1280Sstevel@tonic-gate type_name[GETTYPE((stk->ptr[stk->index - 1])->flag)]);
1290Sstevel@tonic-gate printf("-----------------\n");
1300Sstevel@tonic-gate #endif
1310Sstevel@tonic-gate return (stk->ptr[--stk->index]);
1320Sstevel@tonic-gate }
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate static void
freeexpr(struct expr * e)1350Sstevel@tonic-gate freeexpr(struct expr *e)
1360Sstevel@tonic-gate {
1370Sstevel@tonic-gate #ifdef PARSE_DEBUG
1380Sstevel@tonic-gate printf("--- freeexpr ---\n");
1390Sstevel@tonic-gate printf(" type: %s\n", type_name[GETTYPE(e->op)]);
1400Sstevel@tonic-gate printf("----------------\n");
1410Sstevel@tonic-gate #endif
1420Sstevel@tonic-gate switch (GETOPNUM(e->op)) {
1430Sstevel@tonic-gate case TRINARY:
1440Sstevel@tonic-gate if (e->nodes[2])
1450Sstevel@tonic-gate freeexpr(e->nodes[2]);
1460Sstevel@tonic-gate /* FALLTHROUGH */
1470Sstevel@tonic-gate case BINARY:
1480Sstevel@tonic-gate if (e->nodes[1])
1490Sstevel@tonic-gate freeexpr(e->nodes[1]);
1500Sstevel@tonic-gate /* FALLTHROUGH */
1510Sstevel@tonic-gate case UNARY:
1520Sstevel@tonic-gate if (e->nodes[0])
1530Sstevel@tonic-gate freeexpr(e->nodes[0]);
1540Sstevel@tonic-gate /* FALLTHROUGH */
1550Sstevel@tonic-gate default:
1560Sstevel@tonic-gate break;
1570Sstevel@tonic-gate }
1580Sstevel@tonic-gate free(e);
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate static struct expr *
setop1(unsigned int op,unsigned int num,struct stack * stk,unsigned int flag)1620Sstevel@tonic-gate setop1(unsigned int op, unsigned int num,
1630Sstevel@tonic-gate struct stack *stk, unsigned int flag)
1640Sstevel@tonic-gate {
1650Sstevel@tonic-gate struct expr *newitem;
1660Sstevel@tonic-gate unsigned int type;
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate type = GETTYPE(op);
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate #ifdef PARSE_DEBUG
1710Sstevel@tonic-gate printf("---setop1---\n");
1720Sstevel@tonic-gate printf(" op type: %s\n", type_name[type]);
1730Sstevel@tonic-gate printf("-----------\n");
1740Sstevel@tonic-gate #endif
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate newitem = (struct expr *)calloc(1, sizeof (struct expr));
1770Sstevel@tonic-gate if (!newitem) {
1780Sstevel@tonic-gate STACKFREE;
1790Sstevel@tonic-gate return (NULL);
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate newitem->op = op;
1820Sstevel@tonic-gate if (type == T_NUM)
1830Sstevel@tonic-gate newitem->num = num;
1840Sstevel@tonic-gate newitem->flag = flag;
1850Sstevel@tonic-gate return (newitem);
1860Sstevel@tonic-gate }
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate static struct expr *
setop_reduce(unsigned int n,unsigned int op,struct stack * stk,struct expr * exp1,struct expr * exp2,struct expr * exp3)1890Sstevel@tonic-gate setop_reduce(unsigned int n, unsigned int op, struct stack *stk,
1900Sstevel@tonic-gate struct expr *exp1, struct expr *exp2, struct expr *exp3)
1910Sstevel@tonic-gate {
1920Sstevel@tonic-gate struct expr *newitem;
1930Sstevel@tonic-gate #ifdef PARSE_DEBUG
1940Sstevel@tonic-gate unsigned int type;
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate type = GETTYPE(op);
1970Sstevel@tonic-gate printf("---setop_reduce---\n");
1980Sstevel@tonic-gate printf(" n: %d\n", n);
1990Sstevel@tonic-gate printf(" op type: %s\n", type_name[type]);
2000Sstevel@tonic-gate switch (n) {
2010Sstevel@tonic-gate case TRINARY:
2020Sstevel@tonic-gate printf(" exp3 type: %s\n",
2030Sstevel@tonic-gate type_name[GETTYPE(exp3->op)]);
2040Sstevel@tonic-gate case BINARY:
2050Sstevel@tonic-gate printf(" exp2 type: %s\n",
2060Sstevel@tonic-gate type_name[GETTYPE(exp2->op)]);
2070Sstevel@tonic-gate case UNARY:
2080Sstevel@tonic-gate printf(" exp1 type: %s\n",
2090Sstevel@tonic-gate type_name[GETTYPE(exp1->op)]);
2100Sstevel@tonic-gate case NARY:
2110Sstevel@tonic-gate break;
2120Sstevel@tonic-gate }
2130Sstevel@tonic-gate printf("-----------\n");
2140Sstevel@tonic-gate #endif
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate newitem = (struct expr *)calloc(1, sizeof (struct expr));
2170Sstevel@tonic-gate if (!newitem) {
2180Sstevel@tonic-gate if (exp1)
2190Sstevel@tonic-gate freeexpr(exp1);
2200Sstevel@tonic-gate if (exp2)
2210Sstevel@tonic-gate freeexpr(exp2);
2220Sstevel@tonic-gate if (exp3)
2230Sstevel@tonic-gate freeexpr(exp3);
2240Sstevel@tonic-gate STACKFREE;
2250Sstevel@tonic-gate return (NULL);
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate newitem->op = op;
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate switch (n) {
2300Sstevel@tonic-gate case TRINARY:
2310Sstevel@tonic-gate newitem->nodes[2] = exp3;
2320Sstevel@tonic-gate /* FALLTHROUGH */
2330Sstevel@tonic-gate case BINARY:
2340Sstevel@tonic-gate newitem->nodes[1] = exp2;
2350Sstevel@tonic-gate /* FALLTHROUGH */
2360Sstevel@tonic-gate case UNARY:
2370Sstevel@tonic-gate newitem->nodes[0] = exp1;
2380Sstevel@tonic-gate /* FALLTHROUGH */
2390Sstevel@tonic-gate case NARY:
2400Sstevel@tonic-gate break;
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate return (newitem);
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate static int
reduce(struct expr ** nexp,unsigned int n,struct expr * exp,struct stack * stk)2460Sstevel@tonic-gate reduce(struct expr **nexp, unsigned int n, struct expr *exp, struct stack *stk)
2470Sstevel@tonic-gate {
2480Sstevel@tonic-gate struct expr *exp_op, *exp1, *exp2, *exp3;
2490Sstevel@tonic-gate unsigned int tmp_flag;
2500Sstevel@tonic-gate unsigned int oop;
2510Sstevel@tonic-gate #ifdef PARSE_DEBUG
2520Sstevel@tonic-gate printf("---reduce---\n");
2530Sstevel@tonic-gate printf(" n: %d\n", n);
2540Sstevel@tonic-gate printf("-----------\n");
2550Sstevel@tonic-gate #endif
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate switch (n) {
2580Sstevel@tonic-gate case UNARY:
2590Sstevel@tonic-gate /* unary operator */
2600Sstevel@tonic-gate exp1 = exp;
2610Sstevel@tonic-gate exp_op = stack_pop(stk, exp1, NULL);
2620Sstevel@tonic-gate if (!exp_op)
2630Sstevel@tonic-gate return (1);
2640Sstevel@tonic-gate tmp_flag = exp_op->flag;
2650Sstevel@tonic-gate oop = exp_op->op;
2660Sstevel@tonic-gate freeexpr(exp_op);
2670Sstevel@tonic-gate *nexp = setop_reduce(UNARY, oop, stk, exp1, NULL, NULL);
2680Sstevel@tonic-gate if (!*nexp)
2690Sstevel@tonic-gate return (-1);
2700Sstevel@tonic-gate (*nexp)->flag = tmp_flag;
2710Sstevel@tonic-gate return (0);
2720Sstevel@tonic-gate case BINARY:
2730Sstevel@tonic-gate /* binary operator */
2740Sstevel@tonic-gate exp2 = exp;
2750Sstevel@tonic-gate exp_op = stack_pop(stk, exp2, NULL);
2760Sstevel@tonic-gate if (!exp_op)
2770Sstevel@tonic-gate return (1);
2780Sstevel@tonic-gate exp1 = stack_pop(stk, exp_op, exp2);
2790Sstevel@tonic-gate if (!exp1)
2800Sstevel@tonic-gate return (1);
2810Sstevel@tonic-gate tmp_flag = exp1->flag;
2820Sstevel@tonic-gate oop = exp_op->op;
2830Sstevel@tonic-gate freeexpr(exp_op);
2840Sstevel@tonic-gate *nexp = setop_reduce(BINARY, oop, stk, exp1, exp2, NULL);
2850Sstevel@tonic-gate if (!*nexp)
2860Sstevel@tonic-gate return (-1);
2870Sstevel@tonic-gate (*nexp)->flag = tmp_flag;
2880Sstevel@tonic-gate return (0);
2890Sstevel@tonic-gate case TRINARY:
2900Sstevel@tonic-gate /* trinary operator: conditional */
2910Sstevel@tonic-gate exp3 = exp;
2920Sstevel@tonic-gate exp_op = stack_pop(stk, exp3, NULL);
2930Sstevel@tonic-gate if (!exp_op)
2940Sstevel@tonic-gate return (1);
2950Sstevel@tonic-gate freeexpr(exp_op);
2960Sstevel@tonic-gate exp2 = stack_pop(stk, exp3, NULL);
2970Sstevel@tonic-gate if (!exp2)
2980Sstevel@tonic-gate return (1);
2990Sstevel@tonic-gate exp_op = stack_pop(stk, exp2, exp3);
3000Sstevel@tonic-gate if (!exp_op)
3010Sstevel@tonic-gate return (1);
3020Sstevel@tonic-gate if (GETTYPE(exp_op->op) != T_CONDQ) {
3030Sstevel@tonic-gate /* parse failed */
3040Sstevel@tonic-gate freeexpr(exp_op);
3050Sstevel@tonic-gate freeexpr(exp2);
3060Sstevel@tonic-gate freeexpr(exp3);
3070Sstevel@tonic-gate STACKFREE;
3080Sstevel@tonic-gate return (1);
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate oop = exp_op->op;
3110Sstevel@tonic-gate freeexpr(exp_op);
3120Sstevel@tonic-gate exp1 = stack_pop(stk, exp2, exp3);
3130Sstevel@tonic-gate if (!exp1)
3140Sstevel@tonic-gate return (1);
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate tmp_flag = exp1->flag;
3170Sstevel@tonic-gate *nexp = setop_reduce(TRINARY, oop, stk, exp1, exp2, exp3);
3180Sstevel@tonic-gate if (!*nexp)
3190Sstevel@tonic-gate return (-1);
3200Sstevel@tonic-gate (*nexp)->flag = tmp_flag;
3210Sstevel@tonic-gate return (0);
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate /* NOTREACHED */
3240Sstevel@tonic-gate return (0); /* keep gcc happy */
3250Sstevel@tonic-gate }
3260Sstevel@tonic-gate
3270Sstevel@tonic-gate static unsigned int
gettoken(const char ** pstr,unsigned int * num,int which)3280Sstevel@tonic-gate gettoken(const char **pstr, unsigned int *num, int which)
3290Sstevel@tonic-gate {
3300Sstevel@tonic-gate unsigned char *sp = *(unsigned char **)pstr;
3310Sstevel@tonic-gate unsigned int n;
3320Sstevel@tonic-gate unsigned int ret;
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate while (*sp && ((*sp == ' ') || (*sp == '\t')))
3350Sstevel@tonic-gate sp++;
3360Sstevel@tonic-gate if (!*sp) {
3370Sstevel@tonic-gate if (which == GET_TOKEN)
3380Sstevel@tonic-gate *pstr = (const char *)sp;
3390Sstevel@tonic-gate return (T_NULL);
3400Sstevel@tonic-gate }
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate if (isdigit(*sp)) {
3430Sstevel@tonic-gate n = *sp - '0';
3440Sstevel@tonic-gate sp++;
3450Sstevel@tonic-gate while (isdigit(*sp)) {
3460Sstevel@tonic-gate n *= 10;
3470Sstevel@tonic-gate n += *sp - '0';
3480Sstevel@tonic-gate sp++;
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate *num = n;
3510Sstevel@tonic-gate ret = T_NUM;
3520Sstevel@tonic-gate } else if (*sp == 'n') {
3530Sstevel@tonic-gate sp++;
3540Sstevel@tonic-gate ret = T_VAR;
3550Sstevel@tonic-gate } else if (*sp == '(') {
3560Sstevel@tonic-gate sp++;
3570Sstevel@tonic-gate ret = T_LPAR;
3580Sstevel@tonic-gate } else if (*sp == ')') {
3590Sstevel@tonic-gate sp++;
3600Sstevel@tonic-gate ret = T_RPAR;
3610Sstevel@tonic-gate } else if (*sp == '!') {
3620Sstevel@tonic-gate sp++;
3630Sstevel@tonic-gate if (*sp == '=') {
3640Sstevel@tonic-gate sp++;
3650Sstevel@tonic-gate ret = T_NEQ;
3660Sstevel@tonic-gate } else {
3670Sstevel@tonic-gate ret = T_LNOT;
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate } else if (*sp == '*') {
3700Sstevel@tonic-gate sp++;
3710Sstevel@tonic-gate ret = T_MUL;
3720Sstevel@tonic-gate } else if (*sp == '/') {
3730Sstevel@tonic-gate sp++;
3740Sstevel@tonic-gate ret = T_DIV;
3750Sstevel@tonic-gate } else if (*sp == '%') {
3760Sstevel@tonic-gate sp++;
3770Sstevel@tonic-gate ret = T_MOD;
3780Sstevel@tonic-gate } else if (*sp == '+') {
3790Sstevel@tonic-gate sp++;
3800Sstevel@tonic-gate ret = T_ADD;
3810Sstevel@tonic-gate } else if (*sp == '-') {
3820Sstevel@tonic-gate sp++;
3830Sstevel@tonic-gate ret = T_SUB;
3840Sstevel@tonic-gate } else if (*sp == '<') {
3850Sstevel@tonic-gate sp++;
3860Sstevel@tonic-gate if (*sp == '=') {
3870Sstevel@tonic-gate sp++;
3880Sstevel@tonic-gate ret = T_LE;
3890Sstevel@tonic-gate } else {
3900Sstevel@tonic-gate ret = T_LT;
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate } else if (*sp == '>') {
3930Sstevel@tonic-gate sp++;
3940Sstevel@tonic-gate if (*sp == '=') {
3950Sstevel@tonic-gate sp++;
3960Sstevel@tonic-gate ret = T_GE;
3970Sstevel@tonic-gate } else {
3980Sstevel@tonic-gate ret = T_GT;
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate } else if (*sp == '=') {
4010Sstevel@tonic-gate sp++;
4020Sstevel@tonic-gate if (*sp == '=') {
4030Sstevel@tonic-gate sp++;
4040Sstevel@tonic-gate ret = T_EQ;
4050Sstevel@tonic-gate } else {
4060Sstevel@tonic-gate ret = T_ERR;
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate } else if (*sp == '&') {
4090Sstevel@tonic-gate sp++;
4100Sstevel@tonic-gate if (*sp == '&') {
4110Sstevel@tonic-gate sp++;
4120Sstevel@tonic-gate ret = T_LAND;
4130Sstevel@tonic-gate } else {
4140Sstevel@tonic-gate ret = T_ERR;
4150Sstevel@tonic-gate }
4160Sstevel@tonic-gate } else if (*sp == '|') {
4170Sstevel@tonic-gate sp++;
4180Sstevel@tonic-gate if (*sp == '|') {
4190Sstevel@tonic-gate sp++;
4200Sstevel@tonic-gate ret = T_LOR;
4210Sstevel@tonic-gate } else {
4220Sstevel@tonic-gate ret = T_ERR;
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate } else if (*sp == '?') {
4250Sstevel@tonic-gate sp++;
4260Sstevel@tonic-gate ret = T_CONDQ;
4270Sstevel@tonic-gate } else if (*sp == ':') {
4280Sstevel@tonic-gate sp++;
4290Sstevel@tonic-gate ret = T_CONDC;
4300Sstevel@tonic-gate } else if ((*sp == '\n') || (*sp == ';')) {
4310Sstevel@tonic-gate ret = T_NULL;
4320Sstevel@tonic-gate } else {
4330Sstevel@tonic-gate ret = T_ERR;
4340Sstevel@tonic-gate }
4350Sstevel@tonic-gate if (which == GET_TOKEN)
4360Sstevel@tonic-gate *pstr = (const char *)sp;
4370Sstevel@tonic-gate return (operator[ret]);
4380Sstevel@tonic-gate }
4390Sstevel@tonic-gate
4400Sstevel@tonic-gate /*
4410Sstevel@tonic-gate * plural_expr
4420Sstevel@tonic-gate *
4430Sstevel@tonic-gate * INPUT
4440Sstevel@tonic-gate * str: string to parse
4450Sstevel@tonic-gate *
4460Sstevel@tonic-gate * OUTPUT
4470Sstevel@tonic-gate * e: parsed expression
4480Sstevel@tonic-gate *
4490Sstevel@tonic-gate * RETURN
4500Sstevel@tonic-gate * -1: Error happend (malloc failed)
4510Sstevel@tonic-gate * 1: Parse failed (invalid expression)
4520Sstevel@tonic-gate * 0: Parse succeeded
4530Sstevel@tonic-gate */
4540Sstevel@tonic-gate int
plural_expr(struct expr ** e,const char * plural_string)4550Sstevel@tonic-gate plural_expr(struct expr **e, const char *plural_string)
4560Sstevel@tonic-gate {
4570Sstevel@tonic-gate const char *pstr = plural_string;
4580Sstevel@tonic-gate struct stack *stk, stkbuf;
4590Sstevel@tonic-gate struct expr *exp, *nexp, *exp_op, *ret;
4600Sstevel@tonic-gate int par, result;
4610Sstevel@tonic-gate unsigned int flag, ftype, fprio, fopnum, tmp_flag;
4620Sstevel@tonic-gate unsigned int ntype, nprio, ptype, popnum;
4630Sstevel@tonic-gate unsigned int op, nop, num, type, opnum;
4640Sstevel@tonic-gate
4650Sstevel@tonic-gate stk = &stkbuf;
4660Sstevel@tonic-gate stk->index = 0;
4670Sstevel@tonic-gate stk->ptr = (struct expr **)malloc(
4680Sstevel@tonic-gate sizeof (struct expr *) * MAX_STACK_SIZE);
4690Sstevel@tonic-gate if (!stk->ptr) {
4700Sstevel@tonic-gate /* malloc failed */
4710Sstevel@tonic-gate return (-1);
4720Sstevel@tonic-gate }
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate flag = operator[T_INIT];
4750Sstevel@tonic-gate par = 0;
4760Sstevel@tonic-gate while ((op = gettoken(&pstr, &num, GET_TOKEN)) != T_NULL) {
4770Sstevel@tonic-gate type = GETTYPE(op);
4780Sstevel@tonic-gate opnum = GETOPNUM(op);
4790Sstevel@tonic-gate ftype = GETTYPE(flag);
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate #ifdef PARSE_DEBUG
4820Sstevel@tonic-gate printf("*** %s ***\n", type_name[type]);
4830Sstevel@tonic-gate printf(" flag: %s\n", type_name[ftype]);
4840Sstevel@tonic-gate printf(" par: %d\n", par);
4850Sstevel@tonic-gate printf("***********\n");
4860Sstevel@tonic-gate #endif
4870Sstevel@tonic-gate if (type == T_ERR) {
4880Sstevel@tonic-gate /* parse failed */
4890Sstevel@tonic-gate STACKFREE;
4900Sstevel@tonic-gate return (1);
4910Sstevel@tonic-gate }
4920Sstevel@tonic-gate if (opnum == BINARY) {
4930Sstevel@tonic-gate /* binary operation */
4940Sstevel@tonic-gate if (ftype != T_EXP) {
4950Sstevel@tonic-gate /* parse failed */
4960Sstevel@tonic-gate #ifdef PARSE_DEBUG
4970Sstevel@tonic-gate printf("ERR: T_EXP is not followed by %s\n",
4980Sstevel@tonic-gate type_name[type]);
4990Sstevel@tonic-gate #endif
5000Sstevel@tonic-gate STACKFREE;
5010Sstevel@tonic-gate return (1);
5020Sstevel@tonic-gate }
5030Sstevel@tonic-gate exp = setop1(op, 0, stk, flag);
5040Sstevel@tonic-gate if (!exp)
5050Sstevel@tonic-gate return (-1);
5060Sstevel@tonic-gate ret = stack_push(stk, exp);
5070Sstevel@tonic-gate if (!ret)
5080Sstevel@tonic-gate return (1);
5090Sstevel@tonic-gate flag = op;
5100Sstevel@tonic-gate continue; /* while-loop */
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate if (type == T_CONDQ) {
5140Sstevel@tonic-gate /* conditional operation: '?' */
5150Sstevel@tonic-gate if (ftype != T_EXP) {
5160Sstevel@tonic-gate /* parse failed */
5170Sstevel@tonic-gate #ifdef PARSE_DEBUG
5180Sstevel@tonic-gate printf("ERR: T_EXP is not followed by %s\n",
5190Sstevel@tonic-gate type_name[type]);
5200Sstevel@tonic-gate #endif
5210Sstevel@tonic-gate STACKFREE;
5220Sstevel@tonic-gate return (1);
5230Sstevel@tonic-gate }
5240Sstevel@tonic-gate exp = setop1(op, 0, stk, flag);
5250Sstevel@tonic-gate if (!exp)
5260Sstevel@tonic-gate return (-1);
5270Sstevel@tonic-gate ret = stack_push(stk, exp);
5280Sstevel@tonic-gate if (!ret)
5290Sstevel@tonic-gate return (1);
5300Sstevel@tonic-gate flag = op;
5310Sstevel@tonic-gate continue; /* while-loop */
5320Sstevel@tonic-gate }
5330Sstevel@tonic-gate if (type == T_CONDC) {
5340Sstevel@tonic-gate /* conditional operation: ':' */
5350Sstevel@tonic-gate if (ftype != T_EXP) {
5360Sstevel@tonic-gate /* parse failed */
5370Sstevel@tonic-gate #ifdef PARSE_DEBUG
5380Sstevel@tonic-gate printf("ERR: T_EXP is not followed by %s\n",
5390Sstevel@tonic-gate type_name[type]);
5400Sstevel@tonic-gate #endif
5410Sstevel@tonic-gate STACKFREE;
5420Sstevel@tonic-gate return (1);
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate exp = setop1(op, 0, stk, flag);
5450Sstevel@tonic-gate if (!exp)
5460Sstevel@tonic-gate return (-1);
5470Sstevel@tonic-gate ret = stack_push(stk, exp);
5480Sstevel@tonic-gate if (!ret)
5490Sstevel@tonic-gate return (1);
5500Sstevel@tonic-gate flag = op;
5510Sstevel@tonic-gate continue; /* while-loop */
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate if (type == T_LPAR) {
5550Sstevel@tonic-gate /* left parenthesis */
5560Sstevel@tonic-gate if (ftype == T_EXP) {
5570Sstevel@tonic-gate /* parse failed */
5580Sstevel@tonic-gate #ifdef PARSE_DEBUG
5590Sstevel@tonic-gate printf("ERR: T_EXP is followed by %s\n",
5600Sstevel@tonic-gate type_name[type]);
5610Sstevel@tonic-gate #endif
5620Sstevel@tonic-gate STACKFREE;
5630Sstevel@tonic-gate return (1);
5640Sstevel@tonic-gate }
5650Sstevel@tonic-gate exp = setop1(op, 0, stk, flag);
5660Sstevel@tonic-gate if (!exp)
5670Sstevel@tonic-gate return (-1);
5680Sstevel@tonic-gate ret = stack_push(stk, exp);
5690Sstevel@tonic-gate if (!ret)
5700Sstevel@tonic-gate return (1);
5710Sstevel@tonic-gate par++;
5720Sstevel@tonic-gate flag = op;
5730Sstevel@tonic-gate continue; /* while-loop */
5740Sstevel@tonic-gate }
5750Sstevel@tonic-gate if (type == T_RPAR) {
5760Sstevel@tonic-gate /* right parenthesis */
5770Sstevel@tonic-gate if (ftype != T_EXP) {
5780Sstevel@tonic-gate /* parse failed */
5790Sstevel@tonic-gate #ifdef PARSE_DEBUG
5800Sstevel@tonic-gate printf("ERR: T_EXP is not followed by %s\n",
5810Sstevel@tonic-gate type_name[type]);
5820Sstevel@tonic-gate #endif
5830Sstevel@tonic-gate STACKFREE;
5840Sstevel@tonic-gate return (1);
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate par--;
5870Sstevel@tonic-gate if (par < 0) {
5880Sstevel@tonic-gate /* parse failed */
5890Sstevel@tonic-gate #ifdef PARSE_DEBUG
5900Sstevel@tonic-gate printf("ERR: too much T_RPAR\n");
5910Sstevel@tonic-gate #endif
5920Sstevel@tonic-gate STACKFREE;
5930Sstevel@tonic-gate return (1);
5940Sstevel@tonic-gate }
5950Sstevel@tonic-gate exp = stack_pop(stk, NULL, NULL);
5960Sstevel@tonic-gate if (!exp)
5970Sstevel@tonic-gate return (1);
5980Sstevel@tonic-gate
5990Sstevel@tonic-gate #ifdef PARSE_DEBUG
6000Sstevel@tonic-gate printf("======================== RPAR for loop in\n");
6010Sstevel@tonic-gate #endif
6020Sstevel@tonic-gate for (; ; ) {
6030Sstevel@tonic-gate ptype = GETTYPE(exp->flag);
6040Sstevel@tonic-gate popnum = GETOPNUM(exp->flag);
6050Sstevel@tonic-gate
6060Sstevel@tonic-gate #ifdef PARSE_DEBUG
6070Sstevel@tonic-gate printf("=========== exp->flag: %s\n",
6080Sstevel@tonic-gate type_name[ptype]);
6090Sstevel@tonic-gate #endif
6100Sstevel@tonic-gate if (ptype == T_LPAR) {
6110Sstevel@tonic-gate exp_op = stack_pop(stk, exp, NULL);
6120Sstevel@tonic-gate if (!exp_op)
6130Sstevel@tonic-gate return (1);
6140Sstevel@tonic-gate
6150Sstevel@tonic-gate tmp_flag = exp_op->flag;
6160Sstevel@tonic-gate freeexpr(exp_op);
6170Sstevel@tonic-gate
6180Sstevel@tonic-gate exp->flag = tmp_flag;
6190Sstevel@tonic-gate flag = tmp_flag;
6200Sstevel@tonic-gate break; /* break from for-loop */
6210Sstevel@tonic-gate }
6220Sstevel@tonic-gate
6230Sstevel@tonic-gate if ((popnum == BINARY) ||
6240Sstevel@tonic-gate (ptype == T_LNOT) ||
6250Sstevel@tonic-gate (ptype == T_CONDC)) {
6260Sstevel@tonic-gate result = reduce(&nexp, popnum,
6270Sstevel@tonic-gate exp, stk);
6280Sstevel@tonic-gate if (result)
6290Sstevel@tonic-gate return (result);
6300Sstevel@tonic-gate exp = nexp;
6310Sstevel@tonic-gate continue; /* for-loop */
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate /* parse failed */
6340Sstevel@tonic-gate freeexpr(exp);
6350Sstevel@tonic-gate STACKFREE;
6360Sstevel@tonic-gate return (1);
6370Sstevel@tonic-gate } /* for-loop */
6380Sstevel@tonic-gate
6390Sstevel@tonic-gate #ifdef PARSE_DEBUG
6400Sstevel@tonic-gate printf("========================= RPAR for loop out\n");
6410Sstevel@tonic-gate #endif
6420Sstevel@tonic-gate /*
6430Sstevel@tonic-gate * Needs to check if exp can be reduced or not
6440Sstevel@tonic-gate */
6450Sstevel@tonic-gate goto exp_check;
6460Sstevel@tonic-gate }
6470Sstevel@tonic-gate
6480Sstevel@tonic-gate if (type == T_LNOT) {
6490Sstevel@tonic-gate if (ftype == T_EXP) {
6500Sstevel@tonic-gate /* parse failed */
6510Sstevel@tonic-gate #ifdef PARSE_DEBUG
6520Sstevel@tonic-gate printf("ERR: T_EXP is followed by %s\n",
6530Sstevel@tonic-gate type_name[type]);
6540Sstevel@tonic-gate #endif
6550Sstevel@tonic-gate STACKFREE;
6560Sstevel@tonic-gate return (1);
6570Sstevel@tonic-gate }
6580Sstevel@tonic-gate exp = setop1(op, 0, stk, flag);
6590Sstevel@tonic-gate if (!exp)
6600Sstevel@tonic-gate return (-1);
6610Sstevel@tonic-gate ret = stack_push(stk, exp);
6620Sstevel@tonic-gate if (!ret)
6630Sstevel@tonic-gate return (1);
6640Sstevel@tonic-gate flag = op;
6650Sstevel@tonic-gate continue; /* while-loop */
6660Sstevel@tonic-gate }
6670Sstevel@tonic-gate if ((type == T_NUM) || (type == T_VAR)) {
6680Sstevel@tonic-gate exp = setop1(op, type == T_NUM ? num : 0, stk, flag);
6690Sstevel@tonic-gate if (!exp)
6700Sstevel@tonic-gate return (-1);
6710Sstevel@tonic-gate exp_check:
6720Sstevel@tonic-gate ftype = GETTYPE(flag);
6730Sstevel@tonic-gate if ((ftype == T_INIT) || (ftype == T_LPAR)) {
6740Sstevel@tonic-gate /*
6750Sstevel@tonic-gate * if this NUM/VAR is the first EXP,
6760Sstevel@tonic-gate * just push this
6770Sstevel@tonic-gate */
6780Sstevel@tonic-gate exp->flag = flag;
6790Sstevel@tonic-gate ret = stack_push(stk, exp);
6800Sstevel@tonic-gate if (!ret)
6810Sstevel@tonic-gate return (1);
6820Sstevel@tonic-gate flag = operator[T_EXP];
6830Sstevel@tonic-gate continue; /* while-loop */
6840Sstevel@tonic-gate }
6850Sstevel@tonic-gate if (ftype == T_EXP) {
6860Sstevel@tonic-gate /*
6870Sstevel@tonic-gate * parse failed
6880Sstevel@tonic-gate * NUM/VAR cannot be seen just after
6890Sstevel@tonic-gate * T_EXP
6900Sstevel@tonic-gate */
6910Sstevel@tonic-gate freeexpr(exp);
6920Sstevel@tonic-gate STACKFREE;
6930Sstevel@tonic-gate return (1);
6940Sstevel@tonic-gate }
6950Sstevel@tonic-gate
6960Sstevel@tonic-gate nop = gettoken(&pstr, &num, PEEK_TOKEN);
6970Sstevel@tonic-gate if (nop != T_NULL) {
6980Sstevel@tonic-gate ntype = GETTYPE(nop);
6990Sstevel@tonic-gate nprio = GETPRIO(nop);
7000Sstevel@tonic-gate } else {
7010Sstevel@tonic-gate (void) gettoken(&pstr, &num, GET_TOKEN);
7020Sstevel@tonic-gate ntype = T_INIT;
7030Sstevel@tonic-gate nprio = 0;
7040Sstevel@tonic-gate }
7050Sstevel@tonic-gate #ifdef PARSE_DEBUG
7060Sstevel@tonic-gate printf("========================== T_NUM/T_VAR for loop in\n");
7070Sstevel@tonic-gate #endif
7080Sstevel@tonic-gate for (; ; ) {
7090Sstevel@tonic-gate ftype = GETTYPE(flag);
7100Sstevel@tonic-gate fopnum = GETOPNUM(flag);
7110Sstevel@tonic-gate fprio = GETPRIO(flag);
7120Sstevel@tonic-gate #ifdef PARSE_DEBUG
7130Sstevel@tonic-gate printf("========= flag: %s\n",
7140Sstevel@tonic-gate type_name[ftype]);
7150Sstevel@tonic-gate #endif
7160Sstevel@tonic-gate if ((ftype == T_INIT) || (ftype == T_LPAR)) {
7170Sstevel@tonic-gate exp->flag = flag;
7180Sstevel@tonic-gate ret = stack_push(stk, exp);
7190Sstevel@tonic-gate if (!ret)
7200Sstevel@tonic-gate return (1);
7210Sstevel@tonic-gate flag = operator[T_EXP];
7220Sstevel@tonic-gate break; /* exit from for-loop */
7230Sstevel@tonic-gate }
7240Sstevel@tonic-gate
7250Sstevel@tonic-gate if (ftype == T_LNOT) {
7260Sstevel@tonic-gate /* LNOT is the strongest */
7270Sstevel@tonic-gate result = reduce(&nexp, UNARY, exp, stk);
7280Sstevel@tonic-gate if (result)
7290Sstevel@tonic-gate return (result);
7300Sstevel@tonic-gate exp = nexp;
7310Sstevel@tonic-gate flag = nexp->flag;
7320Sstevel@tonic-gate continue; /* for-loop */
7330Sstevel@tonic-gate }
7340Sstevel@tonic-gate
7350Sstevel@tonic-gate if (fopnum == BINARY) {
7360Sstevel@tonic-gate /*
7370Sstevel@tonic-gate * binary operation
7380Sstevel@tonic-gate * T_MUL, T_ADD, T_CMP,
7390Sstevel@tonic-gate * T_EQ, T_LAND, T_LOR
7400Sstevel@tonic-gate */
7410Sstevel@tonic-gate if ((ntype == T_RPAR) ||
7420Sstevel@tonic-gate (nprio <= fprio)) {
7430Sstevel@tonic-gate /* reduce */
7440Sstevel@tonic-gate result = reduce(&nexp, BINARY,
7450Sstevel@tonic-gate exp, stk);
7460Sstevel@tonic-gate if (result)
7470Sstevel@tonic-gate return (result);
7480Sstevel@tonic-gate exp = nexp;
7490Sstevel@tonic-gate flag = nexp->flag;
7500Sstevel@tonic-gate continue; /* for-loop */
7510Sstevel@tonic-gate }
7520Sstevel@tonic-gate /* shift */
7530Sstevel@tonic-gate exp->flag = flag;
7540Sstevel@tonic-gate ret = stack_push(stk, exp);
7550Sstevel@tonic-gate if (!ret)
7560Sstevel@tonic-gate return (1);
7570Sstevel@tonic-gate flag = operator[T_EXP];
7580Sstevel@tonic-gate break; /* exit from for loop */
7590Sstevel@tonic-gate }
7600Sstevel@tonic-gate
7610Sstevel@tonic-gate if (ftype == T_CONDQ) {
7620Sstevel@tonic-gate /*
7630Sstevel@tonic-gate * CONDQ is the weakest
7640Sstevel@tonic-gate * always shift
7650Sstevel@tonic-gate */
7660Sstevel@tonic-gate exp->flag = flag;
7670Sstevel@tonic-gate ret = stack_push(stk, exp);
7680Sstevel@tonic-gate if (!ret)
7690Sstevel@tonic-gate return (1);
7700Sstevel@tonic-gate flag = operator[T_EXP];
7710Sstevel@tonic-gate break; /* exit from for loop */
7720Sstevel@tonic-gate }
7730Sstevel@tonic-gate if (ftype == T_CONDC) {
7740Sstevel@tonic-gate if (nprio <= fprio) {
7750Sstevel@tonic-gate /* reduce */
7760Sstevel@tonic-gate result = reduce(&nexp, TRINARY,
7770Sstevel@tonic-gate exp, stk);
7780Sstevel@tonic-gate if (result)
7790Sstevel@tonic-gate return (result);
7800Sstevel@tonic-gate exp = nexp;
7810Sstevel@tonic-gate flag = nexp->flag;
7820Sstevel@tonic-gate continue; /* for-loop */
7830Sstevel@tonic-gate }
7840Sstevel@tonic-gate /* shift */
7850Sstevel@tonic-gate exp->flag = flag;
7860Sstevel@tonic-gate ret = stack_push(stk, exp);
7870Sstevel@tonic-gate if (!ret)
7880Sstevel@tonic-gate return (1);
7890Sstevel@tonic-gate flag = operator[T_EXP];
7900Sstevel@tonic-gate break; /* exit from for-loop */
7910Sstevel@tonic-gate }
7920Sstevel@tonic-gate /* parse failed */
7930Sstevel@tonic-gate freeexpr(exp);
7940Sstevel@tonic-gate STACKFREE;
7950Sstevel@tonic-gate return (1);
7960Sstevel@tonic-gate }
7970Sstevel@tonic-gate
7980Sstevel@tonic-gate #ifdef PARSE_DEBUG
7990Sstevel@tonic-gate printf("======================= T_NUM/T_VAR for loop out\n");
8000Sstevel@tonic-gate #endif
8010Sstevel@tonic-gate continue; /* while-loop */
8020Sstevel@tonic-gate }
8030Sstevel@tonic-gate /* parse failed */
8040Sstevel@tonic-gate STACKFREE;
8050Sstevel@tonic-gate return (1);
8060Sstevel@tonic-gate } /* while-loop */
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate if (GETTYPE(flag) != T_EXP) {
8090Sstevel@tonic-gate /* parse failed */
8100Sstevel@tonic-gate #ifdef PARSE_DEBUG
8110Sstevel@tonic-gate printf("XXXX ERROR: flag is not T_INIT\n");
8120Sstevel@tonic-gate printf("========= flag: %s\n", type_name[GETTYPE(flag)]);
8130Sstevel@tonic-gate #endif
8140Sstevel@tonic-gate STACKFREE;
8150Sstevel@tonic-gate return (1);
8160Sstevel@tonic-gate } else {
8170Sstevel@tonic-gate exp = stack_pop(stk, NULL, NULL);
8180Sstevel@tonic-gate if (!exp)
8190Sstevel@tonic-gate return (1);
8200Sstevel@tonic-gate
8210Sstevel@tonic-gate if (GETTYPE(exp->flag) != T_INIT) {
8220Sstevel@tonic-gate /* parse failed */
8230Sstevel@tonic-gate #ifdef PARSE_DEBUG
8240Sstevel@tonic-gate printf("ERR: flag for the result is not T_INIT\n");
8250Sstevel@tonic-gate printf(" %s observed\n",
8260Sstevel@tonic-gate type_name[GETTYPE(exp->flag)]);
8270Sstevel@tonic-gate #endif
8280Sstevel@tonic-gate freeexpr(exp);
8290Sstevel@tonic-gate STACKFREE;
8300Sstevel@tonic-gate return (1);
8310Sstevel@tonic-gate }
8320Sstevel@tonic-gate if (stk->index > 0) {
8330Sstevel@tonic-gate /*
8340Sstevel@tonic-gate * exp still remains in stack.
8350Sstevel@tonic-gate * parse failed
8360Sstevel@tonic-gate */
8370Sstevel@tonic-gate while (nexp = stack_pop(stk, NULL, NULL))
8380Sstevel@tonic-gate freeexpr(nexp);
8390Sstevel@tonic-gate freeexpr(exp);
8400Sstevel@tonic-gate return (1);
8410Sstevel@tonic-gate }
8420Sstevel@tonic-gate
8430Sstevel@tonic-gate /* parse succeeded */
8440Sstevel@tonic-gate *e = exp;
8450Sstevel@tonic-gate STACKFREE;
8460Sstevel@tonic-gate return (0);
8470Sstevel@tonic-gate }
8480Sstevel@tonic-gate }
8490Sstevel@tonic-gate
8500Sstevel@tonic-gate unsigned int
plural_eval(struct expr * exp,unsigned int n)8510Sstevel@tonic-gate plural_eval(struct expr *exp, unsigned int n)
8520Sstevel@tonic-gate {
8530Sstevel@tonic-gate unsigned int e1, e2;
8540Sstevel@tonic-gate unsigned int type, opnum;
8550Sstevel@tonic-gate #ifdef GETTEXT_DEBUG
8560Sstevel@tonic-gate (void) printf("*************** plural_eval(%p, %d)\n",
8570Sstevel@tonic-gate exp, n);
8580Sstevel@tonic-gate printexpr(exp, 0);
8590Sstevel@tonic-gate #endif
8600Sstevel@tonic-gate
8610Sstevel@tonic-gate type = GETTYPE(exp->op);
8620Sstevel@tonic-gate opnum = GETOPNUM(exp->op);
8630Sstevel@tonic-gate
8640Sstevel@tonic-gate switch (opnum) {
8650Sstevel@tonic-gate case NARY:
8660Sstevel@tonic-gate if (type == T_NUM) {
8670Sstevel@tonic-gate return (exp->num);
8680Sstevel@tonic-gate } else if (type == T_VAR) {
8690Sstevel@tonic-gate return (n);
8700Sstevel@tonic-gate }
8710Sstevel@tonic-gate break;
8720Sstevel@tonic-gate case UNARY:
8730Sstevel@tonic-gate /* T_LNOT */
8740Sstevel@tonic-gate e1 = plural_eval(exp->nodes[0], n);
8750Sstevel@tonic-gate return (!e1);
8760Sstevel@tonic-gate case BINARY:
8770Sstevel@tonic-gate e1 = plural_eval(exp->nodes[0], n);
8780Sstevel@tonic-gate /* optimization for T_LOR and T_LAND */
8790Sstevel@tonic-gate if (type == T_LOR) {
8800Sstevel@tonic-gate return (e1 || plural_eval(exp->nodes[1], n));
8810Sstevel@tonic-gate } else if (type == T_LAND) {
8820Sstevel@tonic-gate return (e1 && plural_eval(exp->nodes[1], n));
8830Sstevel@tonic-gate }
8840Sstevel@tonic-gate e2 = plural_eval(exp->nodes[1], n);
8850Sstevel@tonic-gate switch (type) {
8860Sstevel@tonic-gate case T_EQ:
8870Sstevel@tonic-gate return (e1 == e2);
8880Sstevel@tonic-gate case T_NEQ:
8890Sstevel@tonic-gate return (e1 != e2);
8900Sstevel@tonic-gate case T_GT:
8910Sstevel@tonic-gate return (e1 > e2);
8920Sstevel@tonic-gate case T_LT:
8930Sstevel@tonic-gate return (e1 < e2);
8940Sstevel@tonic-gate case T_GE:
8950Sstevel@tonic-gate return (e1 >= e2);
8960Sstevel@tonic-gate case T_LE:
8970Sstevel@tonic-gate return (e1 <= e2);
8980Sstevel@tonic-gate case T_ADD:
8990Sstevel@tonic-gate return (e1 + e2);
9000Sstevel@tonic-gate case T_SUB:
9010Sstevel@tonic-gate return (e1 - e2);
9020Sstevel@tonic-gate case T_MUL:
9030Sstevel@tonic-gate return (e1 * e2);
9040Sstevel@tonic-gate case T_DIV:
9050Sstevel@tonic-gate if (e2 != 0)
9060Sstevel@tonic-gate return (e1 / e2);
9070Sstevel@tonic-gate break;
9080Sstevel@tonic-gate case T_MOD:
9090Sstevel@tonic-gate if (e2 != 0)
9100Sstevel@tonic-gate return (e1 % e2);
9110Sstevel@tonic-gate break;
9120Sstevel@tonic-gate }
9130Sstevel@tonic-gate break;
9140Sstevel@tonic-gate case TRINARY:
9150Sstevel@tonic-gate /* T_CONDQ */
9160Sstevel@tonic-gate e1 = plural_eval(exp->nodes[0], n);
9170Sstevel@tonic-gate if (e1) {
9180Sstevel@tonic-gate return (plural_eval(exp->nodes[1], n));
9190Sstevel@tonic-gate } else {
9200Sstevel@tonic-gate return (plural_eval(exp->nodes[2], n));
9210Sstevel@tonic-gate }
9220Sstevel@tonic-gate }
9230Sstevel@tonic-gate /* should not be here */
9240Sstevel@tonic-gate return (0);
9250Sstevel@tonic-gate }
926