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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
36 #include "plural_parser.h"
39 * 31 28 24 20 16 12 8 4 0
40 * +-----+-----+-----+-----+-----+-----+-----+-----+
41 * |opnum| priority | operator |
42 * +-----+-----+-----+-----+-----+-----+-----+-----+
44 static const unsigned int operator[] = {
45 0x00000000, /* NULL */
46 0x00000001, /* INIT */
50 0x30400005, /* CONDC */
51 0x30500006, /* CONDQ */
66 0x00d00015, /* LPAR */
67 0x00e00016, /* RPAR */
73 while (stk->index > 0) \
74 freeexpr(stk->ptr[--stk->index]); \
79 static const char *type_name
[] = {
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",
88 static void freeexpr(struct expr
*);
91 stack_push(struct stack
*stk
, struct expr
*exp
)
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");
99 stk
->ptr
[stk
->index
++] = exp
;
100 if (stk
->index
== MAX_STACK_SIZE
) {
111 stack_pop(struct stack
*stk
,
112 struct expr
*exp_a
, struct expr
*exp_b
)
114 if (stk
->index
== 0) {
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");
131 return (stk
->ptr
[--stk
->index
]);
135 freeexpr(struct expr
*e
)
138 printf("--- freeexpr ---\n");
139 printf(" type: %s\n", type_name
[GETTYPE(e
->op
)]);
140 printf("----------------\n");
142 switch (GETOPNUM(e
->op
)) {
145 freeexpr(e
->nodes
[2]);
149 freeexpr(e
->nodes
[1]);
153 freeexpr(e
->nodes
[0]);
162 setop1(unsigned int op
, unsigned int num
,
163 struct stack
*stk
, unsigned int flag
)
165 struct expr
*newitem
;
171 printf("---setop1---\n");
172 printf(" op type: %s\n", type_name
[type
]);
173 printf("-----------\n");
176 newitem
= (struct expr
*)calloc(1, sizeof (struct expr
));
184 newitem
->flag
= flag
;
189 setop_reduce(unsigned int n
, unsigned int op
, struct stack
*stk
,
190 struct expr
*exp1
, struct expr
*exp2
, struct expr
*exp3
)
192 struct expr
*newitem
;
197 printf("---setop_reduce---\n");
198 printf(" n: %d\n", n
);
199 printf(" op type: %s\n", type_name
[type
]);
202 printf(" exp3 type: %s\n",
203 type_name
[GETTYPE(exp3
->op
)]);
205 printf(" exp2 type: %s\n",
206 type_name
[GETTYPE(exp2
->op
)]);
208 printf(" exp1 type: %s\n",
209 type_name
[GETTYPE(exp1
->op
)]);
213 printf("-----------\n");
216 newitem
= (struct expr
*)calloc(1, sizeof (struct expr
));
231 newitem
->nodes
[2] = exp3
;
234 newitem
->nodes
[1] = exp2
;
237 newitem
->nodes
[0] = exp1
;
246 reduce(struct expr
**nexp
, unsigned int n
, struct expr
*exp
, struct stack
*stk
)
248 struct expr
*exp_op
, *exp1
, *exp2
, *exp3
;
249 unsigned int tmp_flag
;
252 printf("---reduce---\n");
253 printf(" n: %d\n", n
);
254 printf("-----------\n");
261 exp_op
= stack_pop(stk
, exp1
, NULL
);
264 tmp_flag
= exp_op
->flag
;
267 *nexp
= setop_reduce(UNARY
, oop
, stk
, exp1
, NULL
, NULL
);
270 (*nexp
)->flag
= tmp_flag
;
273 /* binary operator */
275 exp_op
= stack_pop(stk
, exp2
, NULL
);
278 exp1
= stack_pop(stk
, exp_op
, exp2
);
281 tmp_flag
= exp1
->flag
;
284 *nexp
= setop_reduce(BINARY
, oop
, stk
, exp1
, exp2
, NULL
);
287 (*nexp
)->flag
= tmp_flag
;
290 /* trinary operator: conditional */
292 exp_op
= stack_pop(stk
, exp3
, NULL
);
296 exp2
= stack_pop(stk
, exp3
, NULL
);
299 exp_op
= stack_pop(stk
, exp2
, exp3
);
302 if (GETTYPE(exp_op
->op
) != T_CONDQ
) {
312 exp1
= stack_pop(stk
, exp2
, exp3
);
316 tmp_flag
= exp1
->flag
;
317 *nexp
= setop_reduce(TRINARY
, oop
, stk
, exp1
, exp2
, exp3
);
320 (*nexp
)->flag
= tmp_flag
;
324 return (0); /* keep gcc happy */
328 gettoken(const char **pstr
, unsigned int *num
, int which
)
330 unsigned char *sp
= *(unsigned char **)pstr
;
334 while (*sp
&& ((*sp
== ' ') || (*sp
== '\t')))
337 if (which
== GET_TOKEN
)
338 *pstr
= (const char *)sp
;
345 while (isdigit(*sp
)) {
352 } else if (*sp
== 'n') {
355 } else if (*sp
== '(') {
358 } else if (*sp
== ')') {
361 } else if (*sp
== '!') {
369 } else if (*sp
== '*') {
372 } else if (*sp
== '/') {
375 } else if (*sp
== '%') {
378 } else if (*sp
== '+') {
381 } else if (*sp
== '-') {
384 } else if (*sp
== '<') {
392 } else if (*sp
== '>') {
400 } else if (*sp
== '=') {
408 } else if (*sp
== '&') {
416 } else if (*sp
== '|') {
424 } else if (*sp
== '?') {
427 } else if (*sp
== ':') {
430 } else if ((*sp
== '\n') || (*sp
== ';')) {
435 if (which
== GET_TOKEN
)
436 *pstr
= (const char *)sp
;
437 return (operator[ret
]);
444 * str: string to parse
447 * e: parsed expression
450 * -1: Error happend (malloc failed)
451 * 1: Parse failed (invalid expression)
455 plural_expr(struct expr
**e
, const char *plural_string
)
457 const char *pstr
= plural_string
;
458 struct stack
*stk
, stkbuf
;
459 struct expr
*exp
, *nexp
, *exp_op
, *ret
;
461 unsigned int flag
, ftype
, fprio
, fopnum
, tmp_flag
;
462 unsigned int ntype
, nprio
, ptype
, popnum
;
463 unsigned int op
, nop
, num
, type
, opnum
;
467 stk
->ptr
= (struct expr
**)malloc(
468 sizeof (struct expr
*) * MAX_STACK_SIZE
);
474 flag
= operator[T_INIT
];
476 while ((op
= gettoken(&pstr
, &num
, GET_TOKEN
)) != T_NULL
) {
478 opnum
= GETOPNUM(op
);
479 ftype
= GETTYPE(flag
);
482 printf("*** %s ***\n", type_name
[type
]);
483 printf(" flag: %s\n", type_name
[ftype
]);
484 printf(" par: %d\n", par
);
485 printf("***********\n");
492 if (opnum
== BINARY
) {
493 /* binary operation */
494 if (ftype
!= T_EXP
) {
497 printf("ERR: T_EXP is not followed by %s\n",
503 exp
= setop1(op
, 0, stk
, flag
);
506 ret
= stack_push(stk
, exp
);
510 continue; /* while-loop */
513 if (type
== T_CONDQ
) {
514 /* conditional operation: '?' */
515 if (ftype
!= T_EXP
) {
518 printf("ERR: T_EXP is not followed by %s\n",
524 exp
= setop1(op
, 0, stk
, flag
);
527 ret
= stack_push(stk
, exp
);
531 continue; /* while-loop */
533 if (type
== T_CONDC
) {
534 /* conditional operation: ':' */
535 if (ftype
!= T_EXP
) {
538 printf("ERR: T_EXP is not followed by %s\n",
544 exp
= setop1(op
, 0, stk
, flag
);
547 ret
= stack_push(stk
, exp
);
551 continue; /* while-loop */
554 if (type
== T_LPAR
) {
555 /* left parenthesis */
556 if (ftype
== T_EXP
) {
559 printf("ERR: T_EXP is followed by %s\n",
565 exp
= setop1(op
, 0, stk
, flag
);
568 ret
= stack_push(stk
, exp
);
573 continue; /* while-loop */
575 if (type
== T_RPAR
) {
576 /* right parenthesis */
577 if (ftype
!= T_EXP
) {
580 printf("ERR: T_EXP is not followed by %s\n",
590 printf("ERR: too much T_RPAR\n");
595 exp
= stack_pop(stk
, NULL
, NULL
);
600 printf("======================== RPAR for loop in\n");
603 ptype
= GETTYPE(exp
->flag
);
604 popnum
= GETOPNUM(exp
->flag
);
607 printf("=========== exp->flag: %s\n",
610 if (ptype
== T_LPAR
) {
611 exp_op
= stack_pop(stk
, exp
, NULL
);
615 tmp_flag
= exp_op
->flag
;
618 exp
->flag
= tmp_flag
;
620 break; /* break from for-loop */
623 if ((popnum
== BINARY
) ||
625 (ptype
== T_CONDC
)) {
626 result
= reduce(&nexp
, popnum
,
631 continue; /* for-loop */
640 printf("========================= RPAR for loop out\n");
643 * Needs to check if exp can be reduced or not
648 if (type
== T_LNOT
) {
649 if (ftype
== T_EXP
) {
652 printf("ERR: T_EXP is followed by %s\n",
658 exp
= setop1(op
, 0, stk
, flag
);
661 ret
= stack_push(stk
, exp
);
665 continue; /* while-loop */
667 if ((type
== T_NUM
) || (type
== T_VAR
)) {
668 exp
= setop1(op
, type
== T_NUM
? num
: 0, stk
, flag
);
672 ftype
= GETTYPE(flag
);
673 if ((ftype
== T_INIT
) || (ftype
== T_LPAR
)) {
675 * if this NUM/VAR is the first EXP,
679 ret
= stack_push(stk
, exp
);
682 flag
= operator[T_EXP
];
683 continue; /* while-loop */
685 if (ftype
== T_EXP
) {
688 * NUM/VAR cannot be seen just after
696 nop
= gettoken(&pstr
, &num
, PEEK_TOKEN
);
698 ntype
= GETTYPE(nop
);
699 nprio
= GETPRIO(nop
);
701 (void) gettoken(&pstr
, &num
, GET_TOKEN
);
706 printf("========================== T_NUM/T_VAR for loop in\n");
709 ftype
= GETTYPE(flag
);
710 fopnum
= GETOPNUM(flag
);
711 fprio
= GETPRIO(flag
);
713 printf("========= flag: %s\n",
716 if ((ftype
== T_INIT
) || (ftype
== T_LPAR
)) {
718 ret
= stack_push(stk
, exp
);
721 flag
= operator[T_EXP
];
722 break; /* exit from for-loop */
725 if (ftype
== T_LNOT
) {
726 /* LNOT is the strongest */
727 result
= reduce(&nexp
, UNARY
, exp
, stk
);
732 continue; /* for-loop */
735 if (fopnum
== BINARY
) {
738 * T_MUL, T_ADD, T_CMP,
739 * T_EQ, T_LAND, T_LOR
741 if ((ntype
== T_RPAR
) ||
744 result
= reduce(&nexp
, BINARY
,
750 continue; /* for-loop */
754 ret
= stack_push(stk
, exp
);
757 flag
= operator[T_EXP
];
758 break; /* exit from for loop */
761 if (ftype
== T_CONDQ
) {
763 * CONDQ is the weakest
767 ret
= stack_push(stk
, exp
);
770 flag
= operator[T_EXP
];
771 break; /* exit from for loop */
773 if (ftype
== T_CONDC
) {
774 if (nprio
<= fprio
) {
776 result
= reduce(&nexp
, TRINARY
,
782 continue; /* for-loop */
786 ret
= stack_push(stk
, exp
);
789 flag
= operator[T_EXP
];
790 break; /* exit from for-loop */
799 printf("======================= T_NUM/T_VAR for loop out\n");
801 continue; /* while-loop */
808 if (GETTYPE(flag
) != T_EXP
) {
811 printf("XXXX ERROR: flag is not T_INIT\n");
812 printf("========= flag: %s\n", type_name
[GETTYPE(flag
)]);
817 exp
= stack_pop(stk
, NULL
, NULL
);
821 if (GETTYPE(exp
->flag
) != T_INIT
) {
824 printf("ERR: flag for the result is not T_INIT\n");
825 printf(" %s observed\n",
826 type_name
[GETTYPE(exp
->flag
)]);
832 if (stk
->index
> 0) {
834 * exp still remains in stack.
837 while (nexp
= stack_pop(stk
, NULL
, NULL
))
843 /* parse succeeded */
851 plural_eval(struct expr
*exp
, unsigned int n
)
854 unsigned int type
, opnum
;
856 (void) printf("*************** plural_eval(%p, %d)\n",
861 type
= GETTYPE(exp
->op
);
862 opnum
= GETOPNUM(exp
->op
);
868 } else if (type
== T_VAR
) {
874 e1
= plural_eval(exp
->nodes
[0], n
);
877 e1
= plural_eval(exp
->nodes
[0], n
);
878 /* optimization for T_LOR and T_LAND */
880 return (e1
|| plural_eval(exp
->nodes
[1], n
));
881 } else if (type
== T_LAND
) {
882 return (e1
&& plural_eval(exp
->nodes
[1], n
));
884 e2
= plural_eval(exp
->nodes
[1], n
);
916 e1
= plural_eval(exp
->nodes
[0], n
);
918 return (plural_eval(exp
->nodes
[1], n
));
920 return (plural_eval(exp
->nodes
[2], n
));
923 /* should not be here */