10a9064fbSMasahiro Yamada /*
20a9064fbSMasahiro Yamada * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
30a9064fbSMasahiro Yamada * Released under the terms of the GNU GPL v2.0.
40a9064fbSMasahiro Yamada */
50a9064fbSMasahiro Yamada
60a9064fbSMasahiro Yamada #include <stdio.h>
70a9064fbSMasahiro Yamada #include <stdlib.h>
80a9064fbSMasahiro Yamada #include <string.h>
90a9064fbSMasahiro Yamada
100a9064fbSMasahiro Yamada #include "lkc.h"
110a9064fbSMasahiro Yamada
120a9064fbSMasahiro Yamada #define DEBUG_EXPR 0
130a9064fbSMasahiro Yamada
149b5f0b1dSMasahiro Yamada static int expr_eq(struct expr *e1, struct expr *e2);
159b5f0b1dSMasahiro Yamada static struct expr *expr_eliminate_yn(struct expr *e);
169b5f0b1dSMasahiro Yamada
expr_alloc_symbol(struct symbol * sym)170a9064fbSMasahiro Yamada struct expr *expr_alloc_symbol(struct symbol *sym)
180a9064fbSMasahiro Yamada {
190a9064fbSMasahiro Yamada struct expr *e = xcalloc(1, sizeof(*e));
200a9064fbSMasahiro Yamada e->type = E_SYMBOL;
210a9064fbSMasahiro Yamada e->left.sym = sym;
220a9064fbSMasahiro Yamada return e;
230a9064fbSMasahiro Yamada }
240a9064fbSMasahiro Yamada
expr_alloc_one(enum expr_type type,struct expr * ce)250a9064fbSMasahiro Yamada struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
260a9064fbSMasahiro Yamada {
270a9064fbSMasahiro Yamada struct expr *e = xcalloc(1, sizeof(*e));
280a9064fbSMasahiro Yamada e->type = type;
290a9064fbSMasahiro Yamada e->left.expr = ce;
300a9064fbSMasahiro Yamada return e;
310a9064fbSMasahiro Yamada }
320a9064fbSMasahiro Yamada
expr_alloc_two(enum expr_type type,struct expr * e1,struct expr * e2)330a9064fbSMasahiro Yamada struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
340a9064fbSMasahiro Yamada {
350a9064fbSMasahiro Yamada struct expr *e = xcalloc(1, sizeof(*e));
360a9064fbSMasahiro Yamada e->type = type;
370a9064fbSMasahiro Yamada e->left.expr = e1;
380a9064fbSMasahiro Yamada e->right.expr = e2;
390a9064fbSMasahiro Yamada return e;
400a9064fbSMasahiro Yamada }
410a9064fbSMasahiro Yamada
expr_alloc_comp(enum expr_type type,struct symbol * s1,struct symbol * s2)420a9064fbSMasahiro Yamada struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
430a9064fbSMasahiro Yamada {
440a9064fbSMasahiro Yamada struct expr *e = xcalloc(1, sizeof(*e));
450a9064fbSMasahiro Yamada e->type = type;
460a9064fbSMasahiro Yamada e->left.sym = s1;
470a9064fbSMasahiro Yamada e->right.sym = s2;
480a9064fbSMasahiro Yamada return e;
490a9064fbSMasahiro Yamada }
500a9064fbSMasahiro Yamada
expr_alloc_and(struct expr * e1,struct expr * e2)510a9064fbSMasahiro Yamada struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
520a9064fbSMasahiro Yamada {
530a9064fbSMasahiro Yamada if (!e1)
540a9064fbSMasahiro Yamada return e2;
550a9064fbSMasahiro Yamada return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
560a9064fbSMasahiro Yamada }
570a9064fbSMasahiro Yamada
expr_alloc_or(struct expr * e1,struct expr * e2)580a9064fbSMasahiro Yamada struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
590a9064fbSMasahiro Yamada {
600a9064fbSMasahiro Yamada if (!e1)
610a9064fbSMasahiro Yamada return e2;
620a9064fbSMasahiro Yamada return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
630a9064fbSMasahiro Yamada }
640a9064fbSMasahiro Yamada
expr_copy(const struct expr * org)650a9064fbSMasahiro Yamada struct expr *expr_copy(const struct expr *org)
660a9064fbSMasahiro Yamada {
670a9064fbSMasahiro Yamada struct expr *e;
680a9064fbSMasahiro Yamada
690a9064fbSMasahiro Yamada if (!org)
700a9064fbSMasahiro Yamada return NULL;
710a9064fbSMasahiro Yamada
720a9064fbSMasahiro Yamada e = xmalloc(sizeof(*org));
730a9064fbSMasahiro Yamada memcpy(e, org, sizeof(*org));
740a9064fbSMasahiro Yamada switch (org->type) {
750a9064fbSMasahiro Yamada case E_SYMBOL:
760a9064fbSMasahiro Yamada e->left = org->left;
770a9064fbSMasahiro Yamada break;
780a9064fbSMasahiro Yamada case E_NOT:
790a9064fbSMasahiro Yamada e->left.expr = expr_copy(org->left.expr);
800a9064fbSMasahiro Yamada break;
810a9064fbSMasahiro Yamada case E_EQUAL:
82bf7ab1e7SMasahiro Yamada case E_GEQ:
83bf7ab1e7SMasahiro Yamada case E_GTH:
84bf7ab1e7SMasahiro Yamada case E_LEQ:
85bf7ab1e7SMasahiro Yamada case E_LTH:
860a9064fbSMasahiro Yamada case E_UNEQUAL:
870a9064fbSMasahiro Yamada e->left.sym = org->left.sym;
880a9064fbSMasahiro Yamada e->right.sym = org->right.sym;
890a9064fbSMasahiro Yamada break;
900a9064fbSMasahiro Yamada case E_AND:
910a9064fbSMasahiro Yamada case E_OR:
920a9064fbSMasahiro Yamada case E_LIST:
930a9064fbSMasahiro Yamada e->left.expr = expr_copy(org->left.expr);
940a9064fbSMasahiro Yamada e->right.expr = expr_copy(org->right.expr);
950a9064fbSMasahiro Yamada break;
960a9064fbSMasahiro Yamada default:
97*e91610daSEugeniu Rosca fprintf(stderr, "can't copy type %d\n", e->type);
980a9064fbSMasahiro Yamada free(e);
990a9064fbSMasahiro Yamada e = NULL;
1000a9064fbSMasahiro Yamada break;
1010a9064fbSMasahiro Yamada }
1020a9064fbSMasahiro Yamada
1030a9064fbSMasahiro Yamada return e;
1040a9064fbSMasahiro Yamada }
1050a9064fbSMasahiro Yamada
expr_free(struct expr * e)1060a9064fbSMasahiro Yamada void expr_free(struct expr *e)
1070a9064fbSMasahiro Yamada {
1080a9064fbSMasahiro Yamada if (!e)
1090a9064fbSMasahiro Yamada return;
1100a9064fbSMasahiro Yamada
1110a9064fbSMasahiro Yamada switch (e->type) {
1120a9064fbSMasahiro Yamada case E_SYMBOL:
1130a9064fbSMasahiro Yamada break;
1140a9064fbSMasahiro Yamada case E_NOT:
1150a9064fbSMasahiro Yamada expr_free(e->left.expr);
116*e91610daSEugeniu Rosca break;
1170a9064fbSMasahiro Yamada case E_EQUAL:
118bf7ab1e7SMasahiro Yamada case E_GEQ:
119bf7ab1e7SMasahiro Yamada case E_GTH:
120bf7ab1e7SMasahiro Yamada case E_LEQ:
121bf7ab1e7SMasahiro Yamada case E_LTH:
1220a9064fbSMasahiro Yamada case E_UNEQUAL:
1230a9064fbSMasahiro Yamada break;
1240a9064fbSMasahiro Yamada case E_OR:
1250a9064fbSMasahiro Yamada case E_AND:
1260a9064fbSMasahiro Yamada expr_free(e->left.expr);
1270a9064fbSMasahiro Yamada expr_free(e->right.expr);
1280a9064fbSMasahiro Yamada break;
1290a9064fbSMasahiro Yamada default:
130*e91610daSEugeniu Rosca fprintf(stderr, "how to free type %d?\n", e->type);
1310a9064fbSMasahiro Yamada break;
1320a9064fbSMasahiro Yamada }
1330a9064fbSMasahiro Yamada free(e);
1340a9064fbSMasahiro Yamada }
1350a9064fbSMasahiro Yamada
1360a9064fbSMasahiro Yamada static int trans_count;
1370a9064fbSMasahiro Yamada
1380a9064fbSMasahiro Yamada #define e1 (*ep1)
1390a9064fbSMasahiro Yamada #define e2 (*ep2)
1400a9064fbSMasahiro Yamada
141*e91610daSEugeniu Rosca /*
142*e91610daSEugeniu Rosca * expr_eliminate_eq() helper.
143*e91610daSEugeniu Rosca *
144*e91610daSEugeniu Rosca * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
145*e91610daSEugeniu Rosca * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
146*e91610daSEugeniu Rosca * against all other leaves. Two equal leaves are both replaced with either 'y'
147*e91610daSEugeniu Rosca * or 'n' as appropriate for 'type', to be eliminated later.
148*e91610daSEugeniu Rosca */
__expr_eliminate_eq(enum expr_type type,struct expr ** ep1,struct expr ** ep2)1490a9064fbSMasahiro Yamada static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
1500a9064fbSMasahiro Yamada {
151*e91610daSEugeniu Rosca /* Recurse down to leaves */
152*e91610daSEugeniu Rosca
1530a9064fbSMasahiro Yamada if (e1->type == type) {
1540a9064fbSMasahiro Yamada __expr_eliminate_eq(type, &e1->left.expr, &e2);
1550a9064fbSMasahiro Yamada __expr_eliminate_eq(type, &e1->right.expr, &e2);
1560a9064fbSMasahiro Yamada return;
1570a9064fbSMasahiro Yamada }
1580a9064fbSMasahiro Yamada if (e2->type == type) {
1590a9064fbSMasahiro Yamada __expr_eliminate_eq(type, &e1, &e2->left.expr);
1600a9064fbSMasahiro Yamada __expr_eliminate_eq(type, &e1, &e2->right.expr);
1610a9064fbSMasahiro Yamada return;
1620a9064fbSMasahiro Yamada }
163*e91610daSEugeniu Rosca
164*e91610daSEugeniu Rosca /* e1 and e2 are leaves. Compare them. */
165*e91610daSEugeniu Rosca
1660a9064fbSMasahiro Yamada if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
1670a9064fbSMasahiro Yamada e1->left.sym == e2->left.sym &&
1680a9064fbSMasahiro Yamada (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
1690a9064fbSMasahiro Yamada return;
1700a9064fbSMasahiro Yamada if (!expr_eq(e1, e2))
1710a9064fbSMasahiro Yamada return;
172*e91610daSEugeniu Rosca
173*e91610daSEugeniu Rosca /* e1 and e2 are equal leaves. Prepare them for elimination. */
174*e91610daSEugeniu Rosca
1750a9064fbSMasahiro Yamada trans_count++;
1760a9064fbSMasahiro Yamada expr_free(e1); expr_free(e2);
1770a9064fbSMasahiro Yamada switch (type) {
1780a9064fbSMasahiro Yamada case E_OR:
1790a9064fbSMasahiro Yamada e1 = expr_alloc_symbol(&symbol_no);
1800a9064fbSMasahiro Yamada e2 = expr_alloc_symbol(&symbol_no);
1810a9064fbSMasahiro Yamada break;
1820a9064fbSMasahiro Yamada case E_AND:
1830a9064fbSMasahiro Yamada e1 = expr_alloc_symbol(&symbol_yes);
1840a9064fbSMasahiro Yamada e2 = expr_alloc_symbol(&symbol_yes);
1850a9064fbSMasahiro Yamada break;
1860a9064fbSMasahiro Yamada default:
1870a9064fbSMasahiro Yamada ;
1880a9064fbSMasahiro Yamada }
1890a9064fbSMasahiro Yamada }
1900a9064fbSMasahiro Yamada
191*e91610daSEugeniu Rosca /*
192*e91610daSEugeniu Rosca * Rewrites the expressions 'ep1' and 'ep2' to remove operands common to both.
193*e91610daSEugeniu Rosca * Example reductions:
194*e91610daSEugeniu Rosca *
195*e91610daSEugeniu Rosca * ep1: A && B -> ep1: y
196*e91610daSEugeniu Rosca * ep2: A && B && C -> ep2: C
197*e91610daSEugeniu Rosca *
198*e91610daSEugeniu Rosca * ep1: A || B -> ep1: n
199*e91610daSEugeniu Rosca * ep2: A || B || C -> ep2: C
200*e91610daSEugeniu Rosca *
201*e91610daSEugeniu Rosca * ep1: A && (B && FOO) -> ep1: FOO
202*e91610daSEugeniu Rosca * ep2: (BAR && B) && A -> ep2: BAR
203*e91610daSEugeniu Rosca *
204*e91610daSEugeniu Rosca * ep1: A && (B || C) -> ep1: y
205*e91610daSEugeniu Rosca * ep2: (C || B) && A -> ep2: y
206*e91610daSEugeniu Rosca *
207*e91610daSEugeniu Rosca * Comparisons are done between all operands at the same "level" of && or ||.
208*e91610daSEugeniu Rosca * For example, in the expression 'e1 && (e2 || e3) && (e4 || e5)', the
209*e91610daSEugeniu Rosca * following operands will be compared:
210*e91610daSEugeniu Rosca *
211*e91610daSEugeniu Rosca * - 'e1', 'e2 || e3', and 'e4 || e5', against each other
212*e91610daSEugeniu Rosca * - e2 against e3
213*e91610daSEugeniu Rosca * - e4 against e5
214*e91610daSEugeniu Rosca *
215*e91610daSEugeniu Rosca * Parentheses are irrelevant within a single level. 'e1 && (e2 && e3)' and
216*e91610daSEugeniu Rosca * '(e1 && e2) && e3' are both a single level.
217*e91610daSEugeniu Rosca *
218*e91610daSEugeniu Rosca * See __expr_eliminate_eq() as well.
219*e91610daSEugeniu Rosca */
expr_eliminate_eq(struct expr ** ep1,struct expr ** ep2)2200a9064fbSMasahiro Yamada void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
2210a9064fbSMasahiro Yamada {
2220a9064fbSMasahiro Yamada if (!e1 || !e2)
2230a9064fbSMasahiro Yamada return;
2240a9064fbSMasahiro Yamada switch (e1->type) {
2250a9064fbSMasahiro Yamada case E_OR:
2260a9064fbSMasahiro Yamada case E_AND:
2270a9064fbSMasahiro Yamada __expr_eliminate_eq(e1->type, ep1, ep2);
2280a9064fbSMasahiro Yamada default:
2290a9064fbSMasahiro Yamada ;
2300a9064fbSMasahiro Yamada }
2310a9064fbSMasahiro Yamada if (e1->type != e2->type) switch (e2->type) {
2320a9064fbSMasahiro Yamada case E_OR:
2330a9064fbSMasahiro Yamada case E_AND:
2340a9064fbSMasahiro Yamada __expr_eliminate_eq(e2->type, ep1, ep2);
2350a9064fbSMasahiro Yamada default:
2360a9064fbSMasahiro Yamada ;
2370a9064fbSMasahiro Yamada }
2380a9064fbSMasahiro Yamada e1 = expr_eliminate_yn(e1);
2390a9064fbSMasahiro Yamada e2 = expr_eliminate_yn(e2);
2400a9064fbSMasahiro Yamada }
2410a9064fbSMasahiro Yamada
2420a9064fbSMasahiro Yamada #undef e1
2430a9064fbSMasahiro Yamada #undef e2
2440a9064fbSMasahiro Yamada
245*e91610daSEugeniu Rosca /*
246*e91610daSEugeniu Rosca * Returns true if 'e1' and 'e2' are equal, after minor simplification. Two
247*e91610daSEugeniu Rosca * &&/|| expressions are considered equal if every operand in one expression
248*e91610daSEugeniu Rosca * equals some operand in the other (operands do not need to appear in the same
249*e91610daSEugeniu Rosca * order), recursively.
250*e91610daSEugeniu Rosca */
expr_eq(struct expr * e1,struct expr * e2)2519b5f0b1dSMasahiro Yamada static int expr_eq(struct expr *e1, struct expr *e2)
2520a9064fbSMasahiro Yamada {
2530a9064fbSMasahiro Yamada int res, old_count;
2540a9064fbSMasahiro Yamada
2550a9064fbSMasahiro Yamada if (e1->type != e2->type)
2560a9064fbSMasahiro Yamada return 0;
2570a9064fbSMasahiro Yamada switch (e1->type) {
2580a9064fbSMasahiro Yamada case E_EQUAL:
259bf7ab1e7SMasahiro Yamada case E_GEQ:
260bf7ab1e7SMasahiro Yamada case E_GTH:
261bf7ab1e7SMasahiro Yamada case E_LEQ:
262bf7ab1e7SMasahiro Yamada case E_LTH:
2630a9064fbSMasahiro Yamada case E_UNEQUAL:
2640a9064fbSMasahiro Yamada return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
2650a9064fbSMasahiro Yamada case E_SYMBOL:
2660a9064fbSMasahiro Yamada return e1->left.sym == e2->left.sym;
2670a9064fbSMasahiro Yamada case E_NOT:
2680a9064fbSMasahiro Yamada return expr_eq(e1->left.expr, e2->left.expr);
2690a9064fbSMasahiro Yamada case E_AND:
2700a9064fbSMasahiro Yamada case E_OR:
2710a9064fbSMasahiro Yamada e1 = expr_copy(e1);
2720a9064fbSMasahiro Yamada e2 = expr_copy(e2);
2730a9064fbSMasahiro Yamada old_count = trans_count;
2740a9064fbSMasahiro Yamada expr_eliminate_eq(&e1, &e2);
2750a9064fbSMasahiro Yamada res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
2760a9064fbSMasahiro Yamada e1->left.sym == e2->left.sym);
2770a9064fbSMasahiro Yamada expr_free(e1);
2780a9064fbSMasahiro Yamada expr_free(e2);
2790a9064fbSMasahiro Yamada trans_count = old_count;
2800a9064fbSMasahiro Yamada return res;
2810a9064fbSMasahiro Yamada case E_LIST:
2820a9064fbSMasahiro Yamada case E_RANGE:
2830a9064fbSMasahiro Yamada case E_NONE:
2840a9064fbSMasahiro Yamada /* panic */;
2850a9064fbSMasahiro Yamada }
2860a9064fbSMasahiro Yamada
2870a9064fbSMasahiro Yamada if (DEBUG_EXPR) {
2880a9064fbSMasahiro Yamada expr_fprint(e1, stdout);
2890a9064fbSMasahiro Yamada printf(" = ");
2900a9064fbSMasahiro Yamada expr_fprint(e2, stdout);
2910a9064fbSMasahiro Yamada printf(" ?\n");
2920a9064fbSMasahiro Yamada }
2930a9064fbSMasahiro Yamada
2940a9064fbSMasahiro Yamada return 0;
2950a9064fbSMasahiro Yamada }
2960a9064fbSMasahiro Yamada
297*e91610daSEugeniu Rosca /*
298*e91610daSEugeniu Rosca * Recursively performs the following simplifications in-place (as well as the
299*e91610daSEugeniu Rosca * corresponding simplifications with swapped operands):
300*e91610daSEugeniu Rosca *
301*e91610daSEugeniu Rosca * expr && n -> n
302*e91610daSEugeniu Rosca * expr && y -> expr
303*e91610daSEugeniu Rosca * expr || n -> expr
304*e91610daSEugeniu Rosca * expr || y -> y
305*e91610daSEugeniu Rosca *
306*e91610daSEugeniu Rosca * Returns the optimized expression.
307*e91610daSEugeniu Rosca */
expr_eliminate_yn(struct expr * e)3089b5f0b1dSMasahiro Yamada static struct expr *expr_eliminate_yn(struct expr *e)
3090a9064fbSMasahiro Yamada {
3100a9064fbSMasahiro Yamada struct expr *tmp;
3110a9064fbSMasahiro Yamada
3120a9064fbSMasahiro Yamada if (e) switch (e->type) {
3130a9064fbSMasahiro Yamada case E_AND:
3140a9064fbSMasahiro Yamada e->left.expr = expr_eliminate_yn(e->left.expr);
3150a9064fbSMasahiro Yamada e->right.expr = expr_eliminate_yn(e->right.expr);
3160a9064fbSMasahiro Yamada if (e->left.expr->type == E_SYMBOL) {
3170a9064fbSMasahiro Yamada if (e->left.expr->left.sym == &symbol_no) {
3180a9064fbSMasahiro Yamada expr_free(e->left.expr);
3190a9064fbSMasahiro Yamada expr_free(e->right.expr);
3200a9064fbSMasahiro Yamada e->type = E_SYMBOL;
3210a9064fbSMasahiro Yamada e->left.sym = &symbol_no;
3220a9064fbSMasahiro Yamada e->right.expr = NULL;
3230a9064fbSMasahiro Yamada return e;
3240a9064fbSMasahiro Yamada } else if (e->left.expr->left.sym == &symbol_yes) {
3250a9064fbSMasahiro Yamada free(e->left.expr);
3260a9064fbSMasahiro Yamada tmp = e->right.expr;
3270a9064fbSMasahiro Yamada *e = *(e->right.expr);
3280a9064fbSMasahiro Yamada free(tmp);
3290a9064fbSMasahiro Yamada return e;
3300a9064fbSMasahiro Yamada }
3310a9064fbSMasahiro Yamada }
3320a9064fbSMasahiro Yamada if (e->right.expr->type == E_SYMBOL) {
3330a9064fbSMasahiro Yamada if (e->right.expr->left.sym == &symbol_no) {
3340a9064fbSMasahiro Yamada expr_free(e->left.expr);
3350a9064fbSMasahiro Yamada expr_free(e->right.expr);
3360a9064fbSMasahiro Yamada e->type = E_SYMBOL;
3370a9064fbSMasahiro Yamada e->left.sym = &symbol_no;
3380a9064fbSMasahiro Yamada e->right.expr = NULL;
3390a9064fbSMasahiro Yamada return e;
3400a9064fbSMasahiro Yamada } else if (e->right.expr->left.sym == &symbol_yes) {
3410a9064fbSMasahiro Yamada free(e->right.expr);
3420a9064fbSMasahiro Yamada tmp = e->left.expr;
3430a9064fbSMasahiro Yamada *e = *(e->left.expr);
3440a9064fbSMasahiro Yamada free(tmp);
3450a9064fbSMasahiro Yamada return e;
3460a9064fbSMasahiro Yamada }
3470a9064fbSMasahiro Yamada }
3480a9064fbSMasahiro Yamada break;
3490a9064fbSMasahiro Yamada case E_OR:
3500a9064fbSMasahiro Yamada e->left.expr = expr_eliminate_yn(e->left.expr);
3510a9064fbSMasahiro Yamada e->right.expr = expr_eliminate_yn(e->right.expr);
3520a9064fbSMasahiro Yamada if (e->left.expr->type == E_SYMBOL) {
3530a9064fbSMasahiro Yamada if (e->left.expr->left.sym == &symbol_no) {
3540a9064fbSMasahiro Yamada free(e->left.expr);
3550a9064fbSMasahiro Yamada tmp = e->right.expr;
3560a9064fbSMasahiro Yamada *e = *(e->right.expr);
3570a9064fbSMasahiro Yamada free(tmp);
3580a9064fbSMasahiro Yamada return e;
3590a9064fbSMasahiro Yamada } else if (e->left.expr->left.sym == &symbol_yes) {
3600a9064fbSMasahiro Yamada expr_free(e->left.expr);
3610a9064fbSMasahiro Yamada expr_free(e->right.expr);
3620a9064fbSMasahiro Yamada e->type = E_SYMBOL;
3630a9064fbSMasahiro Yamada e->left.sym = &symbol_yes;
3640a9064fbSMasahiro Yamada e->right.expr = NULL;
3650a9064fbSMasahiro Yamada return e;
3660a9064fbSMasahiro Yamada }
3670a9064fbSMasahiro Yamada }
3680a9064fbSMasahiro Yamada if (e->right.expr->type == E_SYMBOL) {
3690a9064fbSMasahiro Yamada if (e->right.expr->left.sym == &symbol_no) {
3700a9064fbSMasahiro Yamada free(e->right.expr);
3710a9064fbSMasahiro Yamada tmp = e->left.expr;
3720a9064fbSMasahiro Yamada *e = *(e->left.expr);
3730a9064fbSMasahiro Yamada free(tmp);
3740a9064fbSMasahiro Yamada return e;
3750a9064fbSMasahiro Yamada } else if (e->right.expr->left.sym == &symbol_yes) {
3760a9064fbSMasahiro Yamada expr_free(e->left.expr);
3770a9064fbSMasahiro Yamada expr_free(e->right.expr);
3780a9064fbSMasahiro Yamada e->type = E_SYMBOL;
3790a9064fbSMasahiro Yamada e->left.sym = &symbol_yes;
3800a9064fbSMasahiro Yamada e->right.expr = NULL;
3810a9064fbSMasahiro Yamada return e;
3820a9064fbSMasahiro Yamada }
3830a9064fbSMasahiro Yamada }
3840a9064fbSMasahiro Yamada break;
3850a9064fbSMasahiro Yamada default:
3860a9064fbSMasahiro Yamada ;
3870a9064fbSMasahiro Yamada }
3880a9064fbSMasahiro Yamada return e;
3890a9064fbSMasahiro Yamada }
3900a9064fbSMasahiro Yamada
3910a9064fbSMasahiro Yamada /*
3920a9064fbSMasahiro Yamada * bool FOO!=n => FOO
3930a9064fbSMasahiro Yamada */
expr_trans_bool(struct expr * e)3940a9064fbSMasahiro Yamada struct expr *expr_trans_bool(struct expr *e)
3950a9064fbSMasahiro Yamada {
3960a9064fbSMasahiro Yamada if (!e)
3970a9064fbSMasahiro Yamada return NULL;
3980a9064fbSMasahiro Yamada switch (e->type) {
3990a9064fbSMasahiro Yamada case E_AND:
4000a9064fbSMasahiro Yamada case E_OR:
4010a9064fbSMasahiro Yamada case E_NOT:
4020a9064fbSMasahiro Yamada e->left.expr = expr_trans_bool(e->left.expr);
4030a9064fbSMasahiro Yamada e->right.expr = expr_trans_bool(e->right.expr);
4040a9064fbSMasahiro Yamada break;
4050a9064fbSMasahiro Yamada case E_UNEQUAL:
4060a9064fbSMasahiro Yamada // FOO!=n -> FOO
4070a9064fbSMasahiro Yamada if (e->left.sym->type == S_TRISTATE) {
4080a9064fbSMasahiro Yamada if (e->right.sym == &symbol_no) {
4090a9064fbSMasahiro Yamada e->type = E_SYMBOL;
4100a9064fbSMasahiro Yamada e->right.sym = NULL;
4110a9064fbSMasahiro Yamada }
4120a9064fbSMasahiro Yamada }
4130a9064fbSMasahiro Yamada break;
4140a9064fbSMasahiro Yamada default:
4150a9064fbSMasahiro Yamada ;
4160a9064fbSMasahiro Yamada }
4170a9064fbSMasahiro Yamada return e;
4180a9064fbSMasahiro Yamada }
4190a9064fbSMasahiro Yamada
4200a9064fbSMasahiro Yamada /*
4210a9064fbSMasahiro Yamada * e1 || e2 -> ?
4220a9064fbSMasahiro Yamada */
expr_join_or(struct expr * e1,struct expr * e2)4230a9064fbSMasahiro Yamada static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
4240a9064fbSMasahiro Yamada {
4250a9064fbSMasahiro Yamada struct expr *tmp;
4260a9064fbSMasahiro Yamada struct symbol *sym1, *sym2;
4270a9064fbSMasahiro Yamada
4280a9064fbSMasahiro Yamada if (expr_eq(e1, e2))
4290a9064fbSMasahiro Yamada return expr_copy(e1);
4300a9064fbSMasahiro Yamada if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
4310a9064fbSMasahiro Yamada return NULL;
4320a9064fbSMasahiro Yamada if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
4330a9064fbSMasahiro Yamada return NULL;
4340a9064fbSMasahiro Yamada if (e1->type == E_NOT) {
4350a9064fbSMasahiro Yamada tmp = e1->left.expr;
4360a9064fbSMasahiro Yamada if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
4370a9064fbSMasahiro Yamada return NULL;
4380a9064fbSMasahiro Yamada sym1 = tmp->left.sym;
4390a9064fbSMasahiro Yamada } else
4400a9064fbSMasahiro Yamada sym1 = e1->left.sym;
4410a9064fbSMasahiro Yamada if (e2->type == E_NOT) {
4420a9064fbSMasahiro Yamada if (e2->left.expr->type != E_SYMBOL)
4430a9064fbSMasahiro Yamada return NULL;
4440a9064fbSMasahiro Yamada sym2 = e2->left.expr->left.sym;
4450a9064fbSMasahiro Yamada } else
4460a9064fbSMasahiro Yamada sym2 = e2->left.sym;
4470a9064fbSMasahiro Yamada if (sym1 != sym2)
4480a9064fbSMasahiro Yamada return NULL;
4490a9064fbSMasahiro Yamada if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
4500a9064fbSMasahiro Yamada return NULL;
4510a9064fbSMasahiro Yamada if (sym1->type == S_TRISTATE) {
4520a9064fbSMasahiro Yamada if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
4530a9064fbSMasahiro Yamada ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
4540a9064fbSMasahiro Yamada (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
4550a9064fbSMasahiro Yamada // (a='y') || (a='m') -> (a!='n')
4560a9064fbSMasahiro Yamada return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
4570a9064fbSMasahiro Yamada }
4580a9064fbSMasahiro Yamada if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
4590a9064fbSMasahiro Yamada ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
4600a9064fbSMasahiro Yamada (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
4610a9064fbSMasahiro Yamada // (a='y') || (a='n') -> (a!='m')
4620a9064fbSMasahiro Yamada return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
4630a9064fbSMasahiro Yamada }
4640a9064fbSMasahiro Yamada if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
4650a9064fbSMasahiro Yamada ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
4660a9064fbSMasahiro Yamada (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
4670a9064fbSMasahiro Yamada // (a='m') || (a='n') -> (a!='y')
4680a9064fbSMasahiro Yamada return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
4690a9064fbSMasahiro Yamada }
4700a9064fbSMasahiro Yamada }
4710a9064fbSMasahiro Yamada if (sym1->type == S_BOOLEAN && sym1 == sym2) {
4720a9064fbSMasahiro Yamada if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
4730a9064fbSMasahiro Yamada (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
4740a9064fbSMasahiro Yamada return expr_alloc_symbol(&symbol_yes);
4750a9064fbSMasahiro Yamada }
4760a9064fbSMasahiro Yamada
4770a9064fbSMasahiro Yamada if (DEBUG_EXPR) {
4780a9064fbSMasahiro Yamada printf("optimize (");
4790a9064fbSMasahiro Yamada expr_fprint(e1, stdout);
4800a9064fbSMasahiro Yamada printf(") || (");
4810a9064fbSMasahiro Yamada expr_fprint(e2, stdout);
4820a9064fbSMasahiro Yamada printf(")?\n");
4830a9064fbSMasahiro Yamada }
4840a9064fbSMasahiro Yamada return NULL;
4850a9064fbSMasahiro Yamada }
4860a9064fbSMasahiro Yamada
expr_join_and(struct expr * e1,struct expr * e2)4870a9064fbSMasahiro Yamada static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
4880a9064fbSMasahiro Yamada {
4890a9064fbSMasahiro Yamada struct expr *tmp;
4900a9064fbSMasahiro Yamada struct symbol *sym1, *sym2;
4910a9064fbSMasahiro Yamada
4920a9064fbSMasahiro Yamada if (expr_eq(e1, e2))
4930a9064fbSMasahiro Yamada return expr_copy(e1);
4940a9064fbSMasahiro Yamada if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
4950a9064fbSMasahiro Yamada return NULL;
4960a9064fbSMasahiro Yamada if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
4970a9064fbSMasahiro Yamada return NULL;
4980a9064fbSMasahiro Yamada if (e1->type == E_NOT) {
4990a9064fbSMasahiro Yamada tmp = e1->left.expr;
5000a9064fbSMasahiro Yamada if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
5010a9064fbSMasahiro Yamada return NULL;
5020a9064fbSMasahiro Yamada sym1 = tmp->left.sym;
5030a9064fbSMasahiro Yamada } else
5040a9064fbSMasahiro Yamada sym1 = e1->left.sym;
5050a9064fbSMasahiro Yamada if (e2->type == E_NOT) {
5060a9064fbSMasahiro Yamada if (e2->left.expr->type != E_SYMBOL)
5070a9064fbSMasahiro Yamada return NULL;
5080a9064fbSMasahiro Yamada sym2 = e2->left.expr->left.sym;
5090a9064fbSMasahiro Yamada } else
5100a9064fbSMasahiro Yamada sym2 = e2->left.sym;
5110a9064fbSMasahiro Yamada if (sym1 != sym2)
5120a9064fbSMasahiro Yamada return NULL;
5130a9064fbSMasahiro Yamada if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
5140a9064fbSMasahiro Yamada return NULL;
5150a9064fbSMasahiro Yamada
5160a9064fbSMasahiro Yamada if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
5170a9064fbSMasahiro Yamada (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
5180a9064fbSMasahiro Yamada // (a) && (a='y') -> (a='y')
5190a9064fbSMasahiro Yamada return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
5200a9064fbSMasahiro Yamada
5210a9064fbSMasahiro Yamada if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
5220a9064fbSMasahiro Yamada (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
5230a9064fbSMasahiro Yamada // (a) && (a!='n') -> (a)
5240a9064fbSMasahiro Yamada return expr_alloc_symbol(sym1);
5250a9064fbSMasahiro Yamada
5260a9064fbSMasahiro Yamada if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
5270a9064fbSMasahiro Yamada (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
5280a9064fbSMasahiro Yamada // (a) && (a!='m') -> (a='y')
5290a9064fbSMasahiro Yamada return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
5300a9064fbSMasahiro Yamada
5310a9064fbSMasahiro Yamada if (sym1->type == S_TRISTATE) {
5320a9064fbSMasahiro Yamada if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
5330a9064fbSMasahiro Yamada // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
5340a9064fbSMasahiro Yamada sym2 = e1->right.sym;
5350a9064fbSMasahiro Yamada if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
5360a9064fbSMasahiro Yamada return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
5370a9064fbSMasahiro Yamada : expr_alloc_symbol(&symbol_no);
5380a9064fbSMasahiro Yamada }
5390a9064fbSMasahiro Yamada if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
5400a9064fbSMasahiro Yamada // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
5410a9064fbSMasahiro Yamada sym2 = e2->right.sym;
5420a9064fbSMasahiro Yamada if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
5430a9064fbSMasahiro Yamada return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
5440a9064fbSMasahiro Yamada : expr_alloc_symbol(&symbol_no);
5450a9064fbSMasahiro Yamada }
5460a9064fbSMasahiro Yamada if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
5470a9064fbSMasahiro Yamada ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
5480a9064fbSMasahiro Yamada (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
5490a9064fbSMasahiro Yamada // (a!='y') && (a!='n') -> (a='m')
5500a9064fbSMasahiro Yamada return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
5510a9064fbSMasahiro Yamada
5520a9064fbSMasahiro Yamada if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
5530a9064fbSMasahiro Yamada ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
5540a9064fbSMasahiro Yamada (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
5550a9064fbSMasahiro Yamada // (a!='y') && (a!='m') -> (a='n')
5560a9064fbSMasahiro Yamada return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
5570a9064fbSMasahiro Yamada
5580a9064fbSMasahiro Yamada if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
5590a9064fbSMasahiro Yamada ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
5600a9064fbSMasahiro Yamada (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
5610a9064fbSMasahiro Yamada // (a!='m') && (a!='n') -> (a='m')
5620a9064fbSMasahiro Yamada return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
5630a9064fbSMasahiro Yamada
5640a9064fbSMasahiro Yamada if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
5650a9064fbSMasahiro Yamada (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
5660a9064fbSMasahiro Yamada (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
5670a9064fbSMasahiro Yamada (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
5680a9064fbSMasahiro Yamada return NULL;
5690a9064fbSMasahiro Yamada }
5700a9064fbSMasahiro Yamada
5710a9064fbSMasahiro Yamada if (DEBUG_EXPR) {
5720a9064fbSMasahiro Yamada printf("optimize (");
5730a9064fbSMasahiro Yamada expr_fprint(e1, stdout);
5740a9064fbSMasahiro Yamada printf(") && (");
5750a9064fbSMasahiro Yamada expr_fprint(e2, stdout);
5760a9064fbSMasahiro Yamada printf(")?\n");
5770a9064fbSMasahiro Yamada }
5780a9064fbSMasahiro Yamada return NULL;
5790a9064fbSMasahiro Yamada }
5800a9064fbSMasahiro Yamada
581*e91610daSEugeniu Rosca /*
582*e91610daSEugeniu Rosca * expr_eliminate_dups() helper.
583*e91610daSEugeniu Rosca *
584*e91610daSEugeniu Rosca * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
585*e91610daSEugeniu Rosca * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
586*e91610daSEugeniu Rosca * against all other leaves to look for simplifications.
587*e91610daSEugeniu Rosca */
expr_eliminate_dups1(enum expr_type type,struct expr ** ep1,struct expr ** ep2)5880a9064fbSMasahiro Yamada static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
5890a9064fbSMasahiro Yamada {
5900a9064fbSMasahiro Yamada #define e1 (*ep1)
5910a9064fbSMasahiro Yamada #define e2 (*ep2)
5920a9064fbSMasahiro Yamada struct expr *tmp;
5930a9064fbSMasahiro Yamada
594*e91610daSEugeniu Rosca /* Recurse down to leaves */
595*e91610daSEugeniu Rosca
5960a9064fbSMasahiro Yamada if (e1->type == type) {
5970a9064fbSMasahiro Yamada expr_eliminate_dups1(type, &e1->left.expr, &e2);
5980a9064fbSMasahiro Yamada expr_eliminate_dups1(type, &e1->right.expr, &e2);
5990a9064fbSMasahiro Yamada return;
6000a9064fbSMasahiro Yamada }
6010a9064fbSMasahiro Yamada if (e2->type == type) {
6020a9064fbSMasahiro Yamada expr_eliminate_dups1(type, &e1, &e2->left.expr);
6030a9064fbSMasahiro Yamada expr_eliminate_dups1(type, &e1, &e2->right.expr);
6040a9064fbSMasahiro Yamada return;
6050a9064fbSMasahiro Yamada }
606*e91610daSEugeniu Rosca
607*e91610daSEugeniu Rosca /* e1 and e2 are leaves. Compare and process them. */
608*e91610daSEugeniu Rosca
6090a9064fbSMasahiro Yamada if (e1 == e2)
6100a9064fbSMasahiro Yamada return;
6110a9064fbSMasahiro Yamada
6120a9064fbSMasahiro Yamada switch (e1->type) {
6130a9064fbSMasahiro Yamada case E_OR: case E_AND:
6140a9064fbSMasahiro Yamada expr_eliminate_dups1(e1->type, &e1, &e1);
6150a9064fbSMasahiro Yamada default:
6160a9064fbSMasahiro Yamada ;
6170a9064fbSMasahiro Yamada }
6180a9064fbSMasahiro Yamada
6190a9064fbSMasahiro Yamada switch (type) {
6200a9064fbSMasahiro Yamada case E_OR:
6210a9064fbSMasahiro Yamada tmp = expr_join_or(e1, e2);
6220a9064fbSMasahiro Yamada if (tmp) {
6230a9064fbSMasahiro Yamada expr_free(e1); expr_free(e2);
6240a9064fbSMasahiro Yamada e1 = expr_alloc_symbol(&symbol_no);
6250a9064fbSMasahiro Yamada e2 = tmp;
6260a9064fbSMasahiro Yamada trans_count++;
6270a9064fbSMasahiro Yamada }
6280a9064fbSMasahiro Yamada break;
6290a9064fbSMasahiro Yamada case E_AND:
6300a9064fbSMasahiro Yamada tmp = expr_join_and(e1, e2);
6310a9064fbSMasahiro Yamada if (tmp) {
6320a9064fbSMasahiro Yamada expr_free(e1); expr_free(e2);
6330a9064fbSMasahiro Yamada e1 = expr_alloc_symbol(&symbol_yes);
6340a9064fbSMasahiro Yamada e2 = tmp;
6350a9064fbSMasahiro Yamada trans_count++;
6360a9064fbSMasahiro Yamada }
6370a9064fbSMasahiro Yamada break;
6380a9064fbSMasahiro Yamada default:
6390a9064fbSMasahiro Yamada ;
6400a9064fbSMasahiro Yamada }
6410a9064fbSMasahiro Yamada #undef e1
6420a9064fbSMasahiro Yamada #undef e2
6430a9064fbSMasahiro Yamada }
6440a9064fbSMasahiro Yamada
645*e91610daSEugeniu Rosca /*
646*e91610daSEugeniu Rosca * Rewrites 'e' in-place to remove ("join") duplicate and other redundant
647*e91610daSEugeniu Rosca * operands.
648*e91610daSEugeniu Rosca *
649*e91610daSEugeniu Rosca * Example simplifications:
650*e91610daSEugeniu Rosca *
651*e91610daSEugeniu Rosca * A || B || A -> A || B
652*e91610daSEugeniu Rosca * A && B && A=y -> A=y && B
653*e91610daSEugeniu Rosca *
654*e91610daSEugeniu Rosca * Returns the deduplicated expression.
655*e91610daSEugeniu Rosca */
expr_eliminate_dups(struct expr * e)6560a9064fbSMasahiro Yamada struct expr *expr_eliminate_dups(struct expr *e)
6570a9064fbSMasahiro Yamada {
6580a9064fbSMasahiro Yamada int oldcount;
6590a9064fbSMasahiro Yamada if (!e)
6600a9064fbSMasahiro Yamada return e;
6610a9064fbSMasahiro Yamada
6620a9064fbSMasahiro Yamada oldcount = trans_count;
6630a9064fbSMasahiro Yamada while (1) {
6640a9064fbSMasahiro Yamada trans_count = 0;
6650a9064fbSMasahiro Yamada switch (e->type) {
6660a9064fbSMasahiro Yamada case E_OR: case E_AND:
6670a9064fbSMasahiro Yamada expr_eliminate_dups1(e->type, &e, &e);
6680a9064fbSMasahiro Yamada default:
6690a9064fbSMasahiro Yamada ;
6700a9064fbSMasahiro Yamada }
6710a9064fbSMasahiro Yamada if (!trans_count)
672*e91610daSEugeniu Rosca /* No simplifications done in this pass. We're done */
6730a9064fbSMasahiro Yamada break;
6740a9064fbSMasahiro Yamada e = expr_eliminate_yn(e);
6750a9064fbSMasahiro Yamada }
6760a9064fbSMasahiro Yamada trans_count = oldcount;
6770a9064fbSMasahiro Yamada return e;
6780a9064fbSMasahiro Yamada }
6790a9064fbSMasahiro Yamada
680*e91610daSEugeniu Rosca /*
681*e91610daSEugeniu Rosca * Performs various simplifications involving logical operators and
682*e91610daSEugeniu Rosca * comparisons.
683*e91610daSEugeniu Rosca *
684*e91610daSEugeniu Rosca * Allocates and returns a new expression.
685*e91610daSEugeniu Rosca */
expr_transform(struct expr * e)6860a9064fbSMasahiro Yamada struct expr *expr_transform(struct expr *e)
6870a9064fbSMasahiro Yamada {
6880a9064fbSMasahiro Yamada struct expr *tmp;
6890a9064fbSMasahiro Yamada
6900a9064fbSMasahiro Yamada if (!e)
6910a9064fbSMasahiro Yamada return NULL;
6920a9064fbSMasahiro Yamada switch (e->type) {
6930a9064fbSMasahiro Yamada case E_EQUAL:
694bf7ab1e7SMasahiro Yamada case E_GEQ:
695bf7ab1e7SMasahiro Yamada case E_GTH:
696bf7ab1e7SMasahiro Yamada case E_LEQ:
697bf7ab1e7SMasahiro Yamada case E_LTH:
6980a9064fbSMasahiro Yamada case E_UNEQUAL:
6990a9064fbSMasahiro Yamada case E_SYMBOL:
7000a9064fbSMasahiro Yamada case E_LIST:
7010a9064fbSMasahiro Yamada break;
7020a9064fbSMasahiro Yamada default:
7030a9064fbSMasahiro Yamada e->left.expr = expr_transform(e->left.expr);
7040a9064fbSMasahiro Yamada e->right.expr = expr_transform(e->right.expr);
7050a9064fbSMasahiro Yamada }
7060a9064fbSMasahiro Yamada
7070a9064fbSMasahiro Yamada switch (e->type) {
7080a9064fbSMasahiro Yamada case E_EQUAL:
7090a9064fbSMasahiro Yamada if (e->left.sym->type != S_BOOLEAN)
7100a9064fbSMasahiro Yamada break;
7110a9064fbSMasahiro Yamada if (e->right.sym == &symbol_no) {
7120a9064fbSMasahiro Yamada e->type = E_NOT;
7130a9064fbSMasahiro Yamada e->left.expr = expr_alloc_symbol(e->left.sym);
7140a9064fbSMasahiro Yamada e->right.sym = NULL;
7150a9064fbSMasahiro Yamada break;
7160a9064fbSMasahiro Yamada }
7170a9064fbSMasahiro Yamada if (e->right.sym == &symbol_mod) {
7180a9064fbSMasahiro Yamada printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
7190a9064fbSMasahiro Yamada e->type = E_SYMBOL;
7200a9064fbSMasahiro Yamada e->left.sym = &symbol_no;
7210a9064fbSMasahiro Yamada e->right.sym = NULL;
7220a9064fbSMasahiro Yamada break;
7230a9064fbSMasahiro Yamada }
7240a9064fbSMasahiro Yamada if (e->right.sym == &symbol_yes) {
7250a9064fbSMasahiro Yamada e->type = E_SYMBOL;
7260a9064fbSMasahiro Yamada e->right.sym = NULL;
7270a9064fbSMasahiro Yamada break;
7280a9064fbSMasahiro Yamada }
7290a9064fbSMasahiro Yamada break;
7300a9064fbSMasahiro Yamada case E_UNEQUAL:
7310a9064fbSMasahiro Yamada if (e->left.sym->type != S_BOOLEAN)
7320a9064fbSMasahiro Yamada break;
7330a9064fbSMasahiro Yamada if (e->right.sym == &symbol_no) {
7340a9064fbSMasahiro Yamada e->type = E_SYMBOL;
7350a9064fbSMasahiro Yamada e->right.sym = NULL;
7360a9064fbSMasahiro Yamada break;
7370a9064fbSMasahiro Yamada }
7380a9064fbSMasahiro Yamada if (e->right.sym == &symbol_mod) {
7390a9064fbSMasahiro Yamada printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
7400a9064fbSMasahiro Yamada e->type = E_SYMBOL;
7410a9064fbSMasahiro Yamada e->left.sym = &symbol_yes;
7420a9064fbSMasahiro Yamada e->right.sym = NULL;
7430a9064fbSMasahiro Yamada break;
7440a9064fbSMasahiro Yamada }
7450a9064fbSMasahiro Yamada if (e->right.sym == &symbol_yes) {
7460a9064fbSMasahiro Yamada e->type = E_NOT;
7470a9064fbSMasahiro Yamada e->left.expr = expr_alloc_symbol(e->left.sym);
7480a9064fbSMasahiro Yamada e->right.sym = NULL;
7490a9064fbSMasahiro Yamada break;
7500a9064fbSMasahiro Yamada }
7510a9064fbSMasahiro Yamada break;
7520a9064fbSMasahiro Yamada case E_NOT:
7530a9064fbSMasahiro Yamada switch (e->left.expr->type) {
7540a9064fbSMasahiro Yamada case E_NOT:
7550a9064fbSMasahiro Yamada // !!a -> a
7560a9064fbSMasahiro Yamada tmp = e->left.expr->left.expr;
7570a9064fbSMasahiro Yamada free(e->left.expr);
7580a9064fbSMasahiro Yamada free(e);
7590a9064fbSMasahiro Yamada e = tmp;
7600a9064fbSMasahiro Yamada e = expr_transform(e);
7610a9064fbSMasahiro Yamada break;
7620a9064fbSMasahiro Yamada case E_EQUAL:
7630a9064fbSMasahiro Yamada case E_UNEQUAL:
7640a9064fbSMasahiro Yamada // !a='x' -> a!='x'
7650a9064fbSMasahiro Yamada tmp = e->left.expr;
7660a9064fbSMasahiro Yamada free(e);
7670a9064fbSMasahiro Yamada e = tmp;
7680a9064fbSMasahiro Yamada e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
7690a9064fbSMasahiro Yamada break;
770bf7ab1e7SMasahiro Yamada case E_LEQ:
771bf7ab1e7SMasahiro Yamada case E_GEQ:
772bf7ab1e7SMasahiro Yamada // !a<='x' -> a>'x'
773bf7ab1e7SMasahiro Yamada tmp = e->left.expr;
774bf7ab1e7SMasahiro Yamada free(e);
775bf7ab1e7SMasahiro Yamada e = tmp;
776bf7ab1e7SMasahiro Yamada e->type = e->type == E_LEQ ? E_GTH : E_LTH;
777bf7ab1e7SMasahiro Yamada break;
778bf7ab1e7SMasahiro Yamada case E_LTH:
779bf7ab1e7SMasahiro Yamada case E_GTH:
780bf7ab1e7SMasahiro Yamada // !a<'x' -> a>='x'
781bf7ab1e7SMasahiro Yamada tmp = e->left.expr;
782bf7ab1e7SMasahiro Yamada free(e);
783bf7ab1e7SMasahiro Yamada e = tmp;
784bf7ab1e7SMasahiro Yamada e->type = e->type == E_LTH ? E_GEQ : E_LEQ;
785bf7ab1e7SMasahiro Yamada break;
7860a9064fbSMasahiro Yamada case E_OR:
7870a9064fbSMasahiro Yamada // !(a || b) -> !a && !b
7880a9064fbSMasahiro Yamada tmp = e->left.expr;
7890a9064fbSMasahiro Yamada e->type = E_AND;
7900a9064fbSMasahiro Yamada e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
7910a9064fbSMasahiro Yamada tmp->type = E_NOT;
7920a9064fbSMasahiro Yamada tmp->right.expr = NULL;
7930a9064fbSMasahiro Yamada e = expr_transform(e);
7940a9064fbSMasahiro Yamada break;
7950a9064fbSMasahiro Yamada case E_AND:
7960a9064fbSMasahiro Yamada // !(a && b) -> !a || !b
7970a9064fbSMasahiro Yamada tmp = e->left.expr;
7980a9064fbSMasahiro Yamada e->type = E_OR;
7990a9064fbSMasahiro Yamada e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
8000a9064fbSMasahiro Yamada tmp->type = E_NOT;
8010a9064fbSMasahiro Yamada tmp->right.expr = NULL;
8020a9064fbSMasahiro Yamada e = expr_transform(e);
8030a9064fbSMasahiro Yamada break;
8040a9064fbSMasahiro Yamada case E_SYMBOL:
8050a9064fbSMasahiro Yamada if (e->left.expr->left.sym == &symbol_yes) {
8060a9064fbSMasahiro Yamada // !'y' -> 'n'
8070a9064fbSMasahiro Yamada tmp = e->left.expr;
8080a9064fbSMasahiro Yamada free(e);
8090a9064fbSMasahiro Yamada e = tmp;
8100a9064fbSMasahiro Yamada e->type = E_SYMBOL;
8110a9064fbSMasahiro Yamada e->left.sym = &symbol_no;
8120a9064fbSMasahiro Yamada break;
8130a9064fbSMasahiro Yamada }
8140a9064fbSMasahiro Yamada if (e->left.expr->left.sym == &symbol_mod) {
8150a9064fbSMasahiro Yamada // !'m' -> 'm'
8160a9064fbSMasahiro Yamada tmp = e->left.expr;
8170a9064fbSMasahiro Yamada free(e);
8180a9064fbSMasahiro Yamada e = tmp;
8190a9064fbSMasahiro Yamada e->type = E_SYMBOL;
8200a9064fbSMasahiro Yamada e->left.sym = &symbol_mod;
8210a9064fbSMasahiro Yamada break;
8220a9064fbSMasahiro Yamada }
8230a9064fbSMasahiro Yamada if (e->left.expr->left.sym == &symbol_no) {
8240a9064fbSMasahiro Yamada // !'n' -> 'y'
8250a9064fbSMasahiro Yamada tmp = e->left.expr;
8260a9064fbSMasahiro Yamada free(e);
8270a9064fbSMasahiro Yamada e = tmp;
8280a9064fbSMasahiro Yamada e->type = E_SYMBOL;
8290a9064fbSMasahiro Yamada e->left.sym = &symbol_yes;
8300a9064fbSMasahiro Yamada break;
8310a9064fbSMasahiro Yamada }
8320a9064fbSMasahiro Yamada break;
8330a9064fbSMasahiro Yamada default:
8340a9064fbSMasahiro Yamada ;
8350a9064fbSMasahiro Yamada }
8360a9064fbSMasahiro Yamada break;
8370a9064fbSMasahiro Yamada default:
8380a9064fbSMasahiro Yamada ;
8390a9064fbSMasahiro Yamada }
8400a9064fbSMasahiro Yamada return e;
8410a9064fbSMasahiro Yamada }
8420a9064fbSMasahiro Yamada
expr_contains_symbol(struct expr * dep,struct symbol * sym)8430a9064fbSMasahiro Yamada int expr_contains_symbol(struct expr *dep, struct symbol *sym)
8440a9064fbSMasahiro Yamada {
8450a9064fbSMasahiro Yamada if (!dep)
8460a9064fbSMasahiro Yamada return 0;
8470a9064fbSMasahiro Yamada
8480a9064fbSMasahiro Yamada switch (dep->type) {
8490a9064fbSMasahiro Yamada case E_AND:
8500a9064fbSMasahiro Yamada case E_OR:
8510a9064fbSMasahiro Yamada return expr_contains_symbol(dep->left.expr, sym) ||
8520a9064fbSMasahiro Yamada expr_contains_symbol(dep->right.expr, sym);
8530a9064fbSMasahiro Yamada case E_SYMBOL:
8540a9064fbSMasahiro Yamada return dep->left.sym == sym;
8550a9064fbSMasahiro Yamada case E_EQUAL:
856bf7ab1e7SMasahiro Yamada case E_GEQ:
857bf7ab1e7SMasahiro Yamada case E_GTH:
858bf7ab1e7SMasahiro Yamada case E_LEQ:
859bf7ab1e7SMasahiro Yamada case E_LTH:
8600a9064fbSMasahiro Yamada case E_UNEQUAL:
8610a9064fbSMasahiro Yamada return dep->left.sym == sym ||
8620a9064fbSMasahiro Yamada dep->right.sym == sym;
8630a9064fbSMasahiro Yamada case E_NOT:
8640a9064fbSMasahiro Yamada return expr_contains_symbol(dep->left.expr, sym);
8650a9064fbSMasahiro Yamada default:
8660a9064fbSMasahiro Yamada ;
8670a9064fbSMasahiro Yamada }
8680a9064fbSMasahiro Yamada return 0;
8690a9064fbSMasahiro Yamada }
8700a9064fbSMasahiro Yamada
expr_depends_symbol(struct expr * dep,struct symbol * sym)8710a9064fbSMasahiro Yamada bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
8720a9064fbSMasahiro Yamada {
8730a9064fbSMasahiro Yamada if (!dep)
8740a9064fbSMasahiro Yamada return false;
8750a9064fbSMasahiro Yamada
8760a9064fbSMasahiro Yamada switch (dep->type) {
8770a9064fbSMasahiro Yamada case E_AND:
8780a9064fbSMasahiro Yamada return expr_depends_symbol(dep->left.expr, sym) ||
8790a9064fbSMasahiro Yamada expr_depends_symbol(dep->right.expr, sym);
8800a9064fbSMasahiro Yamada case E_SYMBOL:
8810a9064fbSMasahiro Yamada return dep->left.sym == sym;
8820a9064fbSMasahiro Yamada case E_EQUAL:
8830a9064fbSMasahiro Yamada if (dep->left.sym == sym) {
8840a9064fbSMasahiro Yamada if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
8850a9064fbSMasahiro Yamada return true;
8860a9064fbSMasahiro Yamada }
8870a9064fbSMasahiro Yamada break;
8880a9064fbSMasahiro Yamada case E_UNEQUAL:
8890a9064fbSMasahiro Yamada if (dep->left.sym == sym) {
8900a9064fbSMasahiro Yamada if (dep->right.sym == &symbol_no)
8910a9064fbSMasahiro Yamada return true;
8920a9064fbSMasahiro Yamada }
8930a9064fbSMasahiro Yamada break;
8940a9064fbSMasahiro Yamada default:
8950a9064fbSMasahiro Yamada ;
8960a9064fbSMasahiro Yamada }
8970a9064fbSMasahiro Yamada return false;
8980a9064fbSMasahiro Yamada }
8990a9064fbSMasahiro Yamada
900*e91610daSEugeniu Rosca /*
901*e91610daSEugeniu Rosca * Inserts explicit comparisons of type 'type' to symbol 'sym' into the
902*e91610daSEugeniu Rosca * expression 'e'.
903*e91610daSEugeniu Rosca *
904*e91610daSEugeniu Rosca * Examples transformations for type == E_UNEQUAL, sym == &symbol_no:
905*e91610daSEugeniu Rosca *
906*e91610daSEugeniu Rosca * A -> A!=n
907*e91610daSEugeniu Rosca * !A -> A=n
908*e91610daSEugeniu Rosca * A && B -> !(A=n || B=n)
909*e91610daSEugeniu Rosca * A || B -> !(A=n && B=n)
910*e91610daSEugeniu Rosca * A && (B || C) -> !(A=n || (B=n && C=n))
911*e91610daSEugeniu Rosca *
912*e91610daSEugeniu Rosca * Allocates and returns a new expression.
913*e91610daSEugeniu Rosca */
expr_trans_compare(struct expr * e,enum expr_type type,struct symbol * sym)9140a9064fbSMasahiro Yamada struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
9150a9064fbSMasahiro Yamada {
9160a9064fbSMasahiro Yamada struct expr *e1, *e2;
9170a9064fbSMasahiro Yamada
9180a9064fbSMasahiro Yamada if (!e) {
9190a9064fbSMasahiro Yamada e = expr_alloc_symbol(sym);
9200a9064fbSMasahiro Yamada if (type == E_UNEQUAL)
9210a9064fbSMasahiro Yamada e = expr_alloc_one(E_NOT, e);
9220a9064fbSMasahiro Yamada return e;
9230a9064fbSMasahiro Yamada }
9240a9064fbSMasahiro Yamada switch (e->type) {
9250a9064fbSMasahiro Yamada case E_AND:
9260a9064fbSMasahiro Yamada e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
9270a9064fbSMasahiro Yamada e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
9280a9064fbSMasahiro Yamada if (sym == &symbol_yes)
9290a9064fbSMasahiro Yamada e = expr_alloc_two(E_AND, e1, e2);
9300a9064fbSMasahiro Yamada if (sym == &symbol_no)
9310a9064fbSMasahiro Yamada e = expr_alloc_two(E_OR, e1, e2);
9320a9064fbSMasahiro Yamada if (type == E_UNEQUAL)
9330a9064fbSMasahiro Yamada e = expr_alloc_one(E_NOT, e);
9340a9064fbSMasahiro Yamada return e;
9350a9064fbSMasahiro Yamada case E_OR:
9360a9064fbSMasahiro Yamada e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
9370a9064fbSMasahiro Yamada e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
9380a9064fbSMasahiro Yamada if (sym == &symbol_yes)
9390a9064fbSMasahiro Yamada e = expr_alloc_two(E_OR, e1, e2);
9400a9064fbSMasahiro Yamada if (sym == &symbol_no)
9410a9064fbSMasahiro Yamada e = expr_alloc_two(E_AND, e1, e2);
9420a9064fbSMasahiro Yamada if (type == E_UNEQUAL)
9430a9064fbSMasahiro Yamada e = expr_alloc_one(E_NOT, e);
9440a9064fbSMasahiro Yamada return e;
9450a9064fbSMasahiro Yamada case E_NOT:
9460a9064fbSMasahiro Yamada return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
9470a9064fbSMasahiro Yamada case E_UNEQUAL:
948bf7ab1e7SMasahiro Yamada case E_LTH:
949bf7ab1e7SMasahiro Yamada case E_LEQ:
950bf7ab1e7SMasahiro Yamada case E_GTH:
951bf7ab1e7SMasahiro Yamada case E_GEQ:
9520a9064fbSMasahiro Yamada case E_EQUAL:
9530a9064fbSMasahiro Yamada if (type == E_EQUAL) {
9540a9064fbSMasahiro Yamada if (sym == &symbol_yes)
9550a9064fbSMasahiro Yamada return expr_copy(e);
9560a9064fbSMasahiro Yamada if (sym == &symbol_mod)
9570a9064fbSMasahiro Yamada return expr_alloc_symbol(&symbol_no);
9580a9064fbSMasahiro Yamada if (sym == &symbol_no)
9590a9064fbSMasahiro Yamada return expr_alloc_one(E_NOT, expr_copy(e));
9600a9064fbSMasahiro Yamada } else {
9610a9064fbSMasahiro Yamada if (sym == &symbol_yes)
9620a9064fbSMasahiro Yamada return expr_alloc_one(E_NOT, expr_copy(e));
9630a9064fbSMasahiro Yamada if (sym == &symbol_mod)
9640a9064fbSMasahiro Yamada return expr_alloc_symbol(&symbol_yes);
9650a9064fbSMasahiro Yamada if (sym == &symbol_no)
9660a9064fbSMasahiro Yamada return expr_copy(e);
9670a9064fbSMasahiro Yamada }
9680a9064fbSMasahiro Yamada break;
9690a9064fbSMasahiro Yamada case E_SYMBOL:
9700a9064fbSMasahiro Yamada return expr_alloc_comp(type, e->left.sym, sym);
9710a9064fbSMasahiro Yamada case E_LIST:
9720a9064fbSMasahiro Yamada case E_RANGE:
9730a9064fbSMasahiro Yamada case E_NONE:
9740a9064fbSMasahiro Yamada /* panic */;
9750a9064fbSMasahiro Yamada }
9760a9064fbSMasahiro Yamada return NULL;
9770a9064fbSMasahiro Yamada }
9780a9064fbSMasahiro Yamada
979bf7ab1e7SMasahiro Yamada enum string_value_kind {
980bf7ab1e7SMasahiro Yamada k_string,
981bf7ab1e7SMasahiro Yamada k_signed,
982bf7ab1e7SMasahiro Yamada k_unsigned,
983bf7ab1e7SMasahiro Yamada k_invalid
984bf7ab1e7SMasahiro Yamada };
985bf7ab1e7SMasahiro Yamada
986bf7ab1e7SMasahiro Yamada union string_value {
987bf7ab1e7SMasahiro Yamada unsigned long long u;
988bf7ab1e7SMasahiro Yamada signed long long s;
989bf7ab1e7SMasahiro Yamada };
990bf7ab1e7SMasahiro Yamada
expr_parse_string(const char * str,enum symbol_type type,union string_value * val)991bf7ab1e7SMasahiro Yamada static enum string_value_kind expr_parse_string(const char *str,
992bf7ab1e7SMasahiro Yamada enum symbol_type type,
993bf7ab1e7SMasahiro Yamada union string_value *val)
994bf7ab1e7SMasahiro Yamada {
995bf7ab1e7SMasahiro Yamada char *tail;
996bf7ab1e7SMasahiro Yamada enum string_value_kind kind;
997bf7ab1e7SMasahiro Yamada
998bf7ab1e7SMasahiro Yamada errno = 0;
999bf7ab1e7SMasahiro Yamada switch (type) {
1000bf7ab1e7SMasahiro Yamada case S_BOOLEAN:
1001bf7ab1e7SMasahiro Yamada case S_TRISTATE:
1002*e91610daSEugeniu Rosca val->s = !strcmp(str, "n") ? 0 :
1003*e91610daSEugeniu Rosca !strcmp(str, "m") ? 1 :
1004*e91610daSEugeniu Rosca !strcmp(str, "y") ? 2 : -1;
1005*e91610daSEugeniu Rosca return k_signed;
1006bf7ab1e7SMasahiro Yamada case S_INT:
1007bf7ab1e7SMasahiro Yamada val->s = strtoll(str, &tail, 10);
1008bf7ab1e7SMasahiro Yamada kind = k_signed;
1009bf7ab1e7SMasahiro Yamada break;
1010bf7ab1e7SMasahiro Yamada case S_HEX:
1011bf7ab1e7SMasahiro Yamada val->u = strtoull(str, &tail, 16);
1012bf7ab1e7SMasahiro Yamada kind = k_unsigned;
1013bf7ab1e7SMasahiro Yamada break;
1014bf7ab1e7SMasahiro Yamada case S_STRING:
1015bf7ab1e7SMasahiro Yamada case S_UNKNOWN:
1016bf7ab1e7SMasahiro Yamada val->s = strtoll(str, &tail, 0);
1017bf7ab1e7SMasahiro Yamada kind = k_signed;
1018bf7ab1e7SMasahiro Yamada break;
1019bf7ab1e7SMasahiro Yamada default:
1020bf7ab1e7SMasahiro Yamada return k_invalid;
1021bf7ab1e7SMasahiro Yamada }
1022bf7ab1e7SMasahiro Yamada return !errno && !*tail && tail > str && isxdigit(tail[-1])
1023bf7ab1e7SMasahiro Yamada ? kind : k_string;
1024bf7ab1e7SMasahiro Yamada }
1025bf7ab1e7SMasahiro Yamada
expr_calc_value(struct expr * e)10260a9064fbSMasahiro Yamada tristate expr_calc_value(struct expr *e)
10270a9064fbSMasahiro Yamada {
10280a9064fbSMasahiro Yamada tristate val1, val2;
10290a9064fbSMasahiro Yamada const char *str1, *str2;
1030bf7ab1e7SMasahiro Yamada enum string_value_kind k1 = k_string, k2 = k_string;
1031bf7ab1e7SMasahiro Yamada union string_value lval = {}, rval = {};
1032bf7ab1e7SMasahiro Yamada int res;
10330a9064fbSMasahiro Yamada
10340a9064fbSMasahiro Yamada if (!e)
10350a9064fbSMasahiro Yamada return yes;
10360a9064fbSMasahiro Yamada
10370a9064fbSMasahiro Yamada switch (e->type) {
10380a9064fbSMasahiro Yamada case E_SYMBOL:
10390a9064fbSMasahiro Yamada sym_calc_value(e->left.sym);
10400a9064fbSMasahiro Yamada return e->left.sym->curr.tri;
10410a9064fbSMasahiro Yamada case E_AND:
10420a9064fbSMasahiro Yamada val1 = expr_calc_value(e->left.expr);
10430a9064fbSMasahiro Yamada val2 = expr_calc_value(e->right.expr);
10440a9064fbSMasahiro Yamada return EXPR_AND(val1, val2);
10450a9064fbSMasahiro Yamada case E_OR:
10460a9064fbSMasahiro Yamada val1 = expr_calc_value(e->left.expr);
10470a9064fbSMasahiro Yamada val2 = expr_calc_value(e->right.expr);
10480a9064fbSMasahiro Yamada return EXPR_OR(val1, val2);
10490a9064fbSMasahiro Yamada case E_NOT:
10500a9064fbSMasahiro Yamada val1 = expr_calc_value(e->left.expr);
10510a9064fbSMasahiro Yamada return EXPR_NOT(val1);
10520a9064fbSMasahiro Yamada case E_EQUAL:
1053bf7ab1e7SMasahiro Yamada case E_GEQ:
1054bf7ab1e7SMasahiro Yamada case E_GTH:
1055bf7ab1e7SMasahiro Yamada case E_LEQ:
1056bf7ab1e7SMasahiro Yamada case E_LTH:
10570a9064fbSMasahiro Yamada case E_UNEQUAL:
1058bf7ab1e7SMasahiro Yamada break;
10590a9064fbSMasahiro Yamada default:
10600a9064fbSMasahiro Yamada printf("expr_calc_value: %d?\n", e->type);
10610a9064fbSMasahiro Yamada return no;
10620a9064fbSMasahiro Yamada }
1063bf7ab1e7SMasahiro Yamada
1064bf7ab1e7SMasahiro Yamada sym_calc_value(e->left.sym);
1065bf7ab1e7SMasahiro Yamada sym_calc_value(e->right.sym);
1066bf7ab1e7SMasahiro Yamada str1 = sym_get_string_value(e->left.sym);
1067bf7ab1e7SMasahiro Yamada str2 = sym_get_string_value(e->right.sym);
1068bf7ab1e7SMasahiro Yamada
1069bf7ab1e7SMasahiro Yamada if (e->left.sym->type != S_STRING || e->right.sym->type != S_STRING) {
1070bf7ab1e7SMasahiro Yamada k1 = expr_parse_string(str1, e->left.sym->type, &lval);
1071bf7ab1e7SMasahiro Yamada k2 = expr_parse_string(str2, e->right.sym->type, &rval);
1072bf7ab1e7SMasahiro Yamada }
1073bf7ab1e7SMasahiro Yamada
1074bf7ab1e7SMasahiro Yamada if (k1 == k_string || k2 == k_string)
1075bf7ab1e7SMasahiro Yamada res = strcmp(str1, str2);
1076bf7ab1e7SMasahiro Yamada else if (k1 == k_invalid || k2 == k_invalid) {
1077bf7ab1e7SMasahiro Yamada if (e->type != E_EQUAL && e->type != E_UNEQUAL) {
1078bf7ab1e7SMasahiro Yamada printf("Cannot compare \"%s\" and \"%s\"\n", str1, str2);
1079bf7ab1e7SMasahiro Yamada return no;
1080bf7ab1e7SMasahiro Yamada }
1081bf7ab1e7SMasahiro Yamada res = strcmp(str1, str2);
1082bf7ab1e7SMasahiro Yamada } else if (k1 == k_unsigned || k2 == k_unsigned)
1083bf7ab1e7SMasahiro Yamada res = (lval.u > rval.u) - (lval.u < rval.u);
1084bf7ab1e7SMasahiro Yamada else /* if (k1 == k_signed && k2 == k_signed) */
1085bf7ab1e7SMasahiro Yamada res = (lval.s > rval.s) - (lval.s < rval.s);
1086bf7ab1e7SMasahiro Yamada
1087bf7ab1e7SMasahiro Yamada switch(e->type) {
1088bf7ab1e7SMasahiro Yamada case E_EQUAL:
1089bf7ab1e7SMasahiro Yamada return res ? no : yes;
1090bf7ab1e7SMasahiro Yamada case E_GEQ:
1091bf7ab1e7SMasahiro Yamada return res >= 0 ? yes : no;
1092bf7ab1e7SMasahiro Yamada case E_GTH:
1093bf7ab1e7SMasahiro Yamada return res > 0 ? yes : no;
1094bf7ab1e7SMasahiro Yamada case E_LEQ:
1095bf7ab1e7SMasahiro Yamada return res <= 0 ? yes : no;
1096bf7ab1e7SMasahiro Yamada case E_LTH:
1097bf7ab1e7SMasahiro Yamada return res < 0 ? yes : no;
1098bf7ab1e7SMasahiro Yamada case E_UNEQUAL:
1099bf7ab1e7SMasahiro Yamada return res ? yes : no;
1100bf7ab1e7SMasahiro Yamada default:
1101bf7ab1e7SMasahiro Yamada printf("expr_calc_value: relation %d?\n", e->type);
1102bf7ab1e7SMasahiro Yamada return no;
1103bf7ab1e7SMasahiro Yamada }
11040a9064fbSMasahiro Yamada }
11050a9064fbSMasahiro Yamada
expr_compare_type(enum expr_type t1,enum expr_type t2)11069b5f0b1dSMasahiro Yamada static int expr_compare_type(enum expr_type t1, enum expr_type t2)
11070a9064fbSMasahiro Yamada {
11080a9064fbSMasahiro Yamada if (t1 == t2)
11090a9064fbSMasahiro Yamada return 0;
11100a9064fbSMasahiro Yamada switch (t1) {
1111bf7ab1e7SMasahiro Yamada case E_LEQ:
1112bf7ab1e7SMasahiro Yamada case E_LTH:
1113bf7ab1e7SMasahiro Yamada case E_GEQ:
1114bf7ab1e7SMasahiro Yamada case E_GTH:
1115bf7ab1e7SMasahiro Yamada if (t2 == E_EQUAL || t2 == E_UNEQUAL)
1116bf7ab1e7SMasahiro Yamada return 1;
11170a9064fbSMasahiro Yamada case E_EQUAL:
11180a9064fbSMasahiro Yamada case E_UNEQUAL:
11190a9064fbSMasahiro Yamada if (t2 == E_NOT)
11200a9064fbSMasahiro Yamada return 1;
11210a9064fbSMasahiro Yamada case E_NOT:
11220a9064fbSMasahiro Yamada if (t2 == E_AND)
11230a9064fbSMasahiro Yamada return 1;
11240a9064fbSMasahiro Yamada case E_AND:
11250a9064fbSMasahiro Yamada if (t2 == E_OR)
11260a9064fbSMasahiro Yamada return 1;
11270a9064fbSMasahiro Yamada case E_OR:
11280a9064fbSMasahiro Yamada if (t2 == E_LIST)
11290a9064fbSMasahiro Yamada return 1;
11300a9064fbSMasahiro Yamada case E_LIST:
11310a9064fbSMasahiro Yamada if (t2 == 0)
11320a9064fbSMasahiro Yamada return 1;
11330a9064fbSMasahiro Yamada default:
11340a9064fbSMasahiro Yamada return -1;
11350a9064fbSMasahiro Yamada }
11360a9064fbSMasahiro Yamada printf("[%dgt%d?]", t1, t2);
11370a9064fbSMasahiro Yamada return 0;
11380a9064fbSMasahiro Yamada }
11390a9064fbSMasahiro Yamada
expr_print(struct expr * e,void (* fn)(void *,struct symbol *,const char *),void * data,int prevtoken)1140*e91610daSEugeniu Rosca void expr_print(struct expr *e,
1141*e91610daSEugeniu Rosca void (*fn)(void *, struct symbol *, const char *),
1142*e91610daSEugeniu Rosca void *data, int prevtoken)
11430a9064fbSMasahiro Yamada {
11440a9064fbSMasahiro Yamada if (!e) {
11450a9064fbSMasahiro Yamada fn(data, NULL, "y");
11460a9064fbSMasahiro Yamada return;
11470a9064fbSMasahiro Yamada }
11480a9064fbSMasahiro Yamada
11490a9064fbSMasahiro Yamada if (expr_compare_type(prevtoken, e->type) > 0)
11500a9064fbSMasahiro Yamada fn(data, NULL, "(");
11510a9064fbSMasahiro Yamada switch (e->type) {
11520a9064fbSMasahiro Yamada case E_SYMBOL:
11530a9064fbSMasahiro Yamada if (e->left.sym->name)
11540a9064fbSMasahiro Yamada fn(data, e->left.sym, e->left.sym->name);
11550a9064fbSMasahiro Yamada else
11560a9064fbSMasahiro Yamada fn(data, NULL, "<choice>");
11570a9064fbSMasahiro Yamada break;
11580a9064fbSMasahiro Yamada case E_NOT:
11590a9064fbSMasahiro Yamada fn(data, NULL, "!");
11600a9064fbSMasahiro Yamada expr_print(e->left.expr, fn, data, E_NOT);
11610a9064fbSMasahiro Yamada break;
11620a9064fbSMasahiro Yamada case E_EQUAL:
11630a9064fbSMasahiro Yamada if (e->left.sym->name)
11640a9064fbSMasahiro Yamada fn(data, e->left.sym, e->left.sym->name);
11650a9064fbSMasahiro Yamada else
11660a9064fbSMasahiro Yamada fn(data, NULL, "<choice>");
11670a9064fbSMasahiro Yamada fn(data, NULL, "=");
11680a9064fbSMasahiro Yamada fn(data, e->right.sym, e->right.sym->name);
11690a9064fbSMasahiro Yamada break;
1170bf7ab1e7SMasahiro Yamada case E_LEQ:
1171bf7ab1e7SMasahiro Yamada case E_LTH:
1172bf7ab1e7SMasahiro Yamada if (e->left.sym->name)
1173bf7ab1e7SMasahiro Yamada fn(data, e->left.sym, e->left.sym->name);
1174bf7ab1e7SMasahiro Yamada else
1175bf7ab1e7SMasahiro Yamada fn(data, NULL, "<choice>");
1176bf7ab1e7SMasahiro Yamada fn(data, NULL, e->type == E_LEQ ? "<=" : "<");
1177bf7ab1e7SMasahiro Yamada fn(data, e->right.sym, e->right.sym->name);
1178bf7ab1e7SMasahiro Yamada break;
1179bf7ab1e7SMasahiro Yamada case E_GEQ:
1180bf7ab1e7SMasahiro Yamada case E_GTH:
1181bf7ab1e7SMasahiro Yamada if (e->left.sym->name)
1182bf7ab1e7SMasahiro Yamada fn(data, e->left.sym, e->left.sym->name);
1183bf7ab1e7SMasahiro Yamada else
1184bf7ab1e7SMasahiro Yamada fn(data, NULL, "<choice>");
1185bf7ab1e7SMasahiro Yamada fn(data, NULL, e->type == E_GEQ ? ">=" : ">");
1186bf7ab1e7SMasahiro Yamada fn(data, e->right.sym, e->right.sym->name);
1187bf7ab1e7SMasahiro Yamada break;
11880a9064fbSMasahiro Yamada case E_UNEQUAL:
11890a9064fbSMasahiro Yamada if (e->left.sym->name)
11900a9064fbSMasahiro Yamada fn(data, e->left.sym, e->left.sym->name);
11910a9064fbSMasahiro Yamada else
11920a9064fbSMasahiro Yamada fn(data, NULL, "<choice>");
11930a9064fbSMasahiro Yamada fn(data, NULL, "!=");
11940a9064fbSMasahiro Yamada fn(data, e->right.sym, e->right.sym->name);
11950a9064fbSMasahiro Yamada break;
11960a9064fbSMasahiro Yamada case E_OR:
11970a9064fbSMasahiro Yamada expr_print(e->left.expr, fn, data, E_OR);
11980a9064fbSMasahiro Yamada fn(data, NULL, " || ");
11990a9064fbSMasahiro Yamada expr_print(e->right.expr, fn, data, E_OR);
12000a9064fbSMasahiro Yamada break;
12010a9064fbSMasahiro Yamada case E_AND:
12020a9064fbSMasahiro Yamada expr_print(e->left.expr, fn, data, E_AND);
12030a9064fbSMasahiro Yamada fn(data, NULL, " && ");
12040a9064fbSMasahiro Yamada expr_print(e->right.expr, fn, data, E_AND);
12050a9064fbSMasahiro Yamada break;
12060a9064fbSMasahiro Yamada case E_LIST:
12070a9064fbSMasahiro Yamada fn(data, e->right.sym, e->right.sym->name);
12080a9064fbSMasahiro Yamada if (e->left.expr) {
12090a9064fbSMasahiro Yamada fn(data, NULL, " ^ ");
12100a9064fbSMasahiro Yamada expr_print(e->left.expr, fn, data, E_LIST);
12110a9064fbSMasahiro Yamada }
12120a9064fbSMasahiro Yamada break;
12130a9064fbSMasahiro Yamada case E_RANGE:
12140a9064fbSMasahiro Yamada fn(data, NULL, "[");
12150a9064fbSMasahiro Yamada fn(data, e->left.sym, e->left.sym->name);
12160a9064fbSMasahiro Yamada fn(data, NULL, " ");
12170a9064fbSMasahiro Yamada fn(data, e->right.sym, e->right.sym->name);
12180a9064fbSMasahiro Yamada fn(data, NULL, "]");
12190a9064fbSMasahiro Yamada break;
12200a9064fbSMasahiro Yamada default:
12210a9064fbSMasahiro Yamada {
12220a9064fbSMasahiro Yamada char buf[32];
12230a9064fbSMasahiro Yamada sprintf(buf, "<unknown type %d>", e->type);
12240a9064fbSMasahiro Yamada fn(data, NULL, buf);
12250a9064fbSMasahiro Yamada break;
12260a9064fbSMasahiro Yamada }
12270a9064fbSMasahiro Yamada }
12280a9064fbSMasahiro Yamada if (expr_compare_type(prevtoken, e->type) > 0)
12290a9064fbSMasahiro Yamada fn(data, NULL, ")");
12300a9064fbSMasahiro Yamada }
12310a9064fbSMasahiro Yamada
expr_print_file_helper(void * data,struct symbol * sym,const char * str)12320a9064fbSMasahiro Yamada static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
12330a9064fbSMasahiro Yamada {
12340a9064fbSMasahiro Yamada xfwrite(str, strlen(str), 1, data);
12350a9064fbSMasahiro Yamada }
12360a9064fbSMasahiro Yamada
expr_fprint(struct expr * e,FILE * out)12370a9064fbSMasahiro Yamada void expr_fprint(struct expr *e, FILE *out)
12380a9064fbSMasahiro Yamada {
12390a9064fbSMasahiro Yamada expr_print(e, expr_print_file_helper, out, E_NONE);
12400a9064fbSMasahiro Yamada }
12410a9064fbSMasahiro Yamada
expr_print_gstr_helper(void * data,struct symbol * sym,const char * str)12420a9064fbSMasahiro Yamada static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
12430a9064fbSMasahiro Yamada {
12440a9064fbSMasahiro Yamada struct gstr *gs = (struct gstr*)data;
12450a9064fbSMasahiro Yamada const char *sym_str = NULL;
12460a9064fbSMasahiro Yamada
12470a9064fbSMasahiro Yamada if (sym)
12480a9064fbSMasahiro Yamada sym_str = sym_get_string_value(sym);
12490a9064fbSMasahiro Yamada
12500a9064fbSMasahiro Yamada if (gs->max_width) {
12510a9064fbSMasahiro Yamada unsigned extra_length = strlen(str);
12520a9064fbSMasahiro Yamada const char *last_cr = strrchr(gs->s, '\n');
12530a9064fbSMasahiro Yamada unsigned last_line_length;
12540a9064fbSMasahiro Yamada
12550a9064fbSMasahiro Yamada if (sym_str)
12560a9064fbSMasahiro Yamada extra_length += 4 + strlen(sym_str);
12570a9064fbSMasahiro Yamada
12580a9064fbSMasahiro Yamada if (!last_cr)
12590a9064fbSMasahiro Yamada last_cr = gs->s;
12600a9064fbSMasahiro Yamada
12610a9064fbSMasahiro Yamada last_line_length = strlen(gs->s) - (last_cr - gs->s);
12620a9064fbSMasahiro Yamada
12630a9064fbSMasahiro Yamada if ((last_line_length + extra_length) > gs->max_width)
12640a9064fbSMasahiro Yamada str_append(gs, "\\\n");
12650a9064fbSMasahiro Yamada }
12660a9064fbSMasahiro Yamada
12670a9064fbSMasahiro Yamada str_append(gs, str);
12680a9064fbSMasahiro Yamada if (sym && sym->type != S_UNKNOWN)
12690a9064fbSMasahiro Yamada str_printf(gs, " [=%s]", sym_str);
12700a9064fbSMasahiro Yamada }
12710a9064fbSMasahiro Yamada
expr_gstr_print(struct expr * e,struct gstr * gs)12720a9064fbSMasahiro Yamada void expr_gstr_print(struct expr *e, struct gstr *gs)
12730a9064fbSMasahiro Yamada {
12740a9064fbSMasahiro Yamada expr_print(e, expr_print_gstr_helper, gs, E_NONE);
12750a9064fbSMasahiro Yamada }
1276*e91610daSEugeniu Rosca
1277*e91610daSEugeniu Rosca /*
1278*e91610daSEugeniu Rosca * Transform the top level "||" tokens into newlines and prepend each
1279*e91610daSEugeniu Rosca * line with a minus. This makes expressions much easier to read.
1280*e91610daSEugeniu Rosca * Suitable for reverse dependency expressions.
1281*e91610daSEugeniu Rosca */
expr_print_revdep(struct expr * e,void (* fn)(void *,struct symbol *,const char *),void * data,tristate pr_type,const char ** title)1282*e91610daSEugeniu Rosca static void expr_print_revdep(struct expr *e,
1283*e91610daSEugeniu Rosca void (*fn)(void *, struct symbol *, const char *),
1284*e91610daSEugeniu Rosca void *data, tristate pr_type, const char **title)
1285*e91610daSEugeniu Rosca {
1286*e91610daSEugeniu Rosca if (e->type == E_OR) {
1287*e91610daSEugeniu Rosca expr_print_revdep(e->left.expr, fn, data, pr_type, title);
1288*e91610daSEugeniu Rosca expr_print_revdep(e->right.expr, fn, data, pr_type, title);
1289*e91610daSEugeniu Rosca } else if (expr_calc_value(e) == pr_type) {
1290*e91610daSEugeniu Rosca if (*title) {
1291*e91610daSEugeniu Rosca fn(data, NULL, *title);
1292*e91610daSEugeniu Rosca *title = NULL;
1293*e91610daSEugeniu Rosca }
1294*e91610daSEugeniu Rosca
1295*e91610daSEugeniu Rosca fn(data, NULL, " - ");
1296*e91610daSEugeniu Rosca expr_print(e, fn, data, E_NONE);
1297*e91610daSEugeniu Rosca fn(data, NULL, "\n");
1298*e91610daSEugeniu Rosca }
1299*e91610daSEugeniu Rosca }
1300*e91610daSEugeniu Rosca
expr_gstr_print_revdep(struct expr * e,struct gstr * gs,tristate pr_type,const char * title)1301*e91610daSEugeniu Rosca void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
1302*e91610daSEugeniu Rosca tristate pr_type, const char *title)
1303*e91610daSEugeniu Rosca {
1304*e91610daSEugeniu Rosca expr_print_revdep(e, expr_print_gstr_helper, gs, pr_type, &title);
1305*e91610daSEugeniu Rosca }
1306