Chameleon

Chameleon Svn Source Tree

Root/branches/JrCs/i386/config/expr.c

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

Archive Download this file

Revision: 1466