xref: /aosp_15_r20/external/toybox/kconfig/expr.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /*
2*cf5a6c84SAndroid Build Coastguard Worker  * Copyright (C) 2002 Roman Zippel <[email protected]>
3*cf5a6c84SAndroid Build Coastguard Worker  * Released under the terms of the GNU GPL v2.0.
4*cf5a6c84SAndroid Build Coastguard Worker  */
5*cf5a6c84SAndroid Build Coastguard Worker 
6*cf5a6c84SAndroid Build Coastguard Worker #include <stdio.h>
7*cf5a6c84SAndroid Build Coastguard Worker #include <stdlib.h>
8*cf5a6c84SAndroid Build Coastguard Worker #include <string.h>
9*cf5a6c84SAndroid Build Coastguard Worker 
10*cf5a6c84SAndroid Build Coastguard Worker #define LKC_DIRECT_LINK
11*cf5a6c84SAndroid Build Coastguard Worker #include "lkc.h"
12*cf5a6c84SAndroid Build Coastguard Worker 
13*cf5a6c84SAndroid Build Coastguard Worker #define DEBUG_EXPR	0
14*cf5a6c84SAndroid Build Coastguard Worker 
expr_alloc_symbol(struct symbol * sym)15*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_alloc_symbol(struct symbol *sym)
16*cf5a6c84SAndroid Build Coastguard Worker {
17*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *e = malloc(sizeof(*e));
18*cf5a6c84SAndroid Build Coastguard Worker 	memset(e, 0, sizeof(*e));
19*cf5a6c84SAndroid Build Coastguard Worker 	e->type = E_SYMBOL;
20*cf5a6c84SAndroid Build Coastguard Worker 	e->left.sym = sym;
21*cf5a6c84SAndroid Build Coastguard Worker 	return e;
22*cf5a6c84SAndroid Build Coastguard Worker }
23*cf5a6c84SAndroid Build Coastguard Worker 
expr_alloc_one(enum expr_type type,struct expr * ce)24*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
25*cf5a6c84SAndroid Build Coastguard Worker {
26*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *e = malloc(sizeof(*e));
27*cf5a6c84SAndroid Build Coastguard Worker 	memset(e, 0, sizeof(*e));
28*cf5a6c84SAndroid Build Coastguard Worker 	e->type = type;
29*cf5a6c84SAndroid Build Coastguard Worker 	e->left.expr = ce;
30*cf5a6c84SAndroid Build Coastguard Worker 	return e;
31*cf5a6c84SAndroid Build Coastguard Worker }
32*cf5a6c84SAndroid Build Coastguard Worker 
expr_alloc_two(enum expr_type type,struct expr * e1,struct expr * e2)33*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
34*cf5a6c84SAndroid Build Coastguard Worker {
35*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *e = malloc(sizeof(*e));
36*cf5a6c84SAndroid Build Coastguard Worker 	memset(e, 0, sizeof(*e));
37*cf5a6c84SAndroid Build Coastguard Worker 	e->type = type;
38*cf5a6c84SAndroid Build Coastguard Worker 	e->left.expr = e1;
39*cf5a6c84SAndroid Build Coastguard Worker 	e->right.expr = e2;
40*cf5a6c84SAndroid Build Coastguard Worker 	return e;
41*cf5a6c84SAndroid Build Coastguard Worker }
42*cf5a6c84SAndroid Build Coastguard Worker 
expr_alloc_comp(enum expr_type type,struct symbol * s1,struct symbol * s2)43*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
44*cf5a6c84SAndroid Build Coastguard Worker {
45*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *e = malloc(sizeof(*e));
46*cf5a6c84SAndroid Build Coastguard Worker 	memset(e, 0, sizeof(*e));
47*cf5a6c84SAndroid Build Coastguard Worker 	e->type = type;
48*cf5a6c84SAndroid Build Coastguard Worker 	e->left.sym = s1;
49*cf5a6c84SAndroid Build Coastguard Worker 	e->right.sym = s2;
50*cf5a6c84SAndroid Build Coastguard Worker 	return e;
51*cf5a6c84SAndroid Build Coastguard Worker }
52*cf5a6c84SAndroid Build Coastguard Worker 
expr_alloc_and(struct expr * e1,struct expr * e2)53*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
54*cf5a6c84SAndroid Build Coastguard Worker {
55*cf5a6c84SAndroid Build Coastguard Worker 	if (!e1)
56*cf5a6c84SAndroid Build Coastguard Worker 		return e2;
57*cf5a6c84SAndroid Build Coastguard Worker 	return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
58*cf5a6c84SAndroid Build Coastguard Worker }
59*cf5a6c84SAndroid Build Coastguard Worker 
expr_alloc_or(struct expr * e1,struct expr * e2)60*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
61*cf5a6c84SAndroid Build Coastguard Worker {
62*cf5a6c84SAndroid Build Coastguard Worker 	if (!e1)
63*cf5a6c84SAndroid Build Coastguard Worker 		return e2;
64*cf5a6c84SAndroid Build Coastguard Worker 	return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
65*cf5a6c84SAndroid Build Coastguard Worker }
66*cf5a6c84SAndroid Build Coastguard Worker 
expr_copy(struct expr * org)67*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_copy(struct expr *org)
68*cf5a6c84SAndroid Build Coastguard Worker {
69*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *e;
70*cf5a6c84SAndroid Build Coastguard Worker 
71*cf5a6c84SAndroid Build Coastguard Worker 	if (!org)
72*cf5a6c84SAndroid Build Coastguard Worker 		return NULL;
73*cf5a6c84SAndroid Build Coastguard Worker 
74*cf5a6c84SAndroid Build Coastguard Worker 	e = malloc(sizeof(*org));
75*cf5a6c84SAndroid Build Coastguard Worker 	memcpy(e, org, sizeof(*org));
76*cf5a6c84SAndroid Build Coastguard Worker 	switch (org->type) {
77*cf5a6c84SAndroid Build Coastguard Worker 	case E_SYMBOL:
78*cf5a6c84SAndroid Build Coastguard Worker 		e->left = org->left;
79*cf5a6c84SAndroid Build Coastguard Worker 		break;
80*cf5a6c84SAndroid Build Coastguard Worker 	case E_NOT:
81*cf5a6c84SAndroid Build Coastguard Worker 		e->left.expr = expr_copy(org->left.expr);
82*cf5a6c84SAndroid Build Coastguard Worker 		break;
83*cf5a6c84SAndroid Build Coastguard Worker 	case E_EQUAL:
84*cf5a6c84SAndroid Build Coastguard Worker 	case E_UNEQUAL:
85*cf5a6c84SAndroid Build Coastguard Worker 		e->left.sym = org->left.sym;
86*cf5a6c84SAndroid Build Coastguard Worker 		e->right.sym = org->right.sym;
87*cf5a6c84SAndroid Build Coastguard Worker 		break;
88*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
89*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
90*cf5a6c84SAndroid Build Coastguard Worker 	case E_CHOICE:
91*cf5a6c84SAndroid Build Coastguard Worker 		e->left.expr = expr_copy(org->left.expr);
92*cf5a6c84SAndroid Build Coastguard Worker 		e->right.expr = expr_copy(org->right.expr);
93*cf5a6c84SAndroid Build Coastguard Worker 		break;
94*cf5a6c84SAndroid Build Coastguard Worker 	default:
95*cf5a6c84SAndroid Build Coastguard Worker 		printf("can't copy type %d\n", e->type);
96*cf5a6c84SAndroid Build Coastguard Worker 		free(e);
97*cf5a6c84SAndroid Build Coastguard Worker 		e = NULL;
98*cf5a6c84SAndroid Build Coastguard Worker 		break;
99*cf5a6c84SAndroid Build Coastguard Worker 	}
100*cf5a6c84SAndroid Build Coastguard Worker 
101*cf5a6c84SAndroid Build Coastguard Worker 	return e;
102*cf5a6c84SAndroid Build Coastguard Worker }
103*cf5a6c84SAndroid Build Coastguard Worker 
expr_free(struct expr * e)104*cf5a6c84SAndroid Build Coastguard Worker void expr_free(struct expr *e)
105*cf5a6c84SAndroid Build Coastguard Worker {
106*cf5a6c84SAndroid Build Coastguard Worker 	if (!e)
107*cf5a6c84SAndroid Build Coastguard Worker 		return;
108*cf5a6c84SAndroid Build Coastguard Worker 
109*cf5a6c84SAndroid Build Coastguard Worker 	switch (e->type) {
110*cf5a6c84SAndroid Build Coastguard Worker 	case E_SYMBOL:
111*cf5a6c84SAndroid Build Coastguard Worker 		break;
112*cf5a6c84SAndroid Build Coastguard Worker 	case E_NOT:
113*cf5a6c84SAndroid Build Coastguard Worker 		expr_free(e->left.expr);
114*cf5a6c84SAndroid Build Coastguard Worker 		return;
115*cf5a6c84SAndroid Build Coastguard Worker 	case E_EQUAL:
116*cf5a6c84SAndroid Build Coastguard Worker 	case E_UNEQUAL:
117*cf5a6c84SAndroid Build Coastguard Worker 		break;
118*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
119*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
120*cf5a6c84SAndroid Build Coastguard Worker 		expr_free(e->left.expr);
121*cf5a6c84SAndroid Build Coastguard Worker 		expr_free(e->right.expr);
122*cf5a6c84SAndroid Build Coastguard Worker 		break;
123*cf5a6c84SAndroid Build Coastguard Worker 	default:
124*cf5a6c84SAndroid Build Coastguard Worker 		printf("how to free type %d?\n", e->type);
125*cf5a6c84SAndroid Build Coastguard Worker 		break;
126*cf5a6c84SAndroid Build Coastguard Worker 	}
127*cf5a6c84SAndroid Build Coastguard Worker 	free(e);
128*cf5a6c84SAndroid Build Coastguard Worker }
129*cf5a6c84SAndroid Build Coastguard Worker 
130*cf5a6c84SAndroid Build Coastguard Worker static int trans_count;
131*cf5a6c84SAndroid Build Coastguard Worker 
132*cf5a6c84SAndroid Build Coastguard Worker #define e1 (*ep1)
133*cf5a6c84SAndroid Build Coastguard Worker #define e2 (*ep2)
134*cf5a6c84SAndroid Build Coastguard Worker 
__expr_eliminate_eq(enum expr_type type,struct expr ** ep1,struct expr ** ep2)135*cf5a6c84SAndroid Build Coastguard Worker static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
136*cf5a6c84SAndroid Build Coastguard Worker {
137*cf5a6c84SAndroid Build Coastguard Worker 	if (e1->type == type) {
138*cf5a6c84SAndroid Build Coastguard Worker 		__expr_eliminate_eq(type, &e1->left.expr, &e2);
139*cf5a6c84SAndroid Build Coastguard Worker 		__expr_eliminate_eq(type, &e1->right.expr, &e2);
140*cf5a6c84SAndroid Build Coastguard Worker 		return;
141*cf5a6c84SAndroid Build Coastguard Worker 	}
142*cf5a6c84SAndroid Build Coastguard Worker 	if (e2->type == type) {
143*cf5a6c84SAndroid Build Coastguard Worker 		__expr_eliminate_eq(type, &e1, &e2->left.expr);
144*cf5a6c84SAndroid Build Coastguard Worker 		__expr_eliminate_eq(type, &e1, &e2->right.expr);
145*cf5a6c84SAndroid Build Coastguard Worker 		return;
146*cf5a6c84SAndroid Build Coastguard Worker 	}
147*cf5a6c84SAndroid Build Coastguard Worker 	if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
148*cf5a6c84SAndroid Build Coastguard Worker 	    e1->left.sym == e2->left.sym &&
149*cf5a6c84SAndroid Build Coastguard Worker 	    (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
150*cf5a6c84SAndroid Build Coastguard Worker 		return;
151*cf5a6c84SAndroid Build Coastguard Worker 	if (!expr_eq(e1, e2))
152*cf5a6c84SAndroid Build Coastguard Worker 		return;
153*cf5a6c84SAndroid Build Coastguard Worker 	trans_count++;
154*cf5a6c84SAndroid Build Coastguard Worker 	expr_free(e1); expr_free(e2);
155*cf5a6c84SAndroid Build Coastguard Worker 	switch (type) {
156*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
157*cf5a6c84SAndroid Build Coastguard Worker 		e1 = expr_alloc_symbol(&symbol_no);
158*cf5a6c84SAndroid Build Coastguard Worker 		e2 = expr_alloc_symbol(&symbol_no);
159*cf5a6c84SAndroid Build Coastguard Worker 		break;
160*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
161*cf5a6c84SAndroid Build Coastguard Worker 		e1 = expr_alloc_symbol(&symbol_yes);
162*cf5a6c84SAndroid Build Coastguard Worker 		e2 = expr_alloc_symbol(&symbol_yes);
163*cf5a6c84SAndroid Build Coastguard Worker 		break;
164*cf5a6c84SAndroid Build Coastguard Worker 	default:
165*cf5a6c84SAndroid Build Coastguard Worker 		;
166*cf5a6c84SAndroid Build Coastguard Worker 	}
167*cf5a6c84SAndroid Build Coastguard Worker }
168*cf5a6c84SAndroid Build Coastguard Worker 
expr_eliminate_eq(struct expr ** ep1,struct expr ** ep2)169*cf5a6c84SAndroid Build Coastguard Worker void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
170*cf5a6c84SAndroid Build Coastguard Worker {
171*cf5a6c84SAndroid Build Coastguard Worker 	if (!e1 || !e2)
172*cf5a6c84SAndroid Build Coastguard Worker 		return;
173*cf5a6c84SAndroid Build Coastguard Worker 	switch (e1->type) {
174*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
175*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
176*cf5a6c84SAndroid Build Coastguard Worker 		__expr_eliminate_eq(e1->type, ep1, ep2);
177*cf5a6c84SAndroid Build Coastguard Worker 	default:
178*cf5a6c84SAndroid Build Coastguard Worker 		;
179*cf5a6c84SAndroid Build Coastguard Worker 	}
180*cf5a6c84SAndroid Build Coastguard Worker 	if (e1->type != e2->type) switch (e2->type) {
181*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
182*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
183*cf5a6c84SAndroid Build Coastguard Worker 		__expr_eliminate_eq(e2->type, ep1, ep2);
184*cf5a6c84SAndroid Build Coastguard Worker 	default:
185*cf5a6c84SAndroid Build Coastguard Worker 		;
186*cf5a6c84SAndroid Build Coastguard Worker 	}
187*cf5a6c84SAndroid Build Coastguard Worker 	e1 = expr_eliminate_yn(e1);
188*cf5a6c84SAndroid Build Coastguard Worker 	e2 = expr_eliminate_yn(e2);
189*cf5a6c84SAndroid Build Coastguard Worker }
190*cf5a6c84SAndroid Build Coastguard Worker 
191*cf5a6c84SAndroid Build Coastguard Worker #undef e1
192*cf5a6c84SAndroid Build Coastguard Worker #undef e2
193*cf5a6c84SAndroid Build Coastguard Worker 
expr_eq(struct expr * e1,struct expr * e2)194*cf5a6c84SAndroid Build Coastguard Worker int expr_eq(struct expr *e1, struct expr *e2)
195*cf5a6c84SAndroid Build Coastguard Worker {
196*cf5a6c84SAndroid Build Coastguard Worker 	int res, old_count;
197*cf5a6c84SAndroid Build Coastguard Worker 
198*cf5a6c84SAndroid Build Coastguard Worker 	if (e1->type != e2->type)
199*cf5a6c84SAndroid Build Coastguard Worker 		return 0;
200*cf5a6c84SAndroid Build Coastguard Worker 	switch (e1->type) {
201*cf5a6c84SAndroid Build Coastguard Worker 	case E_EQUAL:
202*cf5a6c84SAndroid Build Coastguard Worker 	case E_UNEQUAL:
203*cf5a6c84SAndroid Build Coastguard Worker 		return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
204*cf5a6c84SAndroid Build Coastguard Worker 	case E_SYMBOL:
205*cf5a6c84SAndroid Build Coastguard Worker 		return e1->left.sym == e2->left.sym;
206*cf5a6c84SAndroid Build Coastguard Worker 	case E_NOT:
207*cf5a6c84SAndroid Build Coastguard Worker 		return expr_eq(e1->left.expr, e2->left.expr);
208*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
209*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
210*cf5a6c84SAndroid Build Coastguard Worker 		e1 = expr_copy(e1);
211*cf5a6c84SAndroid Build Coastguard Worker 		e2 = expr_copy(e2);
212*cf5a6c84SAndroid Build Coastguard Worker 		old_count = trans_count;
213*cf5a6c84SAndroid Build Coastguard Worker 		expr_eliminate_eq(&e1, &e2);
214*cf5a6c84SAndroid Build Coastguard Worker 		res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
215*cf5a6c84SAndroid Build Coastguard Worker 		       e1->left.sym == e2->left.sym);
216*cf5a6c84SAndroid Build Coastguard Worker 		expr_free(e1);
217*cf5a6c84SAndroid Build Coastguard Worker 		expr_free(e2);
218*cf5a6c84SAndroid Build Coastguard Worker 		trans_count = old_count;
219*cf5a6c84SAndroid Build Coastguard Worker 		return res;
220*cf5a6c84SAndroid Build Coastguard Worker 	case E_CHOICE:
221*cf5a6c84SAndroid Build Coastguard Worker 	case E_RANGE:
222*cf5a6c84SAndroid Build Coastguard Worker 	case E_NONE:
223*cf5a6c84SAndroid Build Coastguard Worker 		/* panic */;
224*cf5a6c84SAndroid Build Coastguard Worker 	}
225*cf5a6c84SAndroid Build Coastguard Worker 
226*cf5a6c84SAndroid Build Coastguard Worker 	if (DEBUG_EXPR) {
227*cf5a6c84SAndroid Build Coastguard Worker 		expr_fprint(e1, stdout);
228*cf5a6c84SAndroid Build Coastguard Worker 		printf(" = ");
229*cf5a6c84SAndroid Build Coastguard Worker 		expr_fprint(e2, stdout);
230*cf5a6c84SAndroid Build Coastguard Worker 		printf(" ?\n");
231*cf5a6c84SAndroid Build Coastguard Worker 	}
232*cf5a6c84SAndroid Build Coastguard Worker 
233*cf5a6c84SAndroid Build Coastguard Worker 	return 0;
234*cf5a6c84SAndroid Build Coastguard Worker }
235*cf5a6c84SAndroid Build Coastguard Worker 
expr_eliminate_yn(struct expr * e)236*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_eliminate_yn(struct expr *e)
237*cf5a6c84SAndroid Build Coastguard Worker {
238*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *tmp;
239*cf5a6c84SAndroid Build Coastguard Worker 
240*cf5a6c84SAndroid Build Coastguard Worker 	if (e) switch (e->type) {
241*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
242*cf5a6c84SAndroid Build Coastguard Worker 		e->left.expr = expr_eliminate_yn(e->left.expr);
243*cf5a6c84SAndroid Build Coastguard Worker 		e->right.expr = expr_eliminate_yn(e->right.expr);
244*cf5a6c84SAndroid Build Coastguard Worker 		if (e->left.expr->type == E_SYMBOL) {
245*cf5a6c84SAndroid Build Coastguard Worker 			if (e->left.expr->left.sym == &symbol_no) {
246*cf5a6c84SAndroid Build Coastguard Worker 				expr_free(e->left.expr);
247*cf5a6c84SAndroid Build Coastguard Worker 				expr_free(e->right.expr);
248*cf5a6c84SAndroid Build Coastguard Worker 				e->type = E_SYMBOL;
249*cf5a6c84SAndroid Build Coastguard Worker 				e->left.sym = &symbol_no;
250*cf5a6c84SAndroid Build Coastguard Worker 				e->right.expr = NULL;
251*cf5a6c84SAndroid Build Coastguard Worker 				return e;
252*cf5a6c84SAndroid Build Coastguard Worker 			} else if (e->left.expr->left.sym == &symbol_yes) {
253*cf5a6c84SAndroid Build Coastguard Worker 				free(e->left.expr);
254*cf5a6c84SAndroid Build Coastguard Worker 				tmp = e->right.expr;
255*cf5a6c84SAndroid Build Coastguard Worker 				*e = *(e->right.expr);
256*cf5a6c84SAndroid Build Coastguard Worker 				free(tmp);
257*cf5a6c84SAndroid Build Coastguard Worker 				return e;
258*cf5a6c84SAndroid Build Coastguard Worker 			}
259*cf5a6c84SAndroid Build Coastguard Worker 		}
260*cf5a6c84SAndroid Build Coastguard Worker 		if (e->right.expr->type == E_SYMBOL) {
261*cf5a6c84SAndroid Build Coastguard Worker 			if (e->right.expr->left.sym == &symbol_no) {
262*cf5a6c84SAndroid Build Coastguard Worker 				expr_free(e->left.expr);
263*cf5a6c84SAndroid Build Coastguard Worker 				expr_free(e->right.expr);
264*cf5a6c84SAndroid Build Coastguard Worker 				e->type = E_SYMBOL;
265*cf5a6c84SAndroid Build Coastguard Worker 				e->left.sym = &symbol_no;
266*cf5a6c84SAndroid Build Coastguard Worker 				e->right.expr = NULL;
267*cf5a6c84SAndroid Build Coastguard Worker 				return e;
268*cf5a6c84SAndroid Build Coastguard Worker 			} else if (e->right.expr->left.sym == &symbol_yes) {
269*cf5a6c84SAndroid Build Coastguard Worker 				free(e->right.expr);
270*cf5a6c84SAndroid Build Coastguard Worker 				tmp = e->left.expr;
271*cf5a6c84SAndroid Build Coastguard Worker 				*e = *(e->left.expr);
272*cf5a6c84SAndroid Build Coastguard Worker 				free(tmp);
273*cf5a6c84SAndroid Build Coastguard Worker 				return e;
274*cf5a6c84SAndroid Build Coastguard Worker 			}
275*cf5a6c84SAndroid Build Coastguard Worker 		}
276*cf5a6c84SAndroid Build Coastguard Worker 		break;
277*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
278*cf5a6c84SAndroid Build Coastguard Worker 		e->left.expr = expr_eliminate_yn(e->left.expr);
279*cf5a6c84SAndroid Build Coastguard Worker 		e->right.expr = expr_eliminate_yn(e->right.expr);
280*cf5a6c84SAndroid Build Coastguard Worker 		if (e->left.expr->type == E_SYMBOL) {
281*cf5a6c84SAndroid Build Coastguard Worker 			if (e->left.expr->left.sym == &symbol_no) {
282*cf5a6c84SAndroid Build Coastguard Worker 				free(e->left.expr);
283*cf5a6c84SAndroid Build Coastguard Worker 				tmp = e->right.expr;
284*cf5a6c84SAndroid Build Coastguard Worker 				*e = *(e->right.expr);
285*cf5a6c84SAndroid Build Coastguard Worker 				free(tmp);
286*cf5a6c84SAndroid Build Coastguard Worker 				return e;
287*cf5a6c84SAndroid Build Coastguard Worker 			} else if (e->left.expr->left.sym == &symbol_yes) {
288*cf5a6c84SAndroid Build Coastguard Worker 				expr_free(e->left.expr);
289*cf5a6c84SAndroid Build Coastguard Worker 				expr_free(e->right.expr);
290*cf5a6c84SAndroid Build Coastguard Worker 				e->type = E_SYMBOL;
291*cf5a6c84SAndroid Build Coastguard Worker 				e->left.sym = &symbol_yes;
292*cf5a6c84SAndroid Build Coastguard Worker 				e->right.expr = NULL;
293*cf5a6c84SAndroid Build Coastguard Worker 				return e;
294*cf5a6c84SAndroid Build Coastguard Worker 			}
295*cf5a6c84SAndroid Build Coastguard Worker 		}
296*cf5a6c84SAndroid Build Coastguard Worker 		if (e->right.expr->type == E_SYMBOL) {
297*cf5a6c84SAndroid Build Coastguard Worker 			if (e->right.expr->left.sym == &symbol_no) {
298*cf5a6c84SAndroid Build Coastguard Worker 				free(e->right.expr);
299*cf5a6c84SAndroid Build Coastguard Worker 				tmp = e->left.expr;
300*cf5a6c84SAndroid Build Coastguard Worker 				*e = *(e->left.expr);
301*cf5a6c84SAndroid Build Coastguard Worker 				free(tmp);
302*cf5a6c84SAndroid Build Coastguard Worker 				return e;
303*cf5a6c84SAndroid Build Coastguard Worker 			} else if (e->right.expr->left.sym == &symbol_yes) {
304*cf5a6c84SAndroid Build Coastguard Worker 				expr_free(e->left.expr);
305*cf5a6c84SAndroid Build Coastguard Worker 				expr_free(e->right.expr);
306*cf5a6c84SAndroid Build Coastguard Worker 				e->type = E_SYMBOL;
307*cf5a6c84SAndroid Build Coastguard Worker 				e->left.sym = &symbol_yes;
308*cf5a6c84SAndroid Build Coastguard Worker 				e->right.expr = NULL;
309*cf5a6c84SAndroid Build Coastguard Worker 				return e;
310*cf5a6c84SAndroid Build Coastguard Worker 			}
311*cf5a6c84SAndroid Build Coastguard Worker 		}
312*cf5a6c84SAndroid Build Coastguard Worker 		break;
313*cf5a6c84SAndroid Build Coastguard Worker 	default:
314*cf5a6c84SAndroid Build Coastguard Worker 		;
315*cf5a6c84SAndroid Build Coastguard Worker 	}
316*cf5a6c84SAndroid Build Coastguard Worker 	return e;
317*cf5a6c84SAndroid Build Coastguard Worker }
318*cf5a6c84SAndroid Build Coastguard Worker 
319*cf5a6c84SAndroid Build Coastguard Worker /*
320*cf5a6c84SAndroid Build Coastguard Worker  * bool FOO!=n => FOO
321*cf5a6c84SAndroid Build Coastguard Worker  */
expr_trans_bool(struct expr * e)322*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_trans_bool(struct expr *e)
323*cf5a6c84SAndroid Build Coastguard Worker {
324*cf5a6c84SAndroid Build Coastguard Worker 	if (!e)
325*cf5a6c84SAndroid Build Coastguard Worker 		return NULL;
326*cf5a6c84SAndroid Build Coastguard Worker 	switch (e->type) {
327*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
328*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
329*cf5a6c84SAndroid Build Coastguard Worker 	case E_NOT:
330*cf5a6c84SAndroid Build Coastguard Worker 		e->left.expr = expr_trans_bool(e->left.expr);
331*cf5a6c84SAndroid Build Coastguard Worker 		e->right.expr = expr_trans_bool(e->right.expr);
332*cf5a6c84SAndroid Build Coastguard Worker 		break;
333*cf5a6c84SAndroid Build Coastguard Worker 	case E_UNEQUAL:
334*cf5a6c84SAndroid Build Coastguard Worker 		// FOO!=n -> FOO
335*cf5a6c84SAndroid Build Coastguard Worker 		if (e->left.sym->type == S_TRISTATE) {
336*cf5a6c84SAndroid Build Coastguard Worker 			if (e->right.sym == &symbol_no) {
337*cf5a6c84SAndroid Build Coastguard Worker 				e->type = E_SYMBOL;
338*cf5a6c84SAndroid Build Coastguard Worker 				e->right.sym = NULL;
339*cf5a6c84SAndroid Build Coastguard Worker 			}
340*cf5a6c84SAndroid Build Coastguard Worker 		}
341*cf5a6c84SAndroid Build Coastguard Worker 		break;
342*cf5a6c84SAndroid Build Coastguard Worker 	default:
343*cf5a6c84SAndroid Build Coastguard Worker 		;
344*cf5a6c84SAndroid Build Coastguard Worker 	}
345*cf5a6c84SAndroid Build Coastguard Worker 	return e;
346*cf5a6c84SAndroid Build Coastguard Worker }
347*cf5a6c84SAndroid Build Coastguard Worker 
348*cf5a6c84SAndroid Build Coastguard Worker /*
349*cf5a6c84SAndroid Build Coastguard Worker  * e1 || e2 -> ?
350*cf5a6c84SAndroid Build Coastguard Worker  */
expr_join_or(struct expr * e1,struct expr * e2)351*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_join_or(struct expr *e1, struct expr *e2)
352*cf5a6c84SAndroid Build Coastguard Worker {
353*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *tmp;
354*cf5a6c84SAndroid Build Coastguard Worker 	struct symbol *sym1, *sym2;
355*cf5a6c84SAndroid Build Coastguard Worker 
356*cf5a6c84SAndroid Build Coastguard Worker 	if (expr_eq(e1, e2))
357*cf5a6c84SAndroid Build Coastguard Worker 		return expr_copy(e1);
358*cf5a6c84SAndroid Build Coastguard Worker 	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
359*cf5a6c84SAndroid Build Coastguard Worker 		return NULL;
360*cf5a6c84SAndroid Build Coastguard Worker 	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
361*cf5a6c84SAndroid Build Coastguard Worker 		return NULL;
362*cf5a6c84SAndroid Build Coastguard Worker 	if (e1->type == E_NOT) {
363*cf5a6c84SAndroid Build Coastguard Worker 		tmp = e1->left.expr;
364*cf5a6c84SAndroid Build Coastguard Worker 		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
365*cf5a6c84SAndroid Build Coastguard Worker 			return NULL;
366*cf5a6c84SAndroid Build Coastguard Worker 		sym1 = tmp->left.sym;
367*cf5a6c84SAndroid Build Coastguard Worker 	} else
368*cf5a6c84SAndroid Build Coastguard Worker 		sym1 = e1->left.sym;
369*cf5a6c84SAndroid Build Coastguard Worker 	if (e2->type == E_NOT) {
370*cf5a6c84SAndroid Build Coastguard Worker 		if (e2->left.expr->type != E_SYMBOL)
371*cf5a6c84SAndroid Build Coastguard Worker 			return NULL;
372*cf5a6c84SAndroid Build Coastguard Worker 		sym2 = e2->left.expr->left.sym;
373*cf5a6c84SAndroid Build Coastguard Worker 	} else
374*cf5a6c84SAndroid Build Coastguard Worker 		sym2 = e2->left.sym;
375*cf5a6c84SAndroid Build Coastguard Worker 	if (sym1 != sym2)
376*cf5a6c84SAndroid Build Coastguard Worker 		return NULL;
377*cf5a6c84SAndroid Build Coastguard Worker 	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
378*cf5a6c84SAndroid Build Coastguard Worker 		return NULL;
379*cf5a6c84SAndroid Build Coastguard Worker 	if (sym1->type == S_TRISTATE) {
380*cf5a6c84SAndroid Build Coastguard Worker 		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
381*cf5a6c84SAndroid Build Coastguard Worker 		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
382*cf5a6c84SAndroid Build Coastguard Worker 		     (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
383*cf5a6c84SAndroid Build Coastguard Worker 			// (a='y') || (a='m') -> (a!='n')
384*cf5a6c84SAndroid Build Coastguard Worker 			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
385*cf5a6c84SAndroid Build Coastguard Worker 		}
386*cf5a6c84SAndroid Build Coastguard Worker 		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
387*cf5a6c84SAndroid Build Coastguard Worker 		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
388*cf5a6c84SAndroid Build Coastguard Worker 		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
389*cf5a6c84SAndroid Build Coastguard Worker 			// (a='y') || (a='n') -> (a!='m')
390*cf5a6c84SAndroid Build Coastguard Worker 			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
391*cf5a6c84SAndroid Build Coastguard Worker 		}
392*cf5a6c84SAndroid Build Coastguard Worker 		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
393*cf5a6c84SAndroid Build Coastguard Worker 		    ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
394*cf5a6c84SAndroid Build Coastguard Worker 		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
395*cf5a6c84SAndroid Build Coastguard Worker 			// (a='m') || (a='n') -> (a!='y')
396*cf5a6c84SAndroid Build Coastguard Worker 			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
397*cf5a6c84SAndroid Build Coastguard Worker 		}
398*cf5a6c84SAndroid Build Coastguard Worker 	}
399*cf5a6c84SAndroid Build Coastguard Worker 	if (sym1->type == S_BOOLEAN && sym1 == sym2) {
400*cf5a6c84SAndroid Build Coastguard Worker 		if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
401*cf5a6c84SAndroid Build Coastguard Worker 		    (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
402*cf5a6c84SAndroid Build Coastguard Worker 			return expr_alloc_symbol(&symbol_yes);
403*cf5a6c84SAndroid Build Coastguard Worker 	}
404*cf5a6c84SAndroid Build Coastguard Worker 
405*cf5a6c84SAndroid Build Coastguard Worker 	if (DEBUG_EXPR) {
406*cf5a6c84SAndroid Build Coastguard Worker 		printf("optimize (");
407*cf5a6c84SAndroid Build Coastguard Worker 		expr_fprint(e1, stdout);
408*cf5a6c84SAndroid Build Coastguard Worker 		printf(") || (");
409*cf5a6c84SAndroid Build Coastguard Worker 		expr_fprint(e2, stdout);
410*cf5a6c84SAndroid Build Coastguard Worker 		printf(")?\n");
411*cf5a6c84SAndroid Build Coastguard Worker 	}
412*cf5a6c84SAndroid Build Coastguard Worker 	return NULL;
413*cf5a6c84SAndroid Build Coastguard Worker }
414*cf5a6c84SAndroid Build Coastguard Worker 
expr_join_and(struct expr * e1,struct expr * e2)415*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_join_and(struct expr *e1, struct expr *e2)
416*cf5a6c84SAndroid Build Coastguard Worker {
417*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *tmp;
418*cf5a6c84SAndroid Build Coastguard Worker 	struct symbol *sym1, *sym2;
419*cf5a6c84SAndroid Build Coastguard Worker 
420*cf5a6c84SAndroid Build Coastguard Worker 	if (expr_eq(e1, e2))
421*cf5a6c84SAndroid Build Coastguard Worker 		return expr_copy(e1);
422*cf5a6c84SAndroid Build Coastguard Worker 	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
423*cf5a6c84SAndroid Build Coastguard Worker 		return NULL;
424*cf5a6c84SAndroid Build Coastguard Worker 	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
425*cf5a6c84SAndroid Build Coastguard Worker 		return NULL;
426*cf5a6c84SAndroid Build Coastguard Worker 	if (e1->type == E_NOT) {
427*cf5a6c84SAndroid Build Coastguard Worker 		tmp = e1->left.expr;
428*cf5a6c84SAndroid Build Coastguard Worker 		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
429*cf5a6c84SAndroid Build Coastguard Worker 			return NULL;
430*cf5a6c84SAndroid Build Coastguard Worker 		sym1 = tmp->left.sym;
431*cf5a6c84SAndroid Build Coastguard Worker 	} else
432*cf5a6c84SAndroid Build Coastguard Worker 		sym1 = e1->left.sym;
433*cf5a6c84SAndroid Build Coastguard Worker 	if (e2->type == E_NOT) {
434*cf5a6c84SAndroid Build Coastguard Worker 		if (e2->left.expr->type != E_SYMBOL)
435*cf5a6c84SAndroid Build Coastguard Worker 			return NULL;
436*cf5a6c84SAndroid Build Coastguard Worker 		sym2 = e2->left.expr->left.sym;
437*cf5a6c84SAndroid Build Coastguard Worker 	} else
438*cf5a6c84SAndroid Build Coastguard Worker 		sym2 = e2->left.sym;
439*cf5a6c84SAndroid Build Coastguard Worker 	if (sym1 != sym2)
440*cf5a6c84SAndroid Build Coastguard Worker 		return NULL;
441*cf5a6c84SAndroid Build Coastguard Worker 	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
442*cf5a6c84SAndroid Build Coastguard Worker 		return NULL;
443*cf5a6c84SAndroid Build Coastguard Worker 
444*cf5a6c84SAndroid Build Coastguard Worker 	if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
445*cf5a6c84SAndroid Build Coastguard Worker 	    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
446*cf5a6c84SAndroid Build Coastguard Worker 		// (a) && (a='y') -> (a='y')
447*cf5a6c84SAndroid Build Coastguard Worker 		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
448*cf5a6c84SAndroid Build Coastguard Worker 
449*cf5a6c84SAndroid Build Coastguard Worker 	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
450*cf5a6c84SAndroid Build Coastguard Worker 	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
451*cf5a6c84SAndroid Build Coastguard Worker 		// (a) && (a!='n') -> (a)
452*cf5a6c84SAndroid Build Coastguard Worker 		return expr_alloc_symbol(sym1);
453*cf5a6c84SAndroid Build Coastguard Worker 
454*cf5a6c84SAndroid Build Coastguard Worker 	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
455*cf5a6c84SAndroid Build Coastguard Worker 	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
456*cf5a6c84SAndroid Build Coastguard Worker 		// (a) && (a!='m') -> (a='y')
457*cf5a6c84SAndroid Build Coastguard Worker 		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
458*cf5a6c84SAndroid Build Coastguard Worker 
459*cf5a6c84SAndroid Build Coastguard Worker 	if (sym1->type == S_TRISTATE) {
460*cf5a6c84SAndroid Build Coastguard Worker 		if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
461*cf5a6c84SAndroid Build Coastguard Worker 			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
462*cf5a6c84SAndroid Build Coastguard Worker 			sym2 = e1->right.sym;
463*cf5a6c84SAndroid Build Coastguard Worker 			if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
464*cf5a6c84SAndroid Build Coastguard Worker 				return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
465*cf5a6c84SAndroid Build Coastguard Worker 							     : expr_alloc_symbol(&symbol_no);
466*cf5a6c84SAndroid Build Coastguard Worker 		}
467*cf5a6c84SAndroid Build Coastguard Worker 		if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
468*cf5a6c84SAndroid Build Coastguard Worker 			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
469*cf5a6c84SAndroid Build Coastguard Worker 			sym2 = e2->right.sym;
470*cf5a6c84SAndroid Build Coastguard Worker 			if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
471*cf5a6c84SAndroid Build Coastguard Worker 				return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
472*cf5a6c84SAndroid Build Coastguard Worker 							     : expr_alloc_symbol(&symbol_no);
473*cf5a6c84SAndroid Build Coastguard Worker 		}
474*cf5a6c84SAndroid Build Coastguard Worker 		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
475*cf5a6c84SAndroid Build Coastguard Worker 			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
476*cf5a6c84SAndroid Build Coastguard Worker 			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
477*cf5a6c84SAndroid Build Coastguard Worker 			// (a!='y') && (a!='n') -> (a='m')
478*cf5a6c84SAndroid Build Coastguard Worker 			return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
479*cf5a6c84SAndroid Build Coastguard Worker 
480*cf5a6c84SAndroid Build Coastguard Worker 		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
481*cf5a6c84SAndroid Build Coastguard Worker 			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
482*cf5a6c84SAndroid Build Coastguard Worker 			    (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
483*cf5a6c84SAndroid Build Coastguard Worker 			// (a!='y') && (a!='m') -> (a='n')
484*cf5a6c84SAndroid Build Coastguard Worker 			return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
485*cf5a6c84SAndroid Build Coastguard Worker 
486*cf5a6c84SAndroid Build Coastguard Worker 		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
487*cf5a6c84SAndroid Build Coastguard Worker 			   ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
488*cf5a6c84SAndroid Build Coastguard Worker 			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
489*cf5a6c84SAndroid Build Coastguard Worker 			// (a!='m') && (a!='n') -> (a='m')
490*cf5a6c84SAndroid Build Coastguard Worker 			return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
491*cf5a6c84SAndroid Build Coastguard Worker 
492*cf5a6c84SAndroid Build Coastguard Worker 		if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
493*cf5a6c84SAndroid Build Coastguard Worker 		    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
494*cf5a6c84SAndroid Build Coastguard Worker 		    (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
495*cf5a6c84SAndroid Build Coastguard Worker 		    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
496*cf5a6c84SAndroid Build Coastguard Worker 			return NULL;
497*cf5a6c84SAndroid Build Coastguard Worker 	}
498*cf5a6c84SAndroid Build Coastguard Worker 
499*cf5a6c84SAndroid Build Coastguard Worker 	if (DEBUG_EXPR) {
500*cf5a6c84SAndroid Build Coastguard Worker 		printf("optimize (");
501*cf5a6c84SAndroid Build Coastguard Worker 		expr_fprint(e1, stdout);
502*cf5a6c84SAndroid Build Coastguard Worker 		printf(") && (");
503*cf5a6c84SAndroid Build Coastguard Worker 		expr_fprint(e2, stdout);
504*cf5a6c84SAndroid Build Coastguard Worker 		printf(")?\n");
505*cf5a6c84SAndroid Build Coastguard Worker 	}
506*cf5a6c84SAndroid Build Coastguard Worker 	return NULL;
507*cf5a6c84SAndroid Build Coastguard Worker }
508*cf5a6c84SAndroid Build Coastguard Worker 
expr_eliminate_dups1(enum expr_type type,struct expr ** ep1,struct expr ** ep2)509*cf5a6c84SAndroid Build Coastguard Worker static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
510*cf5a6c84SAndroid Build Coastguard Worker {
511*cf5a6c84SAndroid Build Coastguard Worker #define e1 (*ep1)
512*cf5a6c84SAndroid Build Coastguard Worker #define e2 (*ep2)
513*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *tmp;
514*cf5a6c84SAndroid Build Coastguard Worker 
515*cf5a6c84SAndroid Build Coastguard Worker 	if (e1->type == type) {
516*cf5a6c84SAndroid Build Coastguard Worker 		expr_eliminate_dups1(type, &e1->left.expr, &e2);
517*cf5a6c84SAndroid Build Coastguard Worker 		expr_eliminate_dups1(type, &e1->right.expr, &e2);
518*cf5a6c84SAndroid Build Coastguard Worker 		return;
519*cf5a6c84SAndroid Build Coastguard Worker 	}
520*cf5a6c84SAndroid Build Coastguard Worker 	if (e2->type == type) {
521*cf5a6c84SAndroid Build Coastguard Worker 		expr_eliminate_dups1(type, &e1, &e2->left.expr);
522*cf5a6c84SAndroid Build Coastguard Worker 		expr_eliminate_dups1(type, &e1, &e2->right.expr);
523*cf5a6c84SAndroid Build Coastguard Worker 		return;
524*cf5a6c84SAndroid Build Coastguard Worker 	}
525*cf5a6c84SAndroid Build Coastguard Worker 	if (e1 == e2)
526*cf5a6c84SAndroid Build Coastguard Worker 		return;
527*cf5a6c84SAndroid Build Coastguard Worker 
528*cf5a6c84SAndroid Build Coastguard Worker 	switch (e1->type) {
529*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR: case E_AND:
530*cf5a6c84SAndroid Build Coastguard Worker 		expr_eliminate_dups1(e1->type, &e1, &e1);
531*cf5a6c84SAndroid Build Coastguard Worker 	default:
532*cf5a6c84SAndroid Build Coastguard Worker 		;
533*cf5a6c84SAndroid Build Coastguard Worker 	}
534*cf5a6c84SAndroid Build Coastguard Worker 
535*cf5a6c84SAndroid Build Coastguard Worker 	switch (type) {
536*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
537*cf5a6c84SAndroid Build Coastguard Worker 		tmp = expr_join_or(e1, e2);
538*cf5a6c84SAndroid Build Coastguard Worker 		if (tmp) {
539*cf5a6c84SAndroid Build Coastguard Worker 			expr_free(e1); expr_free(e2);
540*cf5a6c84SAndroid Build Coastguard Worker 			e1 = expr_alloc_symbol(&symbol_no);
541*cf5a6c84SAndroid Build Coastguard Worker 			e2 = tmp;
542*cf5a6c84SAndroid Build Coastguard Worker 			trans_count++;
543*cf5a6c84SAndroid Build Coastguard Worker 		}
544*cf5a6c84SAndroid Build Coastguard Worker 		break;
545*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
546*cf5a6c84SAndroid Build Coastguard Worker 		tmp = expr_join_and(e1, e2);
547*cf5a6c84SAndroid Build Coastguard Worker 		if (tmp) {
548*cf5a6c84SAndroid Build Coastguard Worker 			expr_free(e1); expr_free(e2);
549*cf5a6c84SAndroid Build Coastguard Worker 			e1 = expr_alloc_symbol(&symbol_yes);
550*cf5a6c84SAndroid Build Coastguard Worker 			e2 = tmp;
551*cf5a6c84SAndroid Build Coastguard Worker 			trans_count++;
552*cf5a6c84SAndroid Build Coastguard Worker 		}
553*cf5a6c84SAndroid Build Coastguard Worker 		break;
554*cf5a6c84SAndroid Build Coastguard Worker 	default:
555*cf5a6c84SAndroid Build Coastguard Worker 		;
556*cf5a6c84SAndroid Build Coastguard Worker 	}
557*cf5a6c84SAndroid Build Coastguard Worker #undef e1
558*cf5a6c84SAndroid Build Coastguard Worker #undef e2
559*cf5a6c84SAndroid Build Coastguard Worker }
560*cf5a6c84SAndroid Build Coastguard Worker 
expr_eliminate_dups2(enum expr_type type,struct expr ** ep1,struct expr ** ep2)561*cf5a6c84SAndroid Build Coastguard Worker static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)
562*cf5a6c84SAndroid Build Coastguard Worker {
563*cf5a6c84SAndroid Build Coastguard Worker #define e1 (*ep1)
564*cf5a6c84SAndroid Build Coastguard Worker #define e2 (*ep2)
565*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *tmp, *tmp1, *tmp2;
566*cf5a6c84SAndroid Build Coastguard Worker 
567*cf5a6c84SAndroid Build Coastguard Worker 	if (e1->type == type) {
568*cf5a6c84SAndroid Build Coastguard Worker 		expr_eliminate_dups2(type, &e1->left.expr, &e2);
569*cf5a6c84SAndroid Build Coastguard Worker 		expr_eliminate_dups2(type, &e1->right.expr, &e2);
570*cf5a6c84SAndroid Build Coastguard Worker 		return;
571*cf5a6c84SAndroid Build Coastguard Worker 	}
572*cf5a6c84SAndroid Build Coastguard Worker 	if (e2->type == type) {
573*cf5a6c84SAndroid Build Coastguard Worker 		expr_eliminate_dups2(type, &e1, &e2->left.expr);
574*cf5a6c84SAndroid Build Coastguard Worker 		expr_eliminate_dups2(type, &e1, &e2->right.expr);
575*cf5a6c84SAndroid Build Coastguard Worker 	}
576*cf5a6c84SAndroid Build Coastguard Worker 	if (e1 == e2)
577*cf5a6c84SAndroid Build Coastguard Worker 		return;
578*cf5a6c84SAndroid Build Coastguard Worker 
579*cf5a6c84SAndroid Build Coastguard Worker 	switch (e1->type) {
580*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
581*cf5a6c84SAndroid Build Coastguard Worker 		expr_eliminate_dups2(e1->type, &e1, &e1);
582*cf5a6c84SAndroid Build Coastguard Worker 		// (FOO || BAR) && (!FOO && !BAR) -> n
583*cf5a6c84SAndroid Build Coastguard Worker 		tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
584*cf5a6c84SAndroid Build Coastguard Worker 		tmp2 = expr_copy(e2);
585*cf5a6c84SAndroid Build Coastguard Worker 		tmp = expr_extract_eq_and(&tmp1, &tmp2);
586*cf5a6c84SAndroid Build Coastguard Worker 		if (expr_is_yes(tmp1)) {
587*cf5a6c84SAndroid Build Coastguard Worker 			expr_free(e1);
588*cf5a6c84SAndroid Build Coastguard Worker 			e1 = expr_alloc_symbol(&symbol_no);
589*cf5a6c84SAndroid Build Coastguard Worker 			trans_count++;
590*cf5a6c84SAndroid Build Coastguard Worker 		}
591*cf5a6c84SAndroid Build Coastguard Worker 		expr_free(tmp2);
592*cf5a6c84SAndroid Build Coastguard Worker 		expr_free(tmp1);
593*cf5a6c84SAndroid Build Coastguard Worker 		expr_free(tmp);
594*cf5a6c84SAndroid Build Coastguard Worker 		break;
595*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
596*cf5a6c84SAndroid Build Coastguard Worker 		expr_eliminate_dups2(e1->type, &e1, &e1);
597*cf5a6c84SAndroid Build Coastguard Worker 		// (FOO && BAR) || (!FOO || !BAR) -> y
598*cf5a6c84SAndroid Build Coastguard Worker 		tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
599*cf5a6c84SAndroid Build Coastguard Worker 		tmp2 = expr_copy(e2);
600*cf5a6c84SAndroid Build Coastguard Worker 		tmp = expr_extract_eq_or(&tmp1, &tmp2);
601*cf5a6c84SAndroid Build Coastguard Worker 		if (expr_is_no(tmp1)) {
602*cf5a6c84SAndroid Build Coastguard Worker 			expr_free(e1);
603*cf5a6c84SAndroid Build Coastguard Worker 			e1 = expr_alloc_symbol(&symbol_yes);
604*cf5a6c84SAndroid Build Coastguard Worker 			trans_count++;
605*cf5a6c84SAndroid Build Coastguard Worker 		}
606*cf5a6c84SAndroid Build Coastguard Worker 		expr_free(tmp2);
607*cf5a6c84SAndroid Build Coastguard Worker 		expr_free(tmp1);
608*cf5a6c84SAndroid Build Coastguard Worker 		expr_free(tmp);
609*cf5a6c84SAndroid Build Coastguard Worker 		break;
610*cf5a6c84SAndroid Build Coastguard Worker 	default:
611*cf5a6c84SAndroid Build Coastguard Worker 		;
612*cf5a6c84SAndroid Build Coastguard Worker 	}
613*cf5a6c84SAndroid Build Coastguard Worker #undef e1
614*cf5a6c84SAndroid Build Coastguard Worker #undef e2
615*cf5a6c84SAndroid Build Coastguard Worker }
616*cf5a6c84SAndroid Build Coastguard Worker 
expr_eliminate_dups(struct expr * e)617*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_eliminate_dups(struct expr *e)
618*cf5a6c84SAndroid Build Coastguard Worker {
619*cf5a6c84SAndroid Build Coastguard Worker 	int oldcount;
620*cf5a6c84SAndroid Build Coastguard Worker 	if (!e)
621*cf5a6c84SAndroid Build Coastguard Worker 		return e;
622*cf5a6c84SAndroid Build Coastguard Worker 
623*cf5a6c84SAndroid Build Coastguard Worker 	oldcount = trans_count;
624*cf5a6c84SAndroid Build Coastguard Worker 	while (1) {
625*cf5a6c84SAndroid Build Coastguard Worker 		trans_count = 0;
626*cf5a6c84SAndroid Build Coastguard Worker 		switch (e->type) {
627*cf5a6c84SAndroid Build Coastguard Worker 		case E_OR: case E_AND:
628*cf5a6c84SAndroid Build Coastguard Worker 			expr_eliminate_dups1(e->type, &e, &e);
629*cf5a6c84SAndroid Build Coastguard Worker 			expr_eliminate_dups2(e->type, &e, &e);
630*cf5a6c84SAndroid Build Coastguard Worker 		default:
631*cf5a6c84SAndroid Build Coastguard Worker 			;
632*cf5a6c84SAndroid Build Coastguard Worker 		}
633*cf5a6c84SAndroid Build Coastguard Worker 		if (!trans_count)
634*cf5a6c84SAndroid Build Coastguard Worker 			break;
635*cf5a6c84SAndroid Build Coastguard Worker 		e = expr_eliminate_yn(e);
636*cf5a6c84SAndroid Build Coastguard Worker 	}
637*cf5a6c84SAndroid Build Coastguard Worker 	trans_count = oldcount;
638*cf5a6c84SAndroid Build Coastguard Worker 	return e;
639*cf5a6c84SAndroid Build Coastguard Worker }
640*cf5a6c84SAndroid Build Coastguard Worker 
expr_transform(struct expr * e)641*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_transform(struct expr *e)
642*cf5a6c84SAndroid Build Coastguard Worker {
643*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *tmp;
644*cf5a6c84SAndroid Build Coastguard Worker 
645*cf5a6c84SAndroid Build Coastguard Worker 	if (!e)
646*cf5a6c84SAndroid Build Coastguard Worker 		return NULL;
647*cf5a6c84SAndroid Build Coastguard Worker 	switch (e->type) {
648*cf5a6c84SAndroid Build Coastguard Worker 	case E_EQUAL:
649*cf5a6c84SAndroid Build Coastguard Worker 	case E_UNEQUAL:
650*cf5a6c84SAndroid Build Coastguard Worker 	case E_SYMBOL:
651*cf5a6c84SAndroid Build Coastguard Worker 	case E_CHOICE:
652*cf5a6c84SAndroid Build Coastguard Worker 		break;
653*cf5a6c84SAndroid Build Coastguard Worker 	default:
654*cf5a6c84SAndroid Build Coastguard Worker 		e->left.expr = expr_transform(e->left.expr);
655*cf5a6c84SAndroid Build Coastguard Worker 		e->right.expr = expr_transform(e->right.expr);
656*cf5a6c84SAndroid Build Coastguard Worker 	}
657*cf5a6c84SAndroid Build Coastguard Worker 
658*cf5a6c84SAndroid Build Coastguard Worker 	switch (e->type) {
659*cf5a6c84SAndroid Build Coastguard Worker 	case E_EQUAL:
660*cf5a6c84SAndroid Build Coastguard Worker 		if (e->left.sym->type != S_BOOLEAN)
661*cf5a6c84SAndroid Build Coastguard Worker 			break;
662*cf5a6c84SAndroid Build Coastguard Worker 		if (e->right.sym == &symbol_no) {
663*cf5a6c84SAndroid Build Coastguard Worker 			e->type = E_NOT;
664*cf5a6c84SAndroid Build Coastguard Worker 			e->left.expr = expr_alloc_symbol(e->left.sym);
665*cf5a6c84SAndroid Build Coastguard Worker 			e->right.sym = NULL;
666*cf5a6c84SAndroid Build Coastguard Worker 			break;
667*cf5a6c84SAndroid Build Coastguard Worker 		}
668*cf5a6c84SAndroid Build Coastguard Worker 		if (e->right.sym == &symbol_mod) {
669*cf5a6c84SAndroid Build Coastguard Worker 			printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
670*cf5a6c84SAndroid Build Coastguard Worker 			e->type = E_SYMBOL;
671*cf5a6c84SAndroid Build Coastguard Worker 			e->left.sym = &symbol_no;
672*cf5a6c84SAndroid Build Coastguard Worker 			e->right.sym = NULL;
673*cf5a6c84SAndroid Build Coastguard Worker 			break;
674*cf5a6c84SAndroid Build Coastguard Worker 		}
675*cf5a6c84SAndroid Build Coastguard Worker 		if (e->right.sym == &symbol_yes) {
676*cf5a6c84SAndroid Build Coastguard Worker 			e->type = E_SYMBOL;
677*cf5a6c84SAndroid Build Coastguard Worker 			e->right.sym = NULL;
678*cf5a6c84SAndroid Build Coastguard Worker 			break;
679*cf5a6c84SAndroid Build Coastguard Worker 		}
680*cf5a6c84SAndroid Build Coastguard Worker 		break;
681*cf5a6c84SAndroid Build Coastguard Worker 	case E_UNEQUAL:
682*cf5a6c84SAndroid Build Coastguard Worker 		if (e->left.sym->type != S_BOOLEAN)
683*cf5a6c84SAndroid Build Coastguard Worker 			break;
684*cf5a6c84SAndroid Build Coastguard Worker 		if (e->right.sym == &symbol_no) {
685*cf5a6c84SAndroid Build Coastguard Worker 			e->type = E_SYMBOL;
686*cf5a6c84SAndroid Build Coastguard Worker 			e->right.sym = NULL;
687*cf5a6c84SAndroid Build Coastguard Worker 			break;
688*cf5a6c84SAndroid Build Coastguard Worker 		}
689*cf5a6c84SAndroid Build Coastguard Worker 		if (e->right.sym == &symbol_mod) {
690*cf5a6c84SAndroid Build Coastguard Worker 			printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
691*cf5a6c84SAndroid Build Coastguard Worker 			e->type = E_SYMBOL;
692*cf5a6c84SAndroid Build Coastguard Worker 			e->left.sym = &symbol_yes;
693*cf5a6c84SAndroid Build Coastguard Worker 			e->right.sym = NULL;
694*cf5a6c84SAndroid Build Coastguard Worker 			break;
695*cf5a6c84SAndroid Build Coastguard Worker 		}
696*cf5a6c84SAndroid Build Coastguard Worker 		if (e->right.sym == &symbol_yes) {
697*cf5a6c84SAndroid Build Coastguard Worker 			e->type = E_NOT;
698*cf5a6c84SAndroid Build Coastguard Worker 			e->left.expr = expr_alloc_symbol(e->left.sym);
699*cf5a6c84SAndroid Build Coastguard Worker 			e->right.sym = NULL;
700*cf5a6c84SAndroid Build Coastguard Worker 			break;
701*cf5a6c84SAndroid Build Coastguard Worker 		}
702*cf5a6c84SAndroid Build Coastguard Worker 		break;
703*cf5a6c84SAndroid Build Coastguard Worker 	case E_NOT:
704*cf5a6c84SAndroid Build Coastguard Worker 		switch (e->left.expr->type) {
705*cf5a6c84SAndroid Build Coastguard Worker 		case E_NOT:
706*cf5a6c84SAndroid Build Coastguard Worker 			// !!a -> a
707*cf5a6c84SAndroid Build Coastguard Worker 			tmp = e->left.expr->left.expr;
708*cf5a6c84SAndroid Build Coastguard Worker 			free(e->left.expr);
709*cf5a6c84SAndroid Build Coastguard Worker 			free(e);
710*cf5a6c84SAndroid Build Coastguard Worker 			e = tmp;
711*cf5a6c84SAndroid Build Coastguard Worker 			e = expr_transform(e);
712*cf5a6c84SAndroid Build Coastguard Worker 			break;
713*cf5a6c84SAndroid Build Coastguard Worker 		case E_EQUAL:
714*cf5a6c84SAndroid Build Coastguard Worker 		case E_UNEQUAL:
715*cf5a6c84SAndroid Build Coastguard Worker 			// !a='x' -> a!='x'
716*cf5a6c84SAndroid Build Coastguard Worker 			tmp = e->left.expr;
717*cf5a6c84SAndroid Build Coastguard Worker 			free(e);
718*cf5a6c84SAndroid Build Coastguard Worker 			e = tmp;
719*cf5a6c84SAndroid Build Coastguard Worker 			e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
720*cf5a6c84SAndroid Build Coastguard Worker 			break;
721*cf5a6c84SAndroid Build Coastguard Worker 		case E_OR:
722*cf5a6c84SAndroid Build Coastguard Worker 			// !(a || b) -> !a && !b
723*cf5a6c84SAndroid Build Coastguard Worker 			tmp = e->left.expr;
724*cf5a6c84SAndroid Build Coastguard Worker 			e->type = E_AND;
725*cf5a6c84SAndroid Build Coastguard Worker 			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
726*cf5a6c84SAndroid Build Coastguard Worker 			tmp->type = E_NOT;
727*cf5a6c84SAndroid Build Coastguard Worker 			tmp->right.expr = NULL;
728*cf5a6c84SAndroid Build Coastguard Worker 			e = expr_transform(e);
729*cf5a6c84SAndroid Build Coastguard Worker 			break;
730*cf5a6c84SAndroid Build Coastguard Worker 		case E_AND:
731*cf5a6c84SAndroid Build Coastguard Worker 			// !(a && b) -> !a || !b
732*cf5a6c84SAndroid Build Coastguard Worker 			tmp = e->left.expr;
733*cf5a6c84SAndroid Build Coastguard Worker 			e->type = E_OR;
734*cf5a6c84SAndroid Build Coastguard Worker 			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
735*cf5a6c84SAndroid Build Coastguard Worker 			tmp->type = E_NOT;
736*cf5a6c84SAndroid Build Coastguard Worker 			tmp->right.expr = NULL;
737*cf5a6c84SAndroid Build Coastguard Worker 			e = expr_transform(e);
738*cf5a6c84SAndroid Build Coastguard Worker 			break;
739*cf5a6c84SAndroid Build Coastguard Worker 		case E_SYMBOL:
740*cf5a6c84SAndroid Build Coastguard Worker 			if (e->left.expr->left.sym == &symbol_yes) {
741*cf5a6c84SAndroid Build Coastguard Worker 				// !'y' -> 'n'
742*cf5a6c84SAndroid Build Coastguard Worker 				tmp = e->left.expr;
743*cf5a6c84SAndroid Build Coastguard Worker 				free(e);
744*cf5a6c84SAndroid Build Coastguard Worker 				e = tmp;
745*cf5a6c84SAndroid Build Coastguard Worker 				e->type = E_SYMBOL;
746*cf5a6c84SAndroid Build Coastguard Worker 				e->left.sym = &symbol_no;
747*cf5a6c84SAndroid Build Coastguard Worker 				break;
748*cf5a6c84SAndroid Build Coastguard Worker 			}
749*cf5a6c84SAndroid Build Coastguard Worker 			if (e->left.expr->left.sym == &symbol_mod) {
750*cf5a6c84SAndroid Build Coastguard Worker 				// !'m' -> 'm'
751*cf5a6c84SAndroid Build Coastguard Worker 				tmp = e->left.expr;
752*cf5a6c84SAndroid Build Coastguard Worker 				free(e);
753*cf5a6c84SAndroid Build Coastguard Worker 				e = tmp;
754*cf5a6c84SAndroid Build Coastguard Worker 				e->type = E_SYMBOL;
755*cf5a6c84SAndroid Build Coastguard Worker 				e->left.sym = &symbol_mod;
756*cf5a6c84SAndroid Build Coastguard Worker 				break;
757*cf5a6c84SAndroid Build Coastguard Worker 			}
758*cf5a6c84SAndroid Build Coastguard Worker 			if (e->left.expr->left.sym == &symbol_no) {
759*cf5a6c84SAndroid Build Coastguard Worker 				// !'n' -> 'y'
760*cf5a6c84SAndroid Build Coastguard Worker 				tmp = e->left.expr;
761*cf5a6c84SAndroid Build Coastguard Worker 				free(e);
762*cf5a6c84SAndroid Build Coastguard Worker 				e = tmp;
763*cf5a6c84SAndroid Build Coastguard Worker 				e->type = E_SYMBOL;
764*cf5a6c84SAndroid Build Coastguard Worker 				e->left.sym = &symbol_yes;
765*cf5a6c84SAndroid Build Coastguard Worker 				break;
766*cf5a6c84SAndroid Build Coastguard Worker 			}
767*cf5a6c84SAndroid Build Coastguard Worker 			break;
768*cf5a6c84SAndroid Build Coastguard Worker 		default:
769*cf5a6c84SAndroid Build Coastguard Worker 			;
770*cf5a6c84SAndroid Build Coastguard Worker 		}
771*cf5a6c84SAndroid Build Coastguard Worker 		break;
772*cf5a6c84SAndroid Build Coastguard Worker 	default:
773*cf5a6c84SAndroid Build Coastguard Worker 		;
774*cf5a6c84SAndroid Build Coastguard Worker 	}
775*cf5a6c84SAndroid Build Coastguard Worker 	return e;
776*cf5a6c84SAndroid Build Coastguard Worker }
777*cf5a6c84SAndroid Build Coastguard Worker 
expr_contains_symbol(struct expr * dep,struct symbol * sym)778*cf5a6c84SAndroid Build Coastguard Worker int expr_contains_symbol(struct expr *dep, struct symbol *sym)
779*cf5a6c84SAndroid Build Coastguard Worker {
780*cf5a6c84SAndroid Build Coastguard Worker 	if (!dep)
781*cf5a6c84SAndroid Build Coastguard Worker 		return 0;
782*cf5a6c84SAndroid Build Coastguard Worker 
783*cf5a6c84SAndroid Build Coastguard Worker 	switch (dep->type) {
784*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
785*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
786*cf5a6c84SAndroid Build Coastguard Worker 		return expr_contains_symbol(dep->left.expr, sym) ||
787*cf5a6c84SAndroid Build Coastguard Worker 		       expr_contains_symbol(dep->right.expr, sym);
788*cf5a6c84SAndroid Build Coastguard Worker 	case E_SYMBOL:
789*cf5a6c84SAndroid Build Coastguard Worker 		return dep->left.sym == sym;
790*cf5a6c84SAndroid Build Coastguard Worker 	case E_EQUAL:
791*cf5a6c84SAndroid Build Coastguard Worker 	case E_UNEQUAL:
792*cf5a6c84SAndroid Build Coastguard Worker 		return dep->left.sym == sym ||
793*cf5a6c84SAndroid Build Coastguard Worker 		       dep->right.sym == sym;
794*cf5a6c84SAndroid Build Coastguard Worker 	case E_NOT:
795*cf5a6c84SAndroid Build Coastguard Worker 		return expr_contains_symbol(dep->left.expr, sym);
796*cf5a6c84SAndroid Build Coastguard Worker 	default:
797*cf5a6c84SAndroid Build Coastguard Worker 		;
798*cf5a6c84SAndroid Build Coastguard Worker 	}
799*cf5a6c84SAndroid Build Coastguard Worker 	return 0;
800*cf5a6c84SAndroid Build Coastguard Worker }
801*cf5a6c84SAndroid Build Coastguard Worker 
expr_depends_symbol(struct expr * dep,struct symbol * sym)802*cf5a6c84SAndroid Build Coastguard Worker bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
803*cf5a6c84SAndroid Build Coastguard Worker {
804*cf5a6c84SAndroid Build Coastguard Worker 	if (!dep)
805*cf5a6c84SAndroid Build Coastguard Worker 		return false;
806*cf5a6c84SAndroid Build Coastguard Worker 
807*cf5a6c84SAndroid Build Coastguard Worker 	switch (dep->type) {
808*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
809*cf5a6c84SAndroid Build Coastguard Worker 		return expr_depends_symbol(dep->left.expr, sym) ||
810*cf5a6c84SAndroid Build Coastguard Worker 		       expr_depends_symbol(dep->right.expr, sym);
811*cf5a6c84SAndroid Build Coastguard Worker 	case E_SYMBOL:
812*cf5a6c84SAndroid Build Coastguard Worker 		return dep->left.sym == sym;
813*cf5a6c84SAndroid Build Coastguard Worker 	case E_EQUAL:
814*cf5a6c84SAndroid Build Coastguard Worker 		if (dep->left.sym == sym) {
815*cf5a6c84SAndroid Build Coastguard Worker 			if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
816*cf5a6c84SAndroid Build Coastguard Worker 				return true;
817*cf5a6c84SAndroid Build Coastguard Worker 		}
818*cf5a6c84SAndroid Build Coastguard Worker 		break;
819*cf5a6c84SAndroid Build Coastguard Worker 	case E_UNEQUAL:
820*cf5a6c84SAndroid Build Coastguard Worker 		if (dep->left.sym == sym) {
821*cf5a6c84SAndroid Build Coastguard Worker 			if (dep->right.sym == &symbol_no)
822*cf5a6c84SAndroid Build Coastguard Worker 				return true;
823*cf5a6c84SAndroid Build Coastguard Worker 		}
824*cf5a6c84SAndroid Build Coastguard Worker 		break;
825*cf5a6c84SAndroid Build Coastguard Worker 	default:
826*cf5a6c84SAndroid Build Coastguard Worker 		;
827*cf5a6c84SAndroid Build Coastguard Worker 	}
828*cf5a6c84SAndroid Build Coastguard Worker  	return false;
829*cf5a6c84SAndroid Build Coastguard Worker }
830*cf5a6c84SAndroid Build Coastguard Worker 
expr_extract_eq_and(struct expr ** ep1,struct expr ** ep2)831*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)
832*cf5a6c84SAndroid Build Coastguard Worker {
833*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *tmp = NULL;
834*cf5a6c84SAndroid Build Coastguard Worker 	expr_extract_eq(E_AND, &tmp, ep1, ep2);
835*cf5a6c84SAndroid Build Coastguard Worker 	if (tmp) {
836*cf5a6c84SAndroid Build Coastguard Worker 		*ep1 = expr_eliminate_yn(*ep1);
837*cf5a6c84SAndroid Build Coastguard Worker 		*ep2 = expr_eliminate_yn(*ep2);
838*cf5a6c84SAndroid Build Coastguard Worker 	}
839*cf5a6c84SAndroid Build Coastguard Worker 	return tmp;
840*cf5a6c84SAndroid Build Coastguard Worker }
841*cf5a6c84SAndroid Build Coastguard Worker 
expr_extract_eq_or(struct expr ** ep1,struct expr ** ep2)842*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)
843*cf5a6c84SAndroid Build Coastguard Worker {
844*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *tmp = NULL;
845*cf5a6c84SAndroid Build Coastguard Worker 	expr_extract_eq(E_OR, &tmp, ep1, ep2);
846*cf5a6c84SAndroid Build Coastguard Worker 	if (tmp) {
847*cf5a6c84SAndroid Build Coastguard Worker 		*ep1 = expr_eliminate_yn(*ep1);
848*cf5a6c84SAndroid Build Coastguard Worker 		*ep2 = expr_eliminate_yn(*ep2);
849*cf5a6c84SAndroid Build Coastguard Worker 	}
850*cf5a6c84SAndroid Build Coastguard Worker 	return tmp;
851*cf5a6c84SAndroid Build Coastguard Worker }
852*cf5a6c84SAndroid Build Coastguard Worker 
expr_extract_eq(enum expr_type type,struct expr ** ep,struct expr ** ep1,struct expr ** ep2)853*cf5a6c84SAndroid Build Coastguard Worker void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)
854*cf5a6c84SAndroid Build Coastguard Worker {
855*cf5a6c84SAndroid Build Coastguard Worker #define e1 (*ep1)
856*cf5a6c84SAndroid Build Coastguard Worker #define e2 (*ep2)
857*cf5a6c84SAndroid Build Coastguard Worker 	if (e1->type == type) {
858*cf5a6c84SAndroid Build Coastguard Worker 		expr_extract_eq(type, ep, &e1->left.expr, &e2);
859*cf5a6c84SAndroid Build Coastguard Worker 		expr_extract_eq(type, ep, &e1->right.expr, &e2);
860*cf5a6c84SAndroid Build Coastguard Worker 		return;
861*cf5a6c84SAndroid Build Coastguard Worker 	}
862*cf5a6c84SAndroid Build Coastguard Worker 	if (e2->type == type) {
863*cf5a6c84SAndroid Build Coastguard Worker 		expr_extract_eq(type, ep, ep1, &e2->left.expr);
864*cf5a6c84SAndroid Build Coastguard Worker 		expr_extract_eq(type, ep, ep1, &e2->right.expr);
865*cf5a6c84SAndroid Build Coastguard Worker 		return;
866*cf5a6c84SAndroid Build Coastguard Worker 	}
867*cf5a6c84SAndroid Build Coastguard Worker 	if (expr_eq(e1, e2)) {
868*cf5a6c84SAndroid Build Coastguard Worker 		*ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;
869*cf5a6c84SAndroid Build Coastguard Worker 		expr_free(e2);
870*cf5a6c84SAndroid Build Coastguard Worker 		if (type == E_AND) {
871*cf5a6c84SAndroid Build Coastguard Worker 			e1 = expr_alloc_symbol(&symbol_yes);
872*cf5a6c84SAndroid Build Coastguard Worker 			e2 = expr_alloc_symbol(&symbol_yes);
873*cf5a6c84SAndroid Build Coastguard Worker 		} else if (type == E_OR) {
874*cf5a6c84SAndroid Build Coastguard Worker 			e1 = expr_alloc_symbol(&symbol_no);
875*cf5a6c84SAndroid Build Coastguard Worker 			e2 = expr_alloc_symbol(&symbol_no);
876*cf5a6c84SAndroid Build Coastguard Worker 		}
877*cf5a6c84SAndroid Build Coastguard Worker 	}
878*cf5a6c84SAndroid Build Coastguard Worker #undef e1
879*cf5a6c84SAndroid Build Coastguard Worker #undef e2
880*cf5a6c84SAndroid Build Coastguard Worker }
881*cf5a6c84SAndroid Build Coastguard Worker 
expr_trans_compare(struct expr * e,enum expr_type type,struct symbol * sym)882*cf5a6c84SAndroid Build Coastguard Worker struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
883*cf5a6c84SAndroid Build Coastguard Worker {
884*cf5a6c84SAndroid Build Coastguard Worker 	struct expr *e1, *e2;
885*cf5a6c84SAndroid Build Coastguard Worker 
886*cf5a6c84SAndroid Build Coastguard Worker 	if (!e) {
887*cf5a6c84SAndroid Build Coastguard Worker 		e = expr_alloc_symbol(sym);
888*cf5a6c84SAndroid Build Coastguard Worker 		if (type == E_UNEQUAL)
889*cf5a6c84SAndroid Build Coastguard Worker 			e = expr_alloc_one(E_NOT, e);
890*cf5a6c84SAndroid Build Coastguard Worker 		return e;
891*cf5a6c84SAndroid Build Coastguard Worker 	}
892*cf5a6c84SAndroid Build Coastguard Worker 	switch (e->type) {
893*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
894*cf5a6c84SAndroid Build Coastguard Worker 		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
895*cf5a6c84SAndroid Build Coastguard Worker 		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
896*cf5a6c84SAndroid Build Coastguard Worker 		if (sym == &symbol_yes)
897*cf5a6c84SAndroid Build Coastguard Worker 			e = expr_alloc_two(E_AND, e1, e2);
898*cf5a6c84SAndroid Build Coastguard Worker 		if (sym == &symbol_no)
899*cf5a6c84SAndroid Build Coastguard Worker 			e = expr_alloc_two(E_OR, e1, e2);
900*cf5a6c84SAndroid Build Coastguard Worker 		if (type == E_UNEQUAL)
901*cf5a6c84SAndroid Build Coastguard Worker 			e = expr_alloc_one(E_NOT, e);
902*cf5a6c84SAndroid Build Coastguard Worker 		return e;
903*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
904*cf5a6c84SAndroid Build Coastguard Worker 		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
905*cf5a6c84SAndroid Build Coastguard Worker 		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
906*cf5a6c84SAndroid Build Coastguard Worker 		if (sym == &symbol_yes)
907*cf5a6c84SAndroid Build Coastguard Worker 			e = expr_alloc_two(E_OR, e1, e2);
908*cf5a6c84SAndroid Build Coastguard Worker 		if (sym == &symbol_no)
909*cf5a6c84SAndroid Build Coastguard Worker 			e = expr_alloc_two(E_AND, e1, e2);
910*cf5a6c84SAndroid Build Coastguard Worker 		if (type == E_UNEQUAL)
911*cf5a6c84SAndroid Build Coastguard Worker 			e = expr_alloc_one(E_NOT, e);
912*cf5a6c84SAndroid Build Coastguard Worker 		return e;
913*cf5a6c84SAndroid Build Coastguard Worker 	case E_NOT:
914*cf5a6c84SAndroid Build Coastguard Worker 		return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
915*cf5a6c84SAndroid Build Coastguard Worker 	case E_UNEQUAL:
916*cf5a6c84SAndroid Build Coastguard Worker 	case E_EQUAL:
917*cf5a6c84SAndroid Build Coastguard Worker 		if (type == E_EQUAL) {
918*cf5a6c84SAndroid Build Coastguard Worker 			if (sym == &symbol_yes)
919*cf5a6c84SAndroid Build Coastguard Worker 				return expr_copy(e);
920*cf5a6c84SAndroid Build Coastguard Worker 			if (sym == &symbol_mod)
921*cf5a6c84SAndroid Build Coastguard Worker 				return expr_alloc_symbol(&symbol_no);
922*cf5a6c84SAndroid Build Coastguard Worker 			if (sym == &symbol_no)
923*cf5a6c84SAndroid Build Coastguard Worker 				return expr_alloc_one(E_NOT, expr_copy(e));
924*cf5a6c84SAndroid Build Coastguard Worker 		} else {
925*cf5a6c84SAndroid Build Coastguard Worker 			if (sym == &symbol_yes)
926*cf5a6c84SAndroid Build Coastguard Worker 				return expr_alloc_one(E_NOT, expr_copy(e));
927*cf5a6c84SAndroid Build Coastguard Worker 			if (sym == &symbol_mod)
928*cf5a6c84SAndroid Build Coastguard Worker 				return expr_alloc_symbol(&symbol_yes);
929*cf5a6c84SAndroid Build Coastguard Worker 			if (sym == &symbol_no)
930*cf5a6c84SAndroid Build Coastguard Worker 				return expr_copy(e);
931*cf5a6c84SAndroid Build Coastguard Worker 		}
932*cf5a6c84SAndroid Build Coastguard Worker 		break;
933*cf5a6c84SAndroid Build Coastguard Worker 	case E_SYMBOL:
934*cf5a6c84SAndroid Build Coastguard Worker 		return expr_alloc_comp(type, e->left.sym, sym);
935*cf5a6c84SAndroid Build Coastguard Worker 	case E_CHOICE:
936*cf5a6c84SAndroid Build Coastguard Worker 	case E_RANGE:
937*cf5a6c84SAndroid Build Coastguard Worker 	case E_NONE:
938*cf5a6c84SAndroid Build Coastguard Worker 		/* panic */;
939*cf5a6c84SAndroid Build Coastguard Worker 	}
940*cf5a6c84SAndroid Build Coastguard Worker 	return NULL;
941*cf5a6c84SAndroid Build Coastguard Worker }
942*cf5a6c84SAndroid Build Coastguard Worker 
expr_calc_value(struct expr * e)943*cf5a6c84SAndroid Build Coastguard Worker tristate expr_calc_value(struct expr *e)
944*cf5a6c84SAndroid Build Coastguard Worker {
945*cf5a6c84SAndroid Build Coastguard Worker 	tristate val1, val2;
946*cf5a6c84SAndroid Build Coastguard Worker 	const char *str1, *str2;
947*cf5a6c84SAndroid Build Coastguard Worker 
948*cf5a6c84SAndroid Build Coastguard Worker 	if (!e)
949*cf5a6c84SAndroid Build Coastguard Worker 		return yes;
950*cf5a6c84SAndroid Build Coastguard Worker 
951*cf5a6c84SAndroid Build Coastguard Worker 	switch (e->type) {
952*cf5a6c84SAndroid Build Coastguard Worker 	case E_SYMBOL:
953*cf5a6c84SAndroid Build Coastguard Worker 		sym_calc_value(e->left.sym);
954*cf5a6c84SAndroid Build Coastguard Worker 		return e->left.sym->curr.tri;
955*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
956*cf5a6c84SAndroid Build Coastguard Worker 		val1 = expr_calc_value(e->left.expr);
957*cf5a6c84SAndroid Build Coastguard Worker 		val2 = expr_calc_value(e->right.expr);
958*cf5a6c84SAndroid Build Coastguard Worker 		return E_AND(val1, val2);
959*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
960*cf5a6c84SAndroid Build Coastguard Worker 		val1 = expr_calc_value(e->left.expr);
961*cf5a6c84SAndroid Build Coastguard Worker 		val2 = expr_calc_value(e->right.expr);
962*cf5a6c84SAndroid Build Coastguard Worker 		return E_OR(val1, val2);
963*cf5a6c84SAndroid Build Coastguard Worker 	case E_NOT:
964*cf5a6c84SAndroid Build Coastguard Worker 		val1 = expr_calc_value(e->left.expr);
965*cf5a6c84SAndroid Build Coastguard Worker 		return E_NOT(val1);
966*cf5a6c84SAndroid Build Coastguard Worker 	case E_EQUAL:
967*cf5a6c84SAndroid Build Coastguard Worker 		sym_calc_value(e->left.sym);
968*cf5a6c84SAndroid Build Coastguard Worker 		sym_calc_value(e->right.sym);
969*cf5a6c84SAndroid Build Coastguard Worker 		str1 = sym_get_string_value(e->left.sym);
970*cf5a6c84SAndroid Build Coastguard Worker 		str2 = sym_get_string_value(e->right.sym);
971*cf5a6c84SAndroid Build Coastguard Worker 		return !strcmp(str1, str2) ? yes : no;
972*cf5a6c84SAndroid Build Coastguard Worker 	case E_UNEQUAL:
973*cf5a6c84SAndroid Build Coastguard Worker 		sym_calc_value(e->left.sym);
974*cf5a6c84SAndroid Build Coastguard Worker 		sym_calc_value(e->right.sym);
975*cf5a6c84SAndroid Build Coastguard Worker 		str1 = sym_get_string_value(e->left.sym);
976*cf5a6c84SAndroid Build Coastguard Worker 		str2 = sym_get_string_value(e->right.sym);
977*cf5a6c84SAndroid Build Coastguard Worker 		return !strcmp(str1, str2) ? no : yes;
978*cf5a6c84SAndroid Build Coastguard Worker 	default:
979*cf5a6c84SAndroid Build Coastguard Worker 		printf("expr_calc_value: %d?\n", e->type);
980*cf5a6c84SAndroid Build Coastguard Worker 		return no;
981*cf5a6c84SAndroid Build Coastguard Worker 	}
982*cf5a6c84SAndroid Build Coastguard Worker }
983*cf5a6c84SAndroid Build Coastguard Worker 
expr_compare_type(enum expr_type t1,enum expr_type t2)984*cf5a6c84SAndroid Build Coastguard Worker int expr_compare_type(enum expr_type t1, enum expr_type t2)
985*cf5a6c84SAndroid Build Coastguard Worker {
986*cf5a6c84SAndroid Build Coastguard Worker #if 0
987*cf5a6c84SAndroid Build Coastguard Worker 	return 1;
988*cf5a6c84SAndroid Build Coastguard Worker #else
989*cf5a6c84SAndroid Build Coastguard Worker 	if (t1 == t2)
990*cf5a6c84SAndroid Build Coastguard Worker 		return 0;
991*cf5a6c84SAndroid Build Coastguard Worker 	switch (t1) {
992*cf5a6c84SAndroid Build Coastguard Worker 	case E_EQUAL:
993*cf5a6c84SAndroid Build Coastguard Worker 	case E_UNEQUAL:
994*cf5a6c84SAndroid Build Coastguard Worker 		if (t2 == E_NOT)
995*cf5a6c84SAndroid Build Coastguard Worker 			return 1;
996*cf5a6c84SAndroid Build Coastguard Worker 	case E_NOT:
997*cf5a6c84SAndroid Build Coastguard Worker 		if (t2 == E_AND)
998*cf5a6c84SAndroid Build Coastguard Worker 			return 1;
999*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
1000*cf5a6c84SAndroid Build Coastguard Worker 		if (t2 == E_OR)
1001*cf5a6c84SAndroid Build Coastguard Worker 			return 1;
1002*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
1003*cf5a6c84SAndroid Build Coastguard Worker 		if (t2 == E_CHOICE)
1004*cf5a6c84SAndroid Build Coastguard Worker 			return 1;
1005*cf5a6c84SAndroid Build Coastguard Worker 	case E_CHOICE:
1006*cf5a6c84SAndroid Build Coastguard Worker 		if (t2 == 0)
1007*cf5a6c84SAndroid Build Coastguard Worker 			return 1;
1008*cf5a6c84SAndroid Build Coastguard Worker 	default:
1009*cf5a6c84SAndroid Build Coastguard Worker 		return -1;
1010*cf5a6c84SAndroid Build Coastguard Worker 	}
1011*cf5a6c84SAndroid Build Coastguard Worker 	printf("[%dgt%d?]", t1, t2);
1012*cf5a6c84SAndroid Build Coastguard Worker 	return 0;
1013*cf5a6c84SAndroid Build Coastguard Worker #endif
1014*cf5a6c84SAndroid Build Coastguard Worker }
1015*cf5a6c84SAndroid Build Coastguard Worker 
expr_print(struct expr * e,void (* fn)(void *,struct symbol *,const char *),void * data,int prevtoken)1016*cf5a6c84SAndroid Build Coastguard Worker void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
1017*cf5a6c84SAndroid Build Coastguard Worker {
1018*cf5a6c84SAndroid Build Coastguard Worker 	if (!e) {
1019*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, NULL, "y");
1020*cf5a6c84SAndroid Build Coastguard Worker 		return;
1021*cf5a6c84SAndroid Build Coastguard Worker 	}
1022*cf5a6c84SAndroid Build Coastguard Worker 
1023*cf5a6c84SAndroid Build Coastguard Worker 	if (expr_compare_type(prevtoken, e->type) > 0)
1024*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, NULL, "(");
1025*cf5a6c84SAndroid Build Coastguard Worker 	switch (e->type) {
1026*cf5a6c84SAndroid Build Coastguard Worker 	case E_SYMBOL:
1027*cf5a6c84SAndroid Build Coastguard Worker 		if (e->left.sym->name)
1028*cf5a6c84SAndroid Build Coastguard Worker 			fn(data, e->left.sym, e->left.sym->name);
1029*cf5a6c84SAndroid Build Coastguard Worker 		else
1030*cf5a6c84SAndroid Build Coastguard Worker 			fn(data, NULL, "<choice>");
1031*cf5a6c84SAndroid Build Coastguard Worker 		break;
1032*cf5a6c84SAndroid Build Coastguard Worker 	case E_NOT:
1033*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, NULL, "!");
1034*cf5a6c84SAndroid Build Coastguard Worker 		expr_print(e->left.expr, fn, data, E_NOT);
1035*cf5a6c84SAndroid Build Coastguard Worker 		break;
1036*cf5a6c84SAndroid Build Coastguard Worker 	case E_EQUAL:
1037*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, e->left.sym, e->left.sym->name);
1038*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, NULL, "=");
1039*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, e->right.sym, e->right.sym->name);
1040*cf5a6c84SAndroid Build Coastguard Worker 		break;
1041*cf5a6c84SAndroid Build Coastguard Worker 	case E_UNEQUAL:
1042*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, e->left.sym, e->left.sym->name);
1043*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, NULL, "!=");
1044*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, e->right.sym, e->right.sym->name);
1045*cf5a6c84SAndroid Build Coastguard Worker 		break;
1046*cf5a6c84SAndroid Build Coastguard Worker 	case E_OR:
1047*cf5a6c84SAndroid Build Coastguard Worker 		expr_print(e->left.expr, fn, data, E_OR);
1048*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, NULL, " || ");
1049*cf5a6c84SAndroid Build Coastguard Worker 		expr_print(e->right.expr, fn, data, E_OR);
1050*cf5a6c84SAndroid Build Coastguard Worker 		break;
1051*cf5a6c84SAndroid Build Coastguard Worker 	case E_AND:
1052*cf5a6c84SAndroid Build Coastguard Worker 		expr_print(e->left.expr, fn, data, E_AND);
1053*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, NULL, " && ");
1054*cf5a6c84SAndroid Build Coastguard Worker 		expr_print(e->right.expr, fn, data, E_AND);
1055*cf5a6c84SAndroid Build Coastguard Worker 		break;
1056*cf5a6c84SAndroid Build Coastguard Worker 	case E_CHOICE:
1057*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, e->right.sym, e->right.sym->name);
1058*cf5a6c84SAndroid Build Coastguard Worker 		if (e->left.expr) {
1059*cf5a6c84SAndroid Build Coastguard Worker 			fn(data, NULL, " ^ ");
1060*cf5a6c84SAndroid Build Coastguard Worker 			expr_print(e->left.expr, fn, data, E_CHOICE);
1061*cf5a6c84SAndroid Build Coastguard Worker 		}
1062*cf5a6c84SAndroid Build Coastguard Worker 		break;
1063*cf5a6c84SAndroid Build Coastguard Worker 	case E_RANGE:
1064*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, NULL, "[");
1065*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, e->left.sym, e->left.sym->name);
1066*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, NULL, " ");
1067*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, e->right.sym, e->right.sym->name);
1068*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, NULL, "]");
1069*cf5a6c84SAndroid Build Coastguard Worker 		break;
1070*cf5a6c84SAndroid Build Coastguard Worker 	default:
1071*cf5a6c84SAndroid Build Coastguard Worker 	  {
1072*cf5a6c84SAndroid Build Coastguard Worker 		char buf[32];
1073*cf5a6c84SAndroid Build Coastguard Worker 		sprintf(buf, "<unknown type %d>", e->type);
1074*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, NULL, buf);
1075*cf5a6c84SAndroid Build Coastguard Worker 		break;
1076*cf5a6c84SAndroid Build Coastguard Worker 	  }
1077*cf5a6c84SAndroid Build Coastguard Worker 	}
1078*cf5a6c84SAndroid Build Coastguard Worker 	if (expr_compare_type(prevtoken, e->type) > 0)
1079*cf5a6c84SAndroid Build Coastguard Worker 		fn(data, NULL, ")");
1080*cf5a6c84SAndroid Build Coastguard Worker }
1081*cf5a6c84SAndroid Build Coastguard Worker 
expr_print_file_helper(void * data,struct symbol * sym,const char * str)1082*cf5a6c84SAndroid Build Coastguard Worker static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
1083*cf5a6c84SAndroid Build Coastguard Worker {
1084*cf5a6c84SAndroid Build Coastguard Worker 	fwrite(str, strlen(str), 1, data);
1085*cf5a6c84SAndroid Build Coastguard Worker }
1086*cf5a6c84SAndroid Build Coastguard Worker 
expr_fprint(struct expr * e,FILE * out)1087*cf5a6c84SAndroid Build Coastguard Worker void expr_fprint(struct expr *e, FILE *out)
1088*cf5a6c84SAndroid Build Coastguard Worker {
1089*cf5a6c84SAndroid Build Coastguard Worker 	expr_print(e, expr_print_file_helper, out, E_NONE);
1090*cf5a6c84SAndroid Build Coastguard Worker }
1091*cf5a6c84SAndroid Build Coastguard Worker 
expr_print_gstr_helper(void * data,struct symbol * sym,const char * str)1092*cf5a6c84SAndroid Build Coastguard Worker static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
1093*cf5a6c84SAndroid Build Coastguard Worker {
1094*cf5a6c84SAndroid Build Coastguard Worker 	str_append((struct gstr*)data, str);
1095*cf5a6c84SAndroid Build Coastguard Worker }
1096*cf5a6c84SAndroid Build Coastguard Worker 
expr_gstr_print(struct expr * e,struct gstr * gs)1097*cf5a6c84SAndroid Build Coastguard Worker void expr_gstr_print(struct expr *e, struct gstr *gs)
1098*cf5a6c84SAndroid Build Coastguard Worker {
1099*cf5a6c84SAndroid Build Coastguard Worker 	expr_print(e, expr_print_gstr_helper, gs, E_NONE);
1100*cf5a6c84SAndroid Build Coastguard Worker }
1101