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