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