Chameleon

Chameleon Svn Source Tree

Root/tags/2.0/i386/config/expr.c

Source at commit 1808 created 12 years 3 months ago.
By blackosx, Revise layout of package installer 'Welcome' file so it looks cleaner. Change the copyright notice to begin from 2009 as seen in the Chameleon 2.0 r431 installer. Should this date be set earlier?
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: 1808