xref: /OK3568_Linux_fs/buildroot/support/kconfig/expr.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3*4882a593Smuzhiyun  * Released under the terms of the GNU GPL v2.0.
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <stdio.h>
7*4882a593Smuzhiyun #include <stdlib.h>
8*4882a593Smuzhiyun #include <string.h>
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include "lkc.h"
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #define DEBUG_EXPR	0
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun static int expr_eq(struct expr *e1, struct expr *e2);
15*4882a593Smuzhiyun static struct expr *expr_eliminate_yn(struct expr *e);
16*4882a593Smuzhiyun 
expr_alloc_symbol(struct symbol * sym)17*4882a593Smuzhiyun struct expr *expr_alloc_symbol(struct symbol *sym)
18*4882a593Smuzhiyun {
19*4882a593Smuzhiyun 	struct expr *e = xcalloc(1, sizeof(*e));
20*4882a593Smuzhiyun 	e->type = E_SYMBOL;
21*4882a593Smuzhiyun 	e->left.sym = sym;
22*4882a593Smuzhiyun 	return e;
23*4882a593Smuzhiyun }
24*4882a593Smuzhiyun 
expr_alloc_one(enum expr_type type,struct expr * ce)25*4882a593Smuzhiyun struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun 	struct expr *e = xcalloc(1, sizeof(*e));
28*4882a593Smuzhiyun 	e->type = type;
29*4882a593Smuzhiyun 	e->left.expr = ce;
30*4882a593Smuzhiyun 	return e;
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun 
expr_alloc_two(enum expr_type type,struct expr * e1,struct expr * e2)33*4882a593Smuzhiyun struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun 	struct expr *e = xcalloc(1, sizeof(*e));
36*4882a593Smuzhiyun 	e->type = type;
37*4882a593Smuzhiyun 	e->left.expr = e1;
38*4882a593Smuzhiyun 	e->right.expr = e2;
39*4882a593Smuzhiyun 	return e;
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun 
expr_alloc_comp(enum expr_type type,struct symbol * s1,struct symbol * s2)42*4882a593Smuzhiyun struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun 	struct expr *e = xcalloc(1, sizeof(*e));
45*4882a593Smuzhiyun 	e->type = type;
46*4882a593Smuzhiyun 	e->left.sym = s1;
47*4882a593Smuzhiyun 	e->right.sym = s2;
48*4882a593Smuzhiyun 	return e;
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun 
expr_alloc_and(struct expr * e1,struct expr * e2)51*4882a593Smuzhiyun struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun 	if (!e1)
54*4882a593Smuzhiyun 		return e2;
55*4882a593Smuzhiyun 	return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun 
expr_alloc_or(struct expr * e1,struct expr * e2)58*4882a593Smuzhiyun struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	if (!e1)
61*4882a593Smuzhiyun 		return e2;
62*4882a593Smuzhiyun 	return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun 
expr_copy(const struct expr * org)65*4882a593Smuzhiyun struct expr *expr_copy(const struct expr *org)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun 	struct expr *e;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	if (!org)
70*4882a593Smuzhiyun 		return NULL;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	e = xmalloc(sizeof(*org));
73*4882a593Smuzhiyun 	memcpy(e, org, sizeof(*org));
74*4882a593Smuzhiyun 	switch (org->type) {
75*4882a593Smuzhiyun 	case E_SYMBOL:
76*4882a593Smuzhiyun 		e->left = org->left;
77*4882a593Smuzhiyun 		break;
78*4882a593Smuzhiyun 	case E_NOT:
79*4882a593Smuzhiyun 		e->left.expr = expr_copy(org->left.expr);
80*4882a593Smuzhiyun 		break;
81*4882a593Smuzhiyun 	case E_EQUAL:
82*4882a593Smuzhiyun 	case E_GEQ:
83*4882a593Smuzhiyun 	case E_GTH:
84*4882a593Smuzhiyun 	case E_LEQ:
85*4882a593Smuzhiyun 	case E_LTH:
86*4882a593Smuzhiyun 	case E_UNEQUAL:
87*4882a593Smuzhiyun 		e->left.sym = org->left.sym;
88*4882a593Smuzhiyun 		e->right.sym = org->right.sym;
89*4882a593Smuzhiyun 		break;
90*4882a593Smuzhiyun 	case E_AND:
91*4882a593Smuzhiyun 	case E_OR:
92*4882a593Smuzhiyun 	case E_LIST:
93*4882a593Smuzhiyun 		e->left.expr = expr_copy(org->left.expr);
94*4882a593Smuzhiyun 		e->right.expr = expr_copy(org->right.expr);
95*4882a593Smuzhiyun 		break;
96*4882a593Smuzhiyun 	default:
97*4882a593Smuzhiyun 		fprintf(stderr, "can't copy type %d\n", e->type);
98*4882a593Smuzhiyun 		free(e);
99*4882a593Smuzhiyun 		e = NULL;
100*4882a593Smuzhiyun 		break;
101*4882a593Smuzhiyun 	}
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	return e;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
expr_free(struct expr * e)106*4882a593Smuzhiyun void expr_free(struct expr *e)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun 	if (!e)
109*4882a593Smuzhiyun 		return;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	switch (e->type) {
112*4882a593Smuzhiyun 	case E_SYMBOL:
113*4882a593Smuzhiyun 		break;
114*4882a593Smuzhiyun 	case E_NOT:
115*4882a593Smuzhiyun 		expr_free(e->left.expr);
116*4882a593Smuzhiyun 		break;
117*4882a593Smuzhiyun 	case E_EQUAL:
118*4882a593Smuzhiyun 	case E_GEQ:
119*4882a593Smuzhiyun 	case E_GTH:
120*4882a593Smuzhiyun 	case E_LEQ:
121*4882a593Smuzhiyun 	case E_LTH:
122*4882a593Smuzhiyun 	case E_UNEQUAL:
123*4882a593Smuzhiyun 		break;
124*4882a593Smuzhiyun 	case E_OR:
125*4882a593Smuzhiyun 	case E_AND:
126*4882a593Smuzhiyun 		expr_free(e->left.expr);
127*4882a593Smuzhiyun 		expr_free(e->right.expr);
128*4882a593Smuzhiyun 		break;
129*4882a593Smuzhiyun 	default:
130*4882a593Smuzhiyun 		fprintf(stderr, "how to free type %d?\n", e->type);
131*4882a593Smuzhiyun 		break;
132*4882a593Smuzhiyun 	}
133*4882a593Smuzhiyun 	free(e);
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun static int trans_count;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun #define e1 (*ep1)
139*4882a593Smuzhiyun #define e2 (*ep2)
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun /*
142*4882a593Smuzhiyun  * expr_eliminate_eq() helper.
143*4882a593Smuzhiyun  *
144*4882a593Smuzhiyun  * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
145*4882a593Smuzhiyun  * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
146*4882a593Smuzhiyun  * against all other leaves. Two equal leaves are both replaced with either 'y'
147*4882a593Smuzhiyun  * or 'n' as appropriate for 'type', to be eliminated later.
148*4882a593Smuzhiyun  */
__expr_eliminate_eq(enum expr_type type,struct expr ** ep1,struct expr ** ep2)149*4882a593Smuzhiyun static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun 	/* Recurse down to leaves */
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	if (e1->type == type) {
154*4882a593Smuzhiyun 		__expr_eliminate_eq(type, &e1->left.expr, &e2);
155*4882a593Smuzhiyun 		__expr_eliminate_eq(type, &e1->right.expr, &e2);
156*4882a593Smuzhiyun 		return;
157*4882a593Smuzhiyun 	}
158*4882a593Smuzhiyun 	if (e2->type == type) {
159*4882a593Smuzhiyun 		__expr_eliminate_eq(type, &e1, &e2->left.expr);
160*4882a593Smuzhiyun 		__expr_eliminate_eq(type, &e1, &e2->right.expr);
161*4882a593Smuzhiyun 		return;
162*4882a593Smuzhiyun 	}
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	/* e1 and e2 are leaves. Compare them. */
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
167*4882a593Smuzhiyun 	    e1->left.sym == e2->left.sym &&
168*4882a593Smuzhiyun 	    (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
169*4882a593Smuzhiyun 		return;
170*4882a593Smuzhiyun 	if (!expr_eq(e1, e2))
171*4882a593Smuzhiyun 		return;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	/* e1 and e2 are equal leaves. Prepare them for elimination. */
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	trans_count++;
176*4882a593Smuzhiyun 	expr_free(e1); expr_free(e2);
177*4882a593Smuzhiyun 	switch (type) {
178*4882a593Smuzhiyun 	case E_OR:
179*4882a593Smuzhiyun 		e1 = expr_alloc_symbol(&symbol_no);
180*4882a593Smuzhiyun 		e2 = expr_alloc_symbol(&symbol_no);
181*4882a593Smuzhiyun 		break;
182*4882a593Smuzhiyun 	case E_AND:
183*4882a593Smuzhiyun 		e1 = expr_alloc_symbol(&symbol_yes);
184*4882a593Smuzhiyun 		e2 = expr_alloc_symbol(&symbol_yes);
185*4882a593Smuzhiyun 		break;
186*4882a593Smuzhiyun 	default:
187*4882a593Smuzhiyun 		;
188*4882a593Smuzhiyun 	}
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun /*
192*4882a593Smuzhiyun  * Rewrites the expressions 'ep1' and 'ep2' to remove operands common to both.
193*4882a593Smuzhiyun  * Example reductions:
194*4882a593Smuzhiyun  *
195*4882a593Smuzhiyun  *	ep1: A && B           ->  ep1: y
196*4882a593Smuzhiyun  *	ep2: A && B && C      ->  ep2: C
197*4882a593Smuzhiyun  *
198*4882a593Smuzhiyun  *	ep1: A || B           ->  ep1: n
199*4882a593Smuzhiyun  *	ep2: A || B || C      ->  ep2: C
200*4882a593Smuzhiyun  *
201*4882a593Smuzhiyun  *	ep1: A && (B && FOO)  ->  ep1: FOO
202*4882a593Smuzhiyun  *	ep2: (BAR && B) && A  ->  ep2: BAR
203*4882a593Smuzhiyun  *
204*4882a593Smuzhiyun  *	ep1: A && (B || C)    ->  ep1: y
205*4882a593Smuzhiyun  *	ep2: (C || B) && A    ->  ep2: y
206*4882a593Smuzhiyun  *
207*4882a593Smuzhiyun  * Comparisons are done between all operands at the same "level" of && or ||.
208*4882a593Smuzhiyun  * For example, in the expression 'e1 && (e2 || e3) && (e4 || e5)', the
209*4882a593Smuzhiyun  * following operands will be compared:
210*4882a593Smuzhiyun  *
211*4882a593Smuzhiyun  *	- 'e1', 'e2 || e3', and 'e4 || e5', against each other
212*4882a593Smuzhiyun  *	- e2 against e3
213*4882a593Smuzhiyun  *	- e4 against e5
214*4882a593Smuzhiyun  *
215*4882a593Smuzhiyun  * Parentheses are irrelevant within a single level. 'e1 && (e2 && e3)' and
216*4882a593Smuzhiyun  * '(e1 && e2) && e3' are both a single level.
217*4882a593Smuzhiyun  *
218*4882a593Smuzhiyun  * See __expr_eliminate_eq() as well.
219*4882a593Smuzhiyun  */
expr_eliminate_eq(struct expr ** ep1,struct expr ** ep2)220*4882a593Smuzhiyun void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun 	if (!e1 || !e2)
223*4882a593Smuzhiyun 		return;
224*4882a593Smuzhiyun 	switch (e1->type) {
225*4882a593Smuzhiyun 	case E_OR:
226*4882a593Smuzhiyun 	case E_AND:
227*4882a593Smuzhiyun 		__expr_eliminate_eq(e1->type, ep1, ep2);
228*4882a593Smuzhiyun 	default:
229*4882a593Smuzhiyun 		;
230*4882a593Smuzhiyun 	}
231*4882a593Smuzhiyun 	if (e1->type != e2->type) switch (e2->type) {
232*4882a593Smuzhiyun 	case E_OR:
233*4882a593Smuzhiyun 	case E_AND:
234*4882a593Smuzhiyun 		__expr_eliminate_eq(e2->type, ep1, ep2);
235*4882a593Smuzhiyun 	default:
236*4882a593Smuzhiyun 		;
237*4882a593Smuzhiyun 	}
238*4882a593Smuzhiyun 	e1 = expr_eliminate_yn(e1);
239*4882a593Smuzhiyun 	e2 = expr_eliminate_yn(e2);
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun #undef e1
243*4882a593Smuzhiyun #undef e2
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun /*
246*4882a593Smuzhiyun  * Returns true if 'e1' and 'e2' are equal, after minor simplification. Two
247*4882a593Smuzhiyun  * &&/|| expressions are considered equal if every operand in one expression
248*4882a593Smuzhiyun  * equals some operand in the other (operands do not need to appear in the same
249*4882a593Smuzhiyun  * order), recursively.
250*4882a593Smuzhiyun  */
expr_eq(struct expr * e1,struct expr * e2)251*4882a593Smuzhiyun static int expr_eq(struct expr *e1, struct expr *e2)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	int res, old_count;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	if (e1->type != e2->type)
256*4882a593Smuzhiyun 		return 0;
257*4882a593Smuzhiyun 	switch (e1->type) {
258*4882a593Smuzhiyun 	case E_EQUAL:
259*4882a593Smuzhiyun 	case E_GEQ:
260*4882a593Smuzhiyun 	case E_GTH:
261*4882a593Smuzhiyun 	case E_LEQ:
262*4882a593Smuzhiyun 	case E_LTH:
263*4882a593Smuzhiyun 	case E_UNEQUAL:
264*4882a593Smuzhiyun 		return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
265*4882a593Smuzhiyun 	case E_SYMBOL:
266*4882a593Smuzhiyun 		return e1->left.sym == e2->left.sym;
267*4882a593Smuzhiyun 	case E_NOT:
268*4882a593Smuzhiyun 		return expr_eq(e1->left.expr, e2->left.expr);
269*4882a593Smuzhiyun 	case E_AND:
270*4882a593Smuzhiyun 	case E_OR:
271*4882a593Smuzhiyun 		e1 = expr_copy(e1);
272*4882a593Smuzhiyun 		e2 = expr_copy(e2);
273*4882a593Smuzhiyun 		old_count = trans_count;
274*4882a593Smuzhiyun 		expr_eliminate_eq(&e1, &e2);
275*4882a593Smuzhiyun 		res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
276*4882a593Smuzhiyun 		       e1->left.sym == e2->left.sym);
277*4882a593Smuzhiyun 		expr_free(e1);
278*4882a593Smuzhiyun 		expr_free(e2);
279*4882a593Smuzhiyun 		trans_count = old_count;
280*4882a593Smuzhiyun 		return res;
281*4882a593Smuzhiyun 	case E_LIST:
282*4882a593Smuzhiyun 	case E_RANGE:
283*4882a593Smuzhiyun 	case E_NONE:
284*4882a593Smuzhiyun 		/* panic */;
285*4882a593Smuzhiyun 	}
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	if (DEBUG_EXPR) {
288*4882a593Smuzhiyun 		expr_fprint(e1, stdout);
289*4882a593Smuzhiyun 		printf(" = ");
290*4882a593Smuzhiyun 		expr_fprint(e2, stdout);
291*4882a593Smuzhiyun 		printf(" ?\n");
292*4882a593Smuzhiyun 	}
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	return 0;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun /*
298*4882a593Smuzhiyun  * Recursively performs the following simplifications in-place (as well as the
299*4882a593Smuzhiyun  * corresponding simplifications with swapped operands):
300*4882a593Smuzhiyun  *
301*4882a593Smuzhiyun  *	expr && n  ->  n
302*4882a593Smuzhiyun  *	expr && y  ->  expr
303*4882a593Smuzhiyun  *	expr || n  ->  expr
304*4882a593Smuzhiyun  *	expr || y  ->  y
305*4882a593Smuzhiyun  *
306*4882a593Smuzhiyun  * Returns the optimized expression.
307*4882a593Smuzhiyun  */
expr_eliminate_yn(struct expr * e)308*4882a593Smuzhiyun static struct expr *expr_eliminate_yn(struct expr *e)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun 	struct expr *tmp;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	if (e) switch (e->type) {
313*4882a593Smuzhiyun 	case E_AND:
314*4882a593Smuzhiyun 		e->left.expr = expr_eliminate_yn(e->left.expr);
315*4882a593Smuzhiyun 		e->right.expr = expr_eliminate_yn(e->right.expr);
316*4882a593Smuzhiyun 		if (e->left.expr->type == E_SYMBOL) {
317*4882a593Smuzhiyun 			if (e->left.expr->left.sym == &symbol_no) {
318*4882a593Smuzhiyun 				expr_free(e->left.expr);
319*4882a593Smuzhiyun 				expr_free(e->right.expr);
320*4882a593Smuzhiyun 				e->type = E_SYMBOL;
321*4882a593Smuzhiyun 				e->left.sym = &symbol_no;
322*4882a593Smuzhiyun 				e->right.expr = NULL;
323*4882a593Smuzhiyun 				return e;
324*4882a593Smuzhiyun 			} else if (e->left.expr->left.sym == &symbol_yes) {
325*4882a593Smuzhiyun 				free(e->left.expr);
326*4882a593Smuzhiyun 				tmp = e->right.expr;
327*4882a593Smuzhiyun 				*e = *(e->right.expr);
328*4882a593Smuzhiyun 				free(tmp);
329*4882a593Smuzhiyun 				return e;
330*4882a593Smuzhiyun 			}
331*4882a593Smuzhiyun 		}
332*4882a593Smuzhiyun 		if (e->right.expr->type == E_SYMBOL) {
333*4882a593Smuzhiyun 			if (e->right.expr->left.sym == &symbol_no) {
334*4882a593Smuzhiyun 				expr_free(e->left.expr);
335*4882a593Smuzhiyun 				expr_free(e->right.expr);
336*4882a593Smuzhiyun 				e->type = E_SYMBOL;
337*4882a593Smuzhiyun 				e->left.sym = &symbol_no;
338*4882a593Smuzhiyun 				e->right.expr = NULL;
339*4882a593Smuzhiyun 				return e;
340*4882a593Smuzhiyun 			} else if (e->right.expr->left.sym == &symbol_yes) {
341*4882a593Smuzhiyun 				free(e->right.expr);
342*4882a593Smuzhiyun 				tmp = e->left.expr;
343*4882a593Smuzhiyun 				*e = *(e->left.expr);
344*4882a593Smuzhiyun 				free(tmp);
345*4882a593Smuzhiyun 				return e;
346*4882a593Smuzhiyun 			}
347*4882a593Smuzhiyun 		}
348*4882a593Smuzhiyun 		break;
349*4882a593Smuzhiyun 	case E_OR:
350*4882a593Smuzhiyun 		e->left.expr = expr_eliminate_yn(e->left.expr);
351*4882a593Smuzhiyun 		e->right.expr = expr_eliminate_yn(e->right.expr);
352*4882a593Smuzhiyun 		if (e->left.expr->type == E_SYMBOL) {
353*4882a593Smuzhiyun 			if (e->left.expr->left.sym == &symbol_no) {
354*4882a593Smuzhiyun 				free(e->left.expr);
355*4882a593Smuzhiyun 				tmp = e->right.expr;
356*4882a593Smuzhiyun 				*e = *(e->right.expr);
357*4882a593Smuzhiyun 				free(tmp);
358*4882a593Smuzhiyun 				return e;
359*4882a593Smuzhiyun 			} else if (e->left.expr->left.sym == &symbol_yes) {
360*4882a593Smuzhiyun 				expr_free(e->left.expr);
361*4882a593Smuzhiyun 				expr_free(e->right.expr);
362*4882a593Smuzhiyun 				e->type = E_SYMBOL;
363*4882a593Smuzhiyun 				e->left.sym = &symbol_yes;
364*4882a593Smuzhiyun 				e->right.expr = NULL;
365*4882a593Smuzhiyun 				return e;
366*4882a593Smuzhiyun 			}
367*4882a593Smuzhiyun 		}
368*4882a593Smuzhiyun 		if (e->right.expr->type == E_SYMBOL) {
369*4882a593Smuzhiyun 			if (e->right.expr->left.sym == &symbol_no) {
370*4882a593Smuzhiyun 				free(e->right.expr);
371*4882a593Smuzhiyun 				tmp = e->left.expr;
372*4882a593Smuzhiyun 				*e = *(e->left.expr);
373*4882a593Smuzhiyun 				free(tmp);
374*4882a593Smuzhiyun 				return e;
375*4882a593Smuzhiyun 			} else if (e->right.expr->left.sym == &symbol_yes) {
376*4882a593Smuzhiyun 				expr_free(e->left.expr);
377*4882a593Smuzhiyun 				expr_free(e->right.expr);
378*4882a593Smuzhiyun 				e->type = E_SYMBOL;
379*4882a593Smuzhiyun 				e->left.sym = &symbol_yes;
380*4882a593Smuzhiyun 				e->right.expr = NULL;
381*4882a593Smuzhiyun 				return e;
382*4882a593Smuzhiyun 			}
383*4882a593Smuzhiyun 		}
384*4882a593Smuzhiyun 		break;
385*4882a593Smuzhiyun 	default:
386*4882a593Smuzhiyun 		;
387*4882a593Smuzhiyun 	}
388*4882a593Smuzhiyun 	return e;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun /*
392*4882a593Smuzhiyun  * bool FOO!=n => FOO
393*4882a593Smuzhiyun  */
expr_trans_bool(struct expr * e)394*4882a593Smuzhiyun struct expr *expr_trans_bool(struct expr *e)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun 	if (!e)
397*4882a593Smuzhiyun 		return NULL;
398*4882a593Smuzhiyun 	switch (e->type) {
399*4882a593Smuzhiyun 	case E_AND:
400*4882a593Smuzhiyun 	case E_OR:
401*4882a593Smuzhiyun 	case E_NOT:
402*4882a593Smuzhiyun 		e->left.expr = expr_trans_bool(e->left.expr);
403*4882a593Smuzhiyun 		e->right.expr = expr_trans_bool(e->right.expr);
404*4882a593Smuzhiyun 		break;
405*4882a593Smuzhiyun 	case E_UNEQUAL:
406*4882a593Smuzhiyun 		// FOO!=n -> FOO
407*4882a593Smuzhiyun 		if (e->left.sym->type == S_TRISTATE) {
408*4882a593Smuzhiyun 			if (e->right.sym == &symbol_no) {
409*4882a593Smuzhiyun 				e->type = E_SYMBOL;
410*4882a593Smuzhiyun 				e->right.sym = NULL;
411*4882a593Smuzhiyun 			}
412*4882a593Smuzhiyun 		}
413*4882a593Smuzhiyun 		break;
414*4882a593Smuzhiyun 	default:
415*4882a593Smuzhiyun 		;
416*4882a593Smuzhiyun 	}
417*4882a593Smuzhiyun 	return e;
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun /*
421*4882a593Smuzhiyun  * e1 || e2 -> ?
422*4882a593Smuzhiyun  */
expr_join_or(struct expr * e1,struct expr * e2)423*4882a593Smuzhiyun static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
424*4882a593Smuzhiyun {
425*4882a593Smuzhiyun 	struct expr *tmp;
426*4882a593Smuzhiyun 	struct symbol *sym1, *sym2;
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	if (expr_eq(e1, e2))
429*4882a593Smuzhiyun 		return expr_copy(e1);
430*4882a593Smuzhiyun 	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
431*4882a593Smuzhiyun 		return NULL;
432*4882a593Smuzhiyun 	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
433*4882a593Smuzhiyun 		return NULL;
434*4882a593Smuzhiyun 	if (e1->type == E_NOT) {
435*4882a593Smuzhiyun 		tmp = e1->left.expr;
436*4882a593Smuzhiyun 		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
437*4882a593Smuzhiyun 			return NULL;
438*4882a593Smuzhiyun 		sym1 = tmp->left.sym;
439*4882a593Smuzhiyun 	} else
440*4882a593Smuzhiyun 		sym1 = e1->left.sym;
441*4882a593Smuzhiyun 	if (e2->type == E_NOT) {
442*4882a593Smuzhiyun 		if (e2->left.expr->type != E_SYMBOL)
443*4882a593Smuzhiyun 			return NULL;
444*4882a593Smuzhiyun 		sym2 = e2->left.expr->left.sym;
445*4882a593Smuzhiyun 	} else
446*4882a593Smuzhiyun 		sym2 = e2->left.sym;
447*4882a593Smuzhiyun 	if (sym1 != sym2)
448*4882a593Smuzhiyun 		return NULL;
449*4882a593Smuzhiyun 	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
450*4882a593Smuzhiyun 		return NULL;
451*4882a593Smuzhiyun 	if (sym1->type == S_TRISTATE) {
452*4882a593Smuzhiyun 		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
453*4882a593Smuzhiyun 		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
454*4882a593Smuzhiyun 		     (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
455*4882a593Smuzhiyun 			// (a='y') || (a='m') -> (a!='n')
456*4882a593Smuzhiyun 			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
457*4882a593Smuzhiyun 		}
458*4882a593Smuzhiyun 		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
459*4882a593Smuzhiyun 		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
460*4882a593Smuzhiyun 		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
461*4882a593Smuzhiyun 			// (a='y') || (a='n') -> (a!='m')
462*4882a593Smuzhiyun 			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
463*4882a593Smuzhiyun 		}
464*4882a593Smuzhiyun 		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
465*4882a593Smuzhiyun 		    ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
466*4882a593Smuzhiyun 		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
467*4882a593Smuzhiyun 			// (a='m') || (a='n') -> (a!='y')
468*4882a593Smuzhiyun 			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
469*4882a593Smuzhiyun 		}
470*4882a593Smuzhiyun 	}
471*4882a593Smuzhiyun 	if (sym1->type == S_BOOLEAN && sym1 == sym2) {
472*4882a593Smuzhiyun 		if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
473*4882a593Smuzhiyun 		    (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
474*4882a593Smuzhiyun 			return expr_alloc_symbol(&symbol_yes);
475*4882a593Smuzhiyun 	}
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	if (DEBUG_EXPR) {
478*4882a593Smuzhiyun 		printf("optimize (");
479*4882a593Smuzhiyun 		expr_fprint(e1, stdout);
480*4882a593Smuzhiyun 		printf(") || (");
481*4882a593Smuzhiyun 		expr_fprint(e2, stdout);
482*4882a593Smuzhiyun 		printf(")?\n");
483*4882a593Smuzhiyun 	}
484*4882a593Smuzhiyun 	return NULL;
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun 
expr_join_and(struct expr * e1,struct expr * e2)487*4882a593Smuzhiyun static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun 	struct expr *tmp;
490*4882a593Smuzhiyun 	struct symbol *sym1, *sym2;
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	if (expr_eq(e1, e2))
493*4882a593Smuzhiyun 		return expr_copy(e1);
494*4882a593Smuzhiyun 	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
495*4882a593Smuzhiyun 		return NULL;
496*4882a593Smuzhiyun 	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
497*4882a593Smuzhiyun 		return NULL;
498*4882a593Smuzhiyun 	if (e1->type == E_NOT) {
499*4882a593Smuzhiyun 		tmp = e1->left.expr;
500*4882a593Smuzhiyun 		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
501*4882a593Smuzhiyun 			return NULL;
502*4882a593Smuzhiyun 		sym1 = tmp->left.sym;
503*4882a593Smuzhiyun 	} else
504*4882a593Smuzhiyun 		sym1 = e1->left.sym;
505*4882a593Smuzhiyun 	if (e2->type == E_NOT) {
506*4882a593Smuzhiyun 		if (e2->left.expr->type != E_SYMBOL)
507*4882a593Smuzhiyun 			return NULL;
508*4882a593Smuzhiyun 		sym2 = e2->left.expr->left.sym;
509*4882a593Smuzhiyun 	} else
510*4882a593Smuzhiyun 		sym2 = e2->left.sym;
511*4882a593Smuzhiyun 	if (sym1 != sym2)
512*4882a593Smuzhiyun 		return NULL;
513*4882a593Smuzhiyun 	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
514*4882a593Smuzhiyun 		return NULL;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
517*4882a593Smuzhiyun 	    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
518*4882a593Smuzhiyun 		// (a) && (a='y') -> (a='y')
519*4882a593Smuzhiyun 		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
522*4882a593Smuzhiyun 	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
523*4882a593Smuzhiyun 		// (a) && (a!='n') -> (a)
524*4882a593Smuzhiyun 		return expr_alloc_symbol(sym1);
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
527*4882a593Smuzhiyun 	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
528*4882a593Smuzhiyun 		// (a) && (a!='m') -> (a='y')
529*4882a593Smuzhiyun 		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 	if (sym1->type == S_TRISTATE) {
532*4882a593Smuzhiyun 		if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
533*4882a593Smuzhiyun 			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
534*4882a593Smuzhiyun 			sym2 = e1->right.sym;
535*4882a593Smuzhiyun 			if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
536*4882a593Smuzhiyun 				return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
537*4882a593Smuzhiyun 							     : expr_alloc_symbol(&symbol_no);
538*4882a593Smuzhiyun 		}
539*4882a593Smuzhiyun 		if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
540*4882a593Smuzhiyun 			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
541*4882a593Smuzhiyun 			sym2 = e2->right.sym;
542*4882a593Smuzhiyun 			if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
543*4882a593Smuzhiyun 				return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
544*4882a593Smuzhiyun 							     : expr_alloc_symbol(&symbol_no);
545*4882a593Smuzhiyun 		}
546*4882a593Smuzhiyun 		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
547*4882a593Smuzhiyun 			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
548*4882a593Smuzhiyun 			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
549*4882a593Smuzhiyun 			// (a!='y') && (a!='n') -> (a='m')
550*4882a593Smuzhiyun 			return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
553*4882a593Smuzhiyun 			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
554*4882a593Smuzhiyun 			    (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
555*4882a593Smuzhiyun 			// (a!='y') && (a!='m') -> (a='n')
556*4882a593Smuzhiyun 			return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
559*4882a593Smuzhiyun 			   ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
560*4882a593Smuzhiyun 			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
561*4882a593Smuzhiyun 			// (a!='m') && (a!='n') -> (a='m')
562*4882a593Smuzhiyun 			return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 		if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
565*4882a593Smuzhiyun 		    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
566*4882a593Smuzhiyun 		    (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
567*4882a593Smuzhiyun 		    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
568*4882a593Smuzhiyun 			return NULL;
569*4882a593Smuzhiyun 	}
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	if (DEBUG_EXPR) {
572*4882a593Smuzhiyun 		printf("optimize (");
573*4882a593Smuzhiyun 		expr_fprint(e1, stdout);
574*4882a593Smuzhiyun 		printf(") && (");
575*4882a593Smuzhiyun 		expr_fprint(e2, stdout);
576*4882a593Smuzhiyun 		printf(")?\n");
577*4882a593Smuzhiyun 	}
578*4882a593Smuzhiyun 	return NULL;
579*4882a593Smuzhiyun }
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun /*
582*4882a593Smuzhiyun  * expr_eliminate_dups() helper.
583*4882a593Smuzhiyun  *
584*4882a593Smuzhiyun  * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
585*4882a593Smuzhiyun  * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
586*4882a593Smuzhiyun  * against all other leaves to look for simplifications.
587*4882a593Smuzhiyun  */
expr_eliminate_dups1(enum expr_type type,struct expr ** ep1,struct expr ** ep2)588*4882a593Smuzhiyun static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
589*4882a593Smuzhiyun {
590*4882a593Smuzhiyun #define e1 (*ep1)
591*4882a593Smuzhiyun #define e2 (*ep2)
592*4882a593Smuzhiyun 	struct expr *tmp;
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	/* Recurse down to leaves */
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 	if (e1->type == type) {
597*4882a593Smuzhiyun 		expr_eliminate_dups1(type, &e1->left.expr, &e2);
598*4882a593Smuzhiyun 		expr_eliminate_dups1(type, &e1->right.expr, &e2);
599*4882a593Smuzhiyun 		return;
600*4882a593Smuzhiyun 	}
601*4882a593Smuzhiyun 	if (e2->type == type) {
602*4882a593Smuzhiyun 		expr_eliminate_dups1(type, &e1, &e2->left.expr);
603*4882a593Smuzhiyun 		expr_eliminate_dups1(type, &e1, &e2->right.expr);
604*4882a593Smuzhiyun 		return;
605*4882a593Smuzhiyun 	}
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	/* e1 and e2 are leaves. Compare and process them. */
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	if (e1 == e2)
610*4882a593Smuzhiyun 		return;
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 	switch (e1->type) {
613*4882a593Smuzhiyun 	case E_OR: case E_AND:
614*4882a593Smuzhiyun 		expr_eliminate_dups1(e1->type, &e1, &e1);
615*4882a593Smuzhiyun 	default:
616*4882a593Smuzhiyun 		;
617*4882a593Smuzhiyun 	}
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 	switch (type) {
620*4882a593Smuzhiyun 	case E_OR:
621*4882a593Smuzhiyun 		tmp = expr_join_or(e1, e2);
622*4882a593Smuzhiyun 		if (tmp) {
623*4882a593Smuzhiyun 			expr_free(e1); expr_free(e2);
624*4882a593Smuzhiyun 			e1 = expr_alloc_symbol(&symbol_no);
625*4882a593Smuzhiyun 			e2 = tmp;
626*4882a593Smuzhiyun 			trans_count++;
627*4882a593Smuzhiyun 		}
628*4882a593Smuzhiyun 		break;
629*4882a593Smuzhiyun 	case E_AND:
630*4882a593Smuzhiyun 		tmp = expr_join_and(e1, e2);
631*4882a593Smuzhiyun 		if (tmp) {
632*4882a593Smuzhiyun 			expr_free(e1); expr_free(e2);
633*4882a593Smuzhiyun 			e1 = expr_alloc_symbol(&symbol_yes);
634*4882a593Smuzhiyun 			e2 = tmp;
635*4882a593Smuzhiyun 			trans_count++;
636*4882a593Smuzhiyun 		}
637*4882a593Smuzhiyun 		break;
638*4882a593Smuzhiyun 	default:
639*4882a593Smuzhiyun 		;
640*4882a593Smuzhiyun 	}
641*4882a593Smuzhiyun #undef e1
642*4882a593Smuzhiyun #undef e2
643*4882a593Smuzhiyun }
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun /*
646*4882a593Smuzhiyun  * Rewrites 'e' in-place to remove ("join") duplicate and other redundant
647*4882a593Smuzhiyun  * operands.
648*4882a593Smuzhiyun  *
649*4882a593Smuzhiyun  * Example simplifications:
650*4882a593Smuzhiyun  *
651*4882a593Smuzhiyun  *	A || B || A    ->  A || B
652*4882a593Smuzhiyun  *	A && B && A=y  ->  A=y && B
653*4882a593Smuzhiyun  *
654*4882a593Smuzhiyun  * Returns the deduplicated expression.
655*4882a593Smuzhiyun  */
expr_eliminate_dups(struct expr * e)656*4882a593Smuzhiyun struct expr *expr_eliminate_dups(struct expr *e)
657*4882a593Smuzhiyun {
658*4882a593Smuzhiyun 	int oldcount;
659*4882a593Smuzhiyun 	if (!e)
660*4882a593Smuzhiyun 		return e;
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	oldcount = trans_count;
663*4882a593Smuzhiyun 	while (1) {
664*4882a593Smuzhiyun 		trans_count = 0;
665*4882a593Smuzhiyun 		switch (e->type) {
666*4882a593Smuzhiyun 		case E_OR: case E_AND:
667*4882a593Smuzhiyun 			expr_eliminate_dups1(e->type, &e, &e);
668*4882a593Smuzhiyun 		default:
669*4882a593Smuzhiyun 			;
670*4882a593Smuzhiyun 		}
671*4882a593Smuzhiyun 		if (!trans_count)
672*4882a593Smuzhiyun 			/* No simplifications done in this pass. We're done */
673*4882a593Smuzhiyun 			break;
674*4882a593Smuzhiyun 		e = expr_eliminate_yn(e);
675*4882a593Smuzhiyun 	}
676*4882a593Smuzhiyun 	trans_count = oldcount;
677*4882a593Smuzhiyun 	return e;
678*4882a593Smuzhiyun }
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun /*
681*4882a593Smuzhiyun  * Performs various simplifications involving logical operators and
682*4882a593Smuzhiyun  * comparisons.
683*4882a593Smuzhiyun  *
684*4882a593Smuzhiyun  * Allocates and returns a new expression.
685*4882a593Smuzhiyun  */
expr_transform(struct expr * e)686*4882a593Smuzhiyun struct expr *expr_transform(struct expr *e)
687*4882a593Smuzhiyun {
688*4882a593Smuzhiyun 	struct expr *tmp;
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun 	if (!e)
691*4882a593Smuzhiyun 		return NULL;
692*4882a593Smuzhiyun 	switch (e->type) {
693*4882a593Smuzhiyun 	case E_EQUAL:
694*4882a593Smuzhiyun 	case E_GEQ:
695*4882a593Smuzhiyun 	case E_GTH:
696*4882a593Smuzhiyun 	case E_LEQ:
697*4882a593Smuzhiyun 	case E_LTH:
698*4882a593Smuzhiyun 	case E_UNEQUAL:
699*4882a593Smuzhiyun 	case E_SYMBOL:
700*4882a593Smuzhiyun 	case E_LIST:
701*4882a593Smuzhiyun 		break;
702*4882a593Smuzhiyun 	default:
703*4882a593Smuzhiyun 		e->left.expr = expr_transform(e->left.expr);
704*4882a593Smuzhiyun 		e->right.expr = expr_transform(e->right.expr);
705*4882a593Smuzhiyun 	}
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun 	switch (e->type) {
708*4882a593Smuzhiyun 	case E_EQUAL:
709*4882a593Smuzhiyun 		if (e->left.sym->type != S_BOOLEAN)
710*4882a593Smuzhiyun 			break;
711*4882a593Smuzhiyun 		if (e->right.sym == &symbol_no) {
712*4882a593Smuzhiyun 			e->type = E_NOT;
713*4882a593Smuzhiyun 			e->left.expr = expr_alloc_symbol(e->left.sym);
714*4882a593Smuzhiyun 			e->right.sym = NULL;
715*4882a593Smuzhiyun 			break;
716*4882a593Smuzhiyun 		}
717*4882a593Smuzhiyun 		if (e->right.sym == &symbol_mod) {
718*4882a593Smuzhiyun 			printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
719*4882a593Smuzhiyun 			e->type = E_SYMBOL;
720*4882a593Smuzhiyun 			e->left.sym = &symbol_no;
721*4882a593Smuzhiyun 			e->right.sym = NULL;
722*4882a593Smuzhiyun 			break;
723*4882a593Smuzhiyun 		}
724*4882a593Smuzhiyun 		if (e->right.sym == &symbol_yes) {
725*4882a593Smuzhiyun 			e->type = E_SYMBOL;
726*4882a593Smuzhiyun 			e->right.sym = NULL;
727*4882a593Smuzhiyun 			break;
728*4882a593Smuzhiyun 		}
729*4882a593Smuzhiyun 		break;
730*4882a593Smuzhiyun 	case E_UNEQUAL:
731*4882a593Smuzhiyun 		if (e->left.sym->type != S_BOOLEAN)
732*4882a593Smuzhiyun 			break;
733*4882a593Smuzhiyun 		if (e->right.sym == &symbol_no) {
734*4882a593Smuzhiyun 			e->type = E_SYMBOL;
735*4882a593Smuzhiyun 			e->right.sym = NULL;
736*4882a593Smuzhiyun 			break;
737*4882a593Smuzhiyun 		}
738*4882a593Smuzhiyun 		if (e->right.sym == &symbol_mod) {
739*4882a593Smuzhiyun 			printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
740*4882a593Smuzhiyun 			e->type = E_SYMBOL;
741*4882a593Smuzhiyun 			e->left.sym = &symbol_yes;
742*4882a593Smuzhiyun 			e->right.sym = NULL;
743*4882a593Smuzhiyun 			break;
744*4882a593Smuzhiyun 		}
745*4882a593Smuzhiyun 		if (e->right.sym == &symbol_yes) {
746*4882a593Smuzhiyun 			e->type = E_NOT;
747*4882a593Smuzhiyun 			e->left.expr = expr_alloc_symbol(e->left.sym);
748*4882a593Smuzhiyun 			e->right.sym = NULL;
749*4882a593Smuzhiyun 			break;
750*4882a593Smuzhiyun 		}
751*4882a593Smuzhiyun 		break;
752*4882a593Smuzhiyun 	case E_NOT:
753*4882a593Smuzhiyun 		switch (e->left.expr->type) {
754*4882a593Smuzhiyun 		case E_NOT:
755*4882a593Smuzhiyun 			// !!a -> a
756*4882a593Smuzhiyun 			tmp = e->left.expr->left.expr;
757*4882a593Smuzhiyun 			free(e->left.expr);
758*4882a593Smuzhiyun 			free(e);
759*4882a593Smuzhiyun 			e = tmp;
760*4882a593Smuzhiyun 			e = expr_transform(e);
761*4882a593Smuzhiyun 			break;
762*4882a593Smuzhiyun 		case E_EQUAL:
763*4882a593Smuzhiyun 		case E_UNEQUAL:
764*4882a593Smuzhiyun 			// !a='x' -> a!='x'
765*4882a593Smuzhiyun 			tmp = e->left.expr;
766*4882a593Smuzhiyun 			free(e);
767*4882a593Smuzhiyun 			e = tmp;
768*4882a593Smuzhiyun 			e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
769*4882a593Smuzhiyun 			break;
770*4882a593Smuzhiyun 		case E_LEQ:
771*4882a593Smuzhiyun 		case E_GEQ:
772*4882a593Smuzhiyun 			// !a<='x' -> a>'x'
773*4882a593Smuzhiyun 			tmp = e->left.expr;
774*4882a593Smuzhiyun 			free(e);
775*4882a593Smuzhiyun 			e = tmp;
776*4882a593Smuzhiyun 			e->type = e->type == E_LEQ ? E_GTH : E_LTH;
777*4882a593Smuzhiyun 			break;
778*4882a593Smuzhiyun 		case E_LTH:
779*4882a593Smuzhiyun 		case E_GTH:
780*4882a593Smuzhiyun 			// !a<'x' -> a>='x'
781*4882a593Smuzhiyun 			tmp = e->left.expr;
782*4882a593Smuzhiyun 			free(e);
783*4882a593Smuzhiyun 			e = tmp;
784*4882a593Smuzhiyun 			e->type = e->type == E_LTH ? E_GEQ : E_LEQ;
785*4882a593Smuzhiyun 			break;
786*4882a593Smuzhiyun 		case E_OR:
787*4882a593Smuzhiyun 			// !(a || b) -> !a && !b
788*4882a593Smuzhiyun 			tmp = e->left.expr;
789*4882a593Smuzhiyun 			e->type = E_AND;
790*4882a593Smuzhiyun 			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
791*4882a593Smuzhiyun 			tmp->type = E_NOT;
792*4882a593Smuzhiyun 			tmp->right.expr = NULL;
793*4882a593Smuzhiyun 			e = expr_transform(e);
794*4882a593Smuzhiyun 			break;
795*4882a593Smuzhiyun 		case E_AND:
796*4882a593Smuzhiyun 			// !(a && b) -> !a || !b
797*4882a593Smuzhiyun 			tmp = e->left.expr;
798*4882a593Smuzhiyun 			e->type = E_OR;
799*4882a593Smuzhiyun 			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
800*4882a593Smuzhiyun 			tmp->type = E_NOT;
801*4882a593Smuzhiyun 			tmp->right.expr = NULL;
802*4882a593Smuzhiyun 			e = expr_transform(e);
803*4882a593Smuzhiyun 			break;
804*4882a593Smuzhiyun 		case E_SYMBOL:
805*4882a593Smuzhiyun 			if (e->left.expr->left.sym == &symbol_yes) {
806*4882a593Smuzhiyun 				// !'y' -> 'n'
807*4882a593Smuzhiyun 				tmp = e->left.expr;
808*4882a593Smuzhiyun 				free(e);
809*4882a593Smuzhiyun 				e = tmp;
810*4882a593Smuzhiyun 				e->type = E_SYMBOL;
811*4882a593Smuzhiyun 				e->left.sym = &symbol_no;
812*4882a593Smuzhiyun 				break;
813*4882a593Smuzhiyun 			}
814*4882a593Smuzhiyun 			if (e->left.expr->left.sym == &symbol_mod) {
815*4882a593Smuzhiyun 				// !'m' -> 'm'
816*4882a593Smuzhiyun 				tmp = e->left.expr;
817*4882a593Smuzhiyun 				free(e);
818*4882a593Smuzhiyun 				e = tmp;
819*4882a593Smuzhiyun 				e->type = E_SYMBOL;
820*4882a593Smuzhiyun 				e->left.sym = &symbol_mod;
821*4882a593Smuzhiyun 				break;
822*4882a593Smuzhiyun 			}
823*4882a593Smuzhiyun 			if (e->left.expr->left.sym == &symbol_no) {
824*4882a593Smuzhiyun 				// !'n' -> 'y'
825*4882a593Smuzhiyun 				tmp = e->left.expr;
826*4882a593Smuzhiyun 				free(e);
827*4882a593Smuzhiyun 				e = tmp;
828*4882a593Smuzhiyun 				e->type = E_SYMBOL;
829*4882a593Smuzhiyun 				e->left.sym = &symbol_yes;
830*4882a593Smuzhiyun 				break;
831*4882a593Smuzhiyun 			}
832*4882a593Smuzhiyun 			break;
833*4882a593Smuzhiyun 		default:
834*4882a593Smuzhiyun 			;
835*4882a593Smuzhiyun 		}
836*4882a593Smuzhiyun 		break;
837*4882a593Smuzhiyun 	default:
838*4882a593Smuzhiyun 		;
839*4882a593Smuzhiyun 	}
840*4882a593Smuzhiyun 	return e;
841*4882a593Smuzhiyun }
842*4882a593Smuzhiyun 
expr_contains_symbol(struct expr * dep,struct symbol * sym)843*4882a593Smuzhiyun int expr_contains_symbol(struct expr *dep, struct symbol *sym)
844*4882a593Smuzhiyun {
845*4882a593Smuzhiyun 	if (!dep)
846*4882a593Smuzhiyun 		return 0;
847*4882a593Smuzhiyun 
848*4882a593Smuzhiyun 	switch (dep->type) {
849*4882a593Smuzhiyun 	case E_AND:
850*4882a593Smuzhiyun 	case E_OR:
851*4882a593Smuzhiyun 		return expr_contains_symbol(dep->left.expr, sym) ||
852*4882a593Smuzhiyun 		       expr_contains_symbol(dep->right.expr, sym);
853*4882a593Smuzhiyun 	case E_SYMBOL:
854*4882a593Smuzhiyun 		return dep->left.sym == sym;
855*4882a593Smuzhiyun 	case E_EQUAL:
856*4882a593Smuzhiyun 	case E_GEQ:
857*4882a593Smuzhiyun 	case E_GTH:
858*4882a593Smuzhiyun 	case E_LEQ:
859*4882a593Smuzhiyun 	case E_LTH:
860*4882a593Smuzhiyun 	case E_UNEQUAL:
861*4882a593Smuzhiyun 		return dep->left.sym == sym ||
862*4882a593Smuzhiyun 		       dep->right.sym == sym;
863*4882a593Smuzhiyun 	case E_NOT:
864*4882a593Smuzhiyun 		return expr_contains_symbol(dep->left.expr, sym);
865*4882a593Smuzhiyun 	default:
866*4882a593Smuzhiyun 		;
867*4882a593Smuzhiyun 	}
868*4882a593Smuzhiyun 	return 0;
869*4882a593Smuzhiyun }
870*4882a593Smuzhiyun 
expr_depends_symbol(struct expr * dep,struct symbol * sym)871*4882a593Smuzhiyun bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
872*4882a593Smuzhiyun {
873*4882a593Smuzhiyun 	if (!dep)
874*4882a593Smuzhiyun 		return false;
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun 	switch (dep->type) {
877*4882a593Smuzhiyun 	case E_AND:
878*4882a593Smuzhiyun 		return expr_depends_symbol(dep->left.expr, sym) ||
879*4882a593Smuzhiyun 		       expr_depends_symbol(dep->right.expr, sym);
880*4882a593Smuzhiyun 	case E_SYMBOL:
881*4882a593Smuzhiyun 		return dep->left.sym == sym;
882*4882a593Smuzhiyun 	case E_EQUAL:
883*4882a593Smuzhiyun 		if (dep->left.sym == sym) {
884*4882a593Smuzhiyun 			if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
885*4882a593Smuzhiyun 				return true;
886*4882a593Smuzhiyun 		}
887*4882a593Smuzhiyun 		break;
888*4882a593Smuzhiyun 	case E_UNEQUAL:
889*4882a593Smuzhiyun 		if (dep->left.sym == sym) {
890*4882a593Smuzhiyun 			if (dep->right.sym == &symbol_no)
891*4882a593Smuzhiyun 				return true;
892*4882a593Smuzhiyun 		}
893*4882a593Smuzhiyun 		break;
894*4882a593Smuzhiyun 	default:
895*4882a593Smuzhiyun 		;
896*4882a593Smuzhiyun 	}
897*4882a593Smuzhiyun  	return false;
898*4882a593Smuzhiyun }
899*4882a593Smuzhiyun 
900*4882a593Smuzhiyun /*
901*4882a593Smuzhiyun  * Inserts explicit comparisons of type 'type' to symbol 'sym' into the
902*4882a593Smuzhiyun  * expression 'e'.
903*4882a593Smuzhiyun  *
904*4882a593Smuzhiyun  * Examples transformations for type == E_UNEQUAL, sym == &symbol_no:
905*4882a593Smuzhiyun  *
906*4882a593Smuzhiyun  *	A              ->  A!=n
907*4882a593Smuzhiyun  *	!A             ->  A=n
908*4882a593Smuzhiyun  *	A && B         ->  !(A=n || B=n)
909*4882a593Smuzhiyun  *	A || B         ->  !(A=n && B=n)
910*4882a593Smuzhiyun  *	A && (B || C)  ->  !(A=n || (B=n && C=n))
911*4882a593Smuzhiyun  *
912*4882a593Smuzhiyun  * Allocates and returns a new expression.
913*4882a593Smuzhiyun  */
expr_trans_compare(struct expr * e,enum expr_type type,struct symbol * sym)914*4882a593Smuzhiyun struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
915*4882a593Smuzhiyun {
916*4882a593Smuzhiyun 	struct expr *e1, *e2;
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun 	if (!e) {
919*4882a593Smuzhiyun 		e = expr_alloc_symbol(sym);
920*4882a593Smuzhiyun 		if (type == E_UNEQUAL)
921*4882a593Smuzhiyun 			e = expr_alloc_one(E_NOT, e);
922*4882a593Smuzhiyun 		return e;
923*4882a593Smuzhiyun 	}
924*4882a593Smuzhiyun 	switch (e->type) {
925*4882a593Smuzhiyun 	case E_AND:
926*4882a593Smuzhiyun 		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
927*4882a593Smuzhiyun 		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
928*4882a593Smuzhiyun 		if (sym == &symbol_yes)
929*4882a593Smuzhiyun 			e = expr_alloc_two(E_AND, e1, e2);
930*4882a593Smuzhiyun 		if (sym == &symbol_no)
931*4882a593Smuzhiyun 			e = expr_alloc_two(E_OR, e1, e2);
932*4882a593Smuzhiyun 		if (type == E_UNEQUAL)
933*4882a593Smuzhiyun 			e = expr_alloc_one(E_NOT, e);
934*4882a593Smuzhiyun 		return e;
935*4882a593Smuzhiyun 	case E_OR:
936*4882a593Smuzhiyun 		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
937*4882a593Smuzhiyun 		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
938*4882a593Smuzhiyun 		if (sym == &symbol_yes)
939*4882a593Smuzhiyun 			e = expr_alloc_two(E_OR, e1, e2);
940*4882a593Smuzhiyun 		if (sym == &symbol_no)
941*4882a593Smuzhiyun 			e = expr_alloc_two(E_AND, e1, e2);
942*4882a593Smuzhiyun 		if (type == E_UNEQUAL)
943*4882a593Smuzhiyun 			e = expr_alloc_one(E_NOT, e);
944*4882a593Smuzhiyun 		return e;
945*4882a593Smuzhiyun 	case E_NOT:
946*4882a593Smuzhiyun 		return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
947*4882a593Smuzhiyun 	case E_UNEQUAL:
948*4882a593Smuzhiyun 	case E_LTH:
949*4882a593Smuzhiyun 	case E_LEQ:
950*4882a593Smuzhiyun 	case E_GTH:
951*4882a593Smuzhiyun 	case E_GEQ:
952*4882a593Smuzhiyun 	case E_EQUAL:
953*4882a593Smuzhiyun 		if (type == E_EQUAL) {
954*4882a593Smuzhiyun 			if (sym == &symbol_yes)
955*4882a593Smuzhiyun 				return expr_copy(e);
956*4882a593Smuzhiyun 			if (sym == &symbol_mod)
957*4882a593Smuzhiyun 				return expr_alloc_symbol(&symbol_no);
958*4882a593Smuzhiyun 			if (sym == &symbol_no)
959*4882a593Smuzhiyun 				return expr_alloc_one(E_NOT, expr_copy(e));
960*4882a593Smuzhiyun 		} else {
961*4882a593Smuzhiyun 			if (sym == &symbol_yes)
962*4882a593Smuzhiyun 				return expr_alloc_one(E_NOT, expr_copy(e));
963*4882a593Smuzhiyun 			if (sym == &symbol_mod)
964*4882a593Smuzhiyun 				return expr_alloc_symbol(&symbol_yes);
965*4882a593Smuzhiyun 			if (sym == &symbol_no)
966*4882a593Smuzhiyun 				return expr_copy(e);
967*4882a593Smuzhiyun 		}
968*4882a593Smuzhiyun 		break;
969*4882a593Smuzhiyun 	case E_SYMBOL:
970*4882a593Smuzhiyun 		return expr_alloc_comp(type, e->left.sym, sym);
971*4882a593Smuzhiyun 	case E_LIST:
972*4882a593Smuzhiyun 	case E_RANGE:
973*4882a593Smuzhiyun 	case E_NONE:
974*4882a593Smuzhiyun 		/* panic */;
975*4882a593Smuzhiyun 	}
976*4882a593Smuzhiyun 	return NULL;
977*4882a593Smuzhiyun }
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun enum string_value_kind {
980*4882a593Smuzhiyun 	k_string,
981*4882a593Smuzhiyun 	k_signed,
982*4882a593Smuzhiyun 	k_unsigned,
983*4882a593Smuzhiyun 	k_invalid
984*4882a593Smuzhiyun };
985*4882a593Smuzhiyun 
986*4882a593Smuzhiyun union string_value {
987*4882a593Smuzhiyun 	unsigned long long u;
988*4882a593Smuzhiyun 	signed long long s;
989*4882a593Smuzhiyun };
990*4882a593Smuzhiyun 
expr_parse_string(const char * str,enum symbol_type type,union string_value * val)991*4882a593Smuzhiyun static enum string_value_kind expr_parse_string(const char *str,
992*4882a593Smuzhiyun 						enum symbol_type type,
993*4882a593Smuzhiyun 						union string_value *val)
994*4882a593Smuzhiyun {
995*4882a593Smuzhiyun 	char *tail;
996*4882a593Smuzhiyun 	enum string_value_kind kind;
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun 	errno = 0;
999*4882a593Smuzhiyun 	switch (type) {
1000*4882a593Smuzhiyun 	case S_BOOLEAN:
1001*4882a593Smuzhiyun 	case S_TRISTATE:
1002*4882a593Smuzhiyun 		val->s = !strcmp(str, "n") ? 0 :
1003*4882a593Smuzhiyun 			 !strcmp(str, "m") ? 1 :
1004*4882a593Smuzhiyun 			 !strcmp(str, "y") ? 2 : -1;
1005*4882a593Smuzhiyun 		return k_signed;
1006*4882a593Smuzhiyun 	case S_INT:
1007*4882a593Smuzhiyun 		val->s = strtoll(str, &tail, 10);
1008*4882a593Smuzhiyun 		kind = k_signed;
1009*4882a593Smuzhiyun 		break;
1010*4882a593Smuzhiyun 	case S_HEX:
1011*4882a593Smuzhiyun 		val->u = strtoull(str, &tail, 16);
1012*4882a593Smuzhiyun 		kind = k_unsigned;
1013*4882a593Smuzhiyun 		break;
1014*4882a593Smuzhiyun 	case S_STRING:
1015*4882a593Smuzhiyun 	case S_UNKNOWN:
1016*4882a593Smuzhiyun 		val->s = strtoll(str, &tail, 0);
1017*4882a593Smuzhiyun 		kind = k_signed;
1018*4882a593Smuzhiyun 		break;
1019*4882a593Smuzhiyun 	default:
1020*4882a593Smuzhiyun 		return k_invalid;
1021*4882a593Smuzhiyun 	}
1022*4882a593Smuzhiyun 	return !errno && !*tail && tail > str && isxdigit(tail[-1])
1023*4882a593Smuzhiyun 	       ? kind : k_string;
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun 
expr_calc_value(struct expr * e)1026*4882a593Smuzhiyun tristate expr_calc_value(struct expr *e)
1027*4882a593Smuzhiyun {
1028*4882a593Smuzhiyun 	tristate val1, val2;
1029*4882a593Smuzhiyun 	const char *str1, *str2;
1030*4882a593Smuzhiyun 	enum string_value_kind k1 = k_string, k2 = k_string;
1031*4882a593Smuzhiyun 	union string_value lval = {}, rval = {};
1032*4882a593Smuzhiyun 	int res;
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun 	if (!e)
1035*4882a593Smuzhiyun 		return yes;
1036*4882a593Smuzhiyun 
1037*4882a593Smuzhiyun 	switch (e->type) {
1038*4882a593Smuzhiyun 	case E_SYMBOL:
1039*4882a593Smuzhiyun 		sym_calc_value(e->left.sym);
1040*4882a593Smuzhiyun 		return e->left.sym->curr.tri;
1041*4882a593Smuzhiyun 	case E_AND:
1042*4882a593Smuzhiyun 		val1 = expr_calc_value(e->left.expr);
1043*4882a593Smuzhiyun 		val2 = expr_calc_value(e->right.expr);
1044*4882a593Smuzhiyun 		return EXPR_AND(val1, val2);
1045*4882a593Smuzhiyun 	case E_OR:
1046*4882a593Smuzhiyun 		val1 = expr_calc_value(e->left.expr);
1047*4882a593Smuzhiyun 		val2 = expr_calc_value(e->right.expr);
1048*4882a593Smuzhiyun 		return EXPR_OR(val1, val2);
1049*4882a593Smuzhiyun 	case E_NOT:
1050*4882a593Smuzhiyun 		val1 = expr_calc_value(e->left.expr);
1051*4882a593Smuzhiyun 		return EXPR_NOT(val1);
1052*4882a593Smuzhiyun 	case E_EQUAL:
1053*4882a593Smuzhiyun 	case E_GEQ:
1054*4882a593Smuzhiyun 	case E_GTH:
1055*4882a593Smuzhiyun 	case E_LEQ:
1056*4882a593Smuzhiyun 	case E_LTH:
1057*4882a593Smuzhiyun 	case E_UNEQUAL:
1058*4882a593Smuzhiyun 		break;
1059*4882a593Smuzhiyun 	default:
1060*4882a593Smuzhiyun 		printf("expr_calc_value: %d?\n", e->type);
1061*4882a593Smuzhiyun 		return no;
1062*4882a593Smuzhiyun 	}
1063*4882a593Smuzhiyun 
1064*4882a593Smuzhiyun 	sym_calc_value(e->left.sym);
1065*4882a593Smuzhiyun 	sym_calc_value(e->right.sym);
1066*4882a593Smuzhiyun 	str1 = sym_get_string_value(e->left.sym);
1067*4882a593Smuzhiyun 	str2 = sym_get_string_value(e->right.sym);
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun 	if (e->left.sym->type != S_STRING || e->right.sym->type != S_STRING) {
1070*4882a593Smuzhiyun 		k1 = expr_parse_string(str1, e->left.sym->type, &lval);
1071*4882a593Smuzhiyun 		k2 = expr_parse_string(str2, e->right.sym->type, &rval);
1072*4882a593Smuzhiyun 	}
1073*4882a593Smuzhiyun 
1074*4882a593Smuzhiyun 	if (k1 == k_string || k2 == k_string)
1075*4882a593Smuzhiyun 		res = strcmp(str1, str2);
1076*4882a593Smuzhiyun 	else if (k1 == k_invalid || k2 == k_invalid) {
1077*4882a593Smuzhiyun 		if (e->type != E_EQUAL && e->type != E_UNEQUAL) {
1078*4882a593Smuzhiyun 			printf("Cannot compare \"%s\" and \"%s\"\n", str1, str2);
1079*4882a593Smuzhiyun 			return no;
1080*4882a593Smuzhiyun 		}
1081*4882a593Smuzhiyun 		res = strcmp(str1, str2);
1082*4882a593Smuzhiyun 	} else if (k1 == k_unsigned || k2 == k_unsigned)
1083*4882a593Smuzhiyun 		res = (lval.u > rval.u) - (lval.u < rval.u);
1084*4882a593Smuzhiyun 	else /* if (k1 == k_signed && k2 == k_signed) */
1085*4882a593Smuzhiyun 		res = (lval.s > rval.s) - (lval.s < rval.s);
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun 	switch(e->type) {
1088*4882a593Smuzhiyun 	case E_EQUAL:
1089*4882a593Smuzhiyun 		return res ? no : yes;
1090*4882a593Smuzhiyun 	case E_GEQ:
1091*4882a593Smuzhiyun 		return res >= 0 ? yes : no;
1092*4882a593Smuzhiyun 	case E_GTH:
1093*4882a593Smuzhiyun 		return res > 0 ? yes : no;
1094*4882a593Smuzhiyun 	case E_LEQ:
1095*4882a593Smuzhiyun 		return res <= 0 ? yes : no;
1096*4882a593Smuzhiyun 	case E_LTH:
1097*4882a593Smuzhiyun 		return res < 0 ? yes : no;
1098*4882a593Smuzhiyun 	case E_UNEQUAL:
1099*4882a593Smuzhiyun 		return res ? yes : no;
1100*4882a593Smuzhiyun 	default:
1101*4882a593Smuzhiyun 		printf("expr_calc_value: relation %d?\n", e->type);
1102*4882a593Smuzhiyun 		return no;
1103*4882a593Smuzhiyun 	}
1104*4882a593Smuzhiyun }
1105*4882a593Smuzhiyun 
expr_compare_type(enum expr_type t1,enum expr_type t2)1106*4882a593Smuzhiyun static int expr_compare_type(enum expr_type t1, enum expr_type t2)
1107*4882a593Smuzhiyun {
1108*4882a593Smuzhiyun 	if (t1 == t2)
1109*4882a593Smuzhiyun 		return 0;
1110*4882a593Smuzhiyun 	switch (t1) {
1111*4882a593Smuzhiyun 	case E_LEQ:
1112*4882a593Smuzhiyun 	case E_LTH:
1113*4882a593Smuzhiyun 	case E_GEQ:
1114*4882a593Smuzhiyun 	case E_GTH:
1115*4882a593Smuzhiyun 		if (t2 == E_EQUAL || t2 == E_UNEQUAL)
1116*4882a593Smuzhiyun 			return 1;
1117*4882a593Smuzhiyun 	case E_EQUAL:
1118*4882a593Smuzhiyun 	case E_UNEQUAL:
1119*4882a593Smuzhiyun 		if (t2 == E_NOT)
1120*4882a593Smuzhiyun 			return 1;
1121*4882a593Smuzhiyun 	case E_NOT:
1122*4882a593Smuzhiyun 		if (t2 == E_AND)
1123*4882a593Smuzhiyun 			return 1;
1124*4882a593Smuzhiyun 	case E_AND:
1125*4882a593Smuzhiyun 		if (t2 == E_OR)
1126*4882a593Smuzhiyun 			return 1;
1127*4882a593Smuzhiyun 	case E_OR:
1128*4882a593Smuzhiyun 		if (t2 == E_LIST)
1129*4882a593Smuzhiyun 			return 1;
1130*4882a593Smuzhiyun 	case E_LIST:
1131*4882a593Smuzhiyun 		if (t2 == 0)
1132*4882a593Smuzhiyun 			return 1;
1133*4882a593Smuzhiyun 	default:
1134*4882a593Smuzhiyun 		return -1;
1135*4882a593Smuzhiyun 	}
1136*4882a593Smuzhiyun 	printf("[%dgt%d?]", t1, t2);
1137*4882a593Smuzhiyun 	return 0;
1138*4882a593Smuzhiyun }
1139*4882a593Smuzhiyun 
expr_print(struct expr * e,void (* fn)(void *,struct symbol *,const char *),void * data,int prevtoken)1140*4882a593Smuzhiyun void expr_print(struct expr *e,
1141*4882a593Smuzhiyun 		void (*fn)(void *, struct symbol *, const char *),
1142*4882a593Smuzhiyun 		void *data, int prevtoken)
1143*4882a593Smuzhiyun {
1144*4882a593Smuzhiyun 	if (!e) {
1145*4882a593Smuzhiyun 		fn(data, NULL, "y");
1146*4882a593Smuzhiyun 		return;
1147*4882a593Smuzhiyun 	}
1148*4882a593Smuzhiyun 
1149*4882a593Smuzhiyun 	if (expr_compare_type(prevtoken, e->type) > 0)
1150*4882a593Smuzhiyun 		fn(data, NULL, "(");
1151*4882a593Smuzhiyun 	switch (e->type) {
1152*4882a593Smuzhiyun 	case E_SYMBOL:
1153*4882a593Smuzhiyun 		if (e->left.sym->name)
1154*4882a593Smuzhiyun 			fn(data, e->left.sym, e->left.sym->name);
1155*4882a593Smuzhiyun 		else
1156*4882a593Smuzhiyun 			fn(data, NULL, "<choice>");
1157*4882a593Smuzhiyun 		break;
1158*4882a593Smuzhiyun 	case E_NOT:
1159*4882a593Smuzhiyun 		fn(data, NULL, "!");
1160*4882a593Smuzhiyun 		expr_print(e->left.expr, fn, data, E_NOT);
1161*4882a593Smuzhiyun 		break;
1162*4882a593Smuzhiyun 	case E_EQUAL:
1163*4882a593Smuzhiyun 		if (e->left.sym->name)
1164*4882a593Smuzhiyun 			fn(data, e->left.sym, e->left.sym->name);
1165*4882a593Smuzhiyun 		else
1166*4882a593Smuzhiyun 			fn(data, NULL, "<choice>");
1167*4882a593Smuzhiyun 		fn(data, NULL, "=");
1168*4882a593Smuzhiyun 		fn(data, e->right.sym, e->right.sym->name);
1169*4882a593Smuzhiyun 		break;
1170*4882a593Smuzhiyun 	case E_LEQ:
1171*4882a593Smuzhiyun 	case E_LTH:
1172*4882a593Smuzhiyun 		if (e->left.sym->name)
1173*4882a593Smuzhiyun 			fn(data, e->left.sym, e->left.sym->name);
1174*4882a593Smuzhiyun 		else
1175*4882a593Smuzhiyun 			fn(data, NULL, "<choice>");
1176*4882a593Smuzhiyun 		fn(data, NULL, e->type == E_LEQ ? "<=" : "<");
1177*4882a593Smuzhiyun 		fn(data, e->right.sym, e->right.sym->name);
1178*4882a593Smuzhiyun 		break;
1179*4882a593Smuzhiyun 	case E_GEQ:
1180*4882a593Smuzhiyun 	case E_GTH:
1181*4882a593Smuzhiyun 		if (e->left.sym->name)
1182*4882a593Smuzhiyun 			fn(data, e->left.sym, e->left.sym->name);
1183*4882a593Smuzhiyun 		else
1184*4882a593Smuzhiyun 			fn(data, NULL, "<choice>");
1185*4882a593Smuzhiyun 		fn(data, NULL, e->type == E_GEQ ? ">=" : ">");
1186*4882a593Smuzhiyun 		fn(data, e->right.sym, e->right.sym->name);
1187*4882a593Smuzhiyun 		break;
1188*4882a593Smuzhiyun 	case E_UNEQUAL:
1189*4882a593Smuzhiyun 		if (e->left.sym->name)
1190*4882a593Smuzhiyun 			fn(data, e->left.sym, e->left.sym->name);
1191*4882a593Smuzhiyun 		else
1192*4882a593Smuzhiyun 			fn(data, NULL, "<choice>");
1193*4882a593Smuzhiyun 		fn(data, NULL, "!=");
1194*4882a593Smuzhiyun 		fn(data, e->right.sym, e->right.sym->name);
1195*4882a593Smuzhiyun 		break;
1196*4882a593Smuzhiyun 	case E_OR:
1197*4882a593Smuzhiyun 		expr_print(e->left.expr, fn, data, E_OR);
1198*4882a593Smuzhiyun 		fn(data, NULL, " || ");
1199*4882a593Smuzhiyun 		expr_print(e->right.expr, fn, data, E_OR);
1200*4882a593Smuzhiyun 		break;
1201*4882a593Smuzhiyun 	case E_AND:
1202*4882a593Smuzhiyun 		expr_print(e->left.expr, fn, data, E_AND);
1203*4882a593Smuzhiyun 		fn(data, NULL, " && ");
1204*4882a593Smuzhiyun 		expr_print(e->right.expr, fn, data, E_AND);
1205*4882a593Smuzhiyun 		break;
1206*4882a593Smuzhiyun 	case E_LIST:
1207*4882a593Smuzhiyun 		fn(data, e->right.sym, e->right.sym->name);
1208*4882a593Smuzhiyun 		if (e->left.expr) {
1209*4882a593Smuzhiyun 			fn(data, NULL, " ^ ");
1210*4882a593Smuzhiyun 			expr_print(e->left.expr, fn, data, E_LIST);
1211*4882a593Smuzhiyun 		}
1212*4882a593Smuzhiyun 		break;
1213*4882a593Smuzhiyun 	case E_RANGE:
1214*4882a593Smuzhiyun 		fn(data, NULL, "[");
1215*4882a593Smuzhiyun 		fn(data, e->left.sym, e->left.sym->name);
1216*4882a593Smuzhiyun 		fn(data, NULL, " ");
1217*4882a593Smuzhiyun 		fn(data, e->right.sym, e->right.sym->name);
1218*4882a593Smuzhiyun 		fn(data, NULL, "]");
1219*4882a593Smuzhiyun 		break;
1220*4882a593Smuzhiyun 	default:
1221*4882a593Smuzhiyun 	  {
1222*4882a593Smuzhiyun 		char buf[32];
1223*4882a593Smuzhiyun 		sprintf(buf, "<unknown type %d>", e->type);
1224*4882a593Smuzhiyun 		fn(data, NULL, buf);
1225*4882a593Smuzhiyun 		break;
1226*4882a593Smuzhiyun 	  }
1227*4882a593Smuzhiyun 	}
1228*4882a593Smuzhiyun 	if (expr_compare_type(prevtoken, e->type) > 0)
1229*4882a593Smuzhiyun 		fn(data, NULL, ")");
1230*4882a593Smuzhiyun }
1231*4882a593Smuzhiyun 
expr_print_file_helper(void * data,struct symbol * sym,const char * str)1232*4882a593Smuzhiyun static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
1233*4882a593Smuzhiyun {
1234*4882a593Smuzhiyun 	xfwrite(str, strlen(str), 1, data);
1235*4882a593Smuzhiyun }
1236*4882a593Smuzhiyun 
expr_fprint(struct expr * e,FILE * out)1237*4882a593Smuzhiyun void expr_fprint(struct expr *e, FILE *out)
1238*4882a593Smuzhiyun {
1239*4882a593Smuzhiyun 	expr_print(e, expr_print_file_helper, out, E_NONE);
1240*4882a593Smuzhiyun }
1241*4882a593Smuzhiyun 
expr_print_gstr_helper(void * data,struct symbol * sym,const char * str)1242*4882a593Smuzhiyun static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
1243*4882a593Smuzhiyun {
1244*4882a593Smuzhiyun 	struct gstr *gs = (struct gstr*)data;
1245*4882a593Smuzhiyun 	const char *sym_str = NULL;
1246*4882a593Smuzhiyun 
1247*4882a593Smuzhiyun 	if (sym)
1248*4882a593Smuzhiyun 		sym_str = sym_get_string_value(sym);
1249*4882a593Smuzhiyun 
1250*4882a593Smuzhiyun 	if (gs->max_width) {
1251*4882a593Smuzhiyun 		unsigned extra_length = strlen(str);
1252*4882a593Smuzhiyun 		const char *last_cr = strrchr(gs->s, '\n');
1253*4882a593Smuzhiyun 		unsigned last_line_length;
1254*4882a593Smuzhiyun 
1255*4882a593Smuzhiyun 		if (sym_str)
1256*4882a593Smuzhiyun 			extra_length += 4 + strlen(sym_str);
1257*4882a593Smuzhiyun 
1258*4882a593Smuzhiyun 		if (!last_cr)
1259*4882a593Smuzhiyun 			last_cr = gs->s;
1260*4882a593Smuzhiyun 
1261*4882a593Smuzhiyun 		last_line_length = strlen(gs->s) - (last_cr - gs->s);
1262*4882a593Smuzhiyun 
1263*4882a593Smuzhiyun 		if ((last_line_length + extra_length) > gs->max_width)
1264*4882a593Smuzhiyun 			str_append(gs, "\\\n");
1265*4882a593Smuzhiyun 	}
1266*4882a593Smuzhiyun 
1267*4882a593Smuzhiyun 	str_append(gs, str);
1268*4882a593Smuzhiyun 	if (sym && sym->type != S_UNKNOWN)
1269*4882a593Smuzhiyun 		str_printf(gs, " [=%s]", sym_str);
1270*4882a593Smuzhiyun }
1271*4882a593Smuzhiyun 
expr_gstr_print(struct expr * e,struct gstr * gs)1272*4882a593Smuzhiyun void expr_gstr_print(struct expr *e, struct gstr *gs)
1273*4882a593Smuzhiyun {
1274*4882a593Smuzhiyun 	expr_print(e, expr_print_gstr_helper, gs, E_NONE);
1275*4882a593Smuzhiyun }
1276*4882a593Smuzhiyun 
1277*4882a593Smuzhiyun /*
1278*4882a593Smuzhiyun  * Transform the top level "||" tokens into newlines and prepend each
1279*4882a593Smuzhiyun  * line with a minus. This makes expressions much easier to read.
1280*4882a593Smuzhiyun  * Suitable for reverse dependency expressions.
1281*4882a593Smuzhiyun  */
expr_print_revdep(struct expr * e,void (* fn)(void *,struct symbol *,const char *),void * data,tristate pr_type,const char ** title)1282*4882a593Smuzhiyun static void expr_print_revdep(struct expr *e,
1283*4882a593Smuzhiyun 			      void (*fn)(void *, struct symbol *, const char *),
1284*4882a593Smuzhiyun 			      void *data, tristate pr_type, const char **title)
1285*4882a593Smuzhiyun {
1286*4882a593Smuzhiyun 	if (e->type == E_OR) {
1287*4882a593Smuzhiyun 		expr_print_revdep(e->left.expr, fn, data, pr_type, title);
1288*4882a593Smuzhiyun 		expr_print_revdep(e->right.expr, fn, data, pr_type, title);
1289*4882a593Smuzhiyun 	} else if (expr_calc_value(e) == pr_type) {
1290*4882a593Smuzhiyun 		if (*title) {
1291*4882a593Smuzhiyun 			fn(data, NULL, *title);
1292*4882a593Smuzhiyun 			*title = NULL;
1293*4882a593Smuzhiyun 		}
1294*4882a593Smuzhiyun 
1295*4882a593Smuzhiyun 		fn(data, NULL, "  - ");
1296*4882a593Smuzhiyun 		expr_print(e, fn, data, E_NONE);
1297*4882a593Smuzhiyun 		fn(data, NULL, "\n");
1298*4882a593Smuzhiyun 	}
1299*4882a593Smuzhiyun }
1300*4882a593Smuzhiyun 
expr_gstr_print_revdep(struct expr * e,struct gstr * gs,tristate pr_type,const char * title)1301*4882a593Smuzhiyun void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
1302*4882a593Smuzhiyun 			    tristate pr_type, const char *title)
1303*4882a593Smuzhiyun {
1304*4882a593Smuzhiyun 	expr_print_revdep(e, expr_print_gstr_helper, gs, pr_type, &title);
1305*4882a593Smuzhiyun }
1306