xref: /rk3399_rockchip-uboot/scripts/kconfig/expr.c (revision 9b5f0b1da9ba7019316ed8c9698fe25e8c7fc33e)
10a9064fbSMasahiro Yamada /*
20a9064fbSMasahiro Yamada  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
30a9064fbSMasahiro Yamada  * Released under the terms of the GNU GPL v2.0.
40a9064fbSMasahiro Yamada  */
50a9064fbSMasahiro Yamada 
60a9064fbSMasahiro Yamada #include <stdio.h>
70a9064fbSMasahiro Yamada #include <stdlib.h>
80a9064fbSMasahiro Yamada #include <string.h>
90a9064fbSMasahiro Yamada 
100a9064fbSMasahiro Yamada #include "lkc.h"
110a9064fbSMasahiro Yamada 
120a9064fbSMasahiro Yamada #define DEBUG_EXPR	0
130a9064fbSMasahiro Yamada 
14*9b5f0b1dSMasahiro Yamada static int expr_eq(struct expr *e1, struct expr *e2);
15*9b5f0b1dSMasahiro Yamada static struct expr *expr_eliminate_yn(struct expr *e);
16*9b5f0b1dSMasahiro Yamada static struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2);
17*9b5f0b1dSMasahiro Yamada static struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2);
18*9b5f0b1dSMasahiro Yamada static void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2);
19*9b5f0b1dSMasahiro Yamada 
200a9064fbSMasahiro Yamada struct expr *expr_alloc_symbol(struct symbol *sym)
210a9064fbSMasahiro Yamada {
220a9064fbSMasahiro Yamada 	struct expr *e = xcalloc(1, sizeof(*e));
230a9064fbSMasahiro Yamada 	e->type = E_SYMBOL;
240a9064fbSMasahiro Yamada 	e->left.sym = sym;
250a9064fbSMasahiro Yamada 	return e;
260a9064fbSMasahiro Yamada }
270a9064fbSMasahiro Yamada 
280a9064fbSMasahiro Yamada struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
290a9064fbSMasahiro Yamada {
300a9064fbSMasahiro Yamada 	struct expr *e = xcalloc(1, sizeof(*e));
310a9064fbSMasahiro Yamada 	e->type = type;
320a9064fbSMasahiro Yamada 	e->left.expr = ce;
330a9064fbSMasahiro Yamada 	return e;
340a9064fbSMasahiro Yamada }
350a9064fbSMasahiro Yamada 
360a9064fbSMasahiro Yamada struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
370a9064fbSMasahiro Yamada {
380a9064fbSMasahiro Yamada 	struct expr *e = xcalloc(1, sizeof(*e));
390a9064fbSMasahiro Yamada 	e->type = type;
400a9064fbSMasahiro Yamada 	e->left.expr = e1;
410a9064fbSMasahiro Yamada 	e->right.expr = e2;
420a9064fbSMasahiro Yamada 	return e;
430a9064fbSMasahiro Yamada }
440a9064fbSMasahiro Yamada 
450a9064fbSMasahiro Yamada struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
460a9064fbSMasahiro Yamada {
470a9064fbSMasahiro Yamada 	struct expr *e = xcalloc(1, sizeof(*e));
480a9064fbSMasahiro Yamada 	e->type = type;
490a9064fbSMasahiro Yamada 	e->left.sym = s1;
500a9064fbSMasahiro Yamada 	e->right.sym = s2;
510a9064fbSMasahiro Yamada 	return e;
520a9064fbSMasahiro Yamada }
530a9064fbSMasahiro Yamada 
540a9064fbSMasahiro Yamada struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
550a9064fbSMasahiro Yamada {
560a9064fbSMasahiro Yamada 	if (!e1)
570a9064fbSMasahiro Yamada 		return e2;
580a9064fbSMasahiro Yamada 	return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
590a9064fbSMasahiro Yamada }
600a9064fbSMasahiro Yamada 
610a9064fbSMasahiro Yamada struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
620a9064fbSMasahiro Yamada {
630a9064fbSMasahiro Yamada 	if (!e1)
640a9064fbSMasahiro Yamada 		return e2;
650a9064fbSMasahiro Yamada 	return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
660a9064fbSMasahiro Yamada }
670a9064fbSMasahiro Yamada 
680a9064fbSMasahiro Yamada struct expr *expr_copy(const struct expr *org)
690a9064fbSMasahiro Yamada {
700a9064fbSMasahiro Yamada 	struct expr *e;
710a9064fbSMasahiro Yamada 
720a9064fbSMasahiro Yamada 	if (!org)
730a9064fbSMasahiro Yamada 		return NULL;
740a9064fbSMasahiro Yamada 
750a9064fbSMasahiro Yamada 	e = xmalloc(sizeof(*org));
760a9064fbSMasahiro Yamada 	memcpy(e, org, sizeof(*org));
770a9064fbSMasahiro Yamada 	switch (org->type) {
780a9064fbSMasahiro Yamada 	case E_SYMBOL:
790a9064fbSMasahiro Yamada 		e->left = org->left;
800a9064fbSMasahiro Yamada 		break;
810a9064fbSMasahiro Yamada 	case E_NOT:
820a9064fbSMasahiro Yamada 		e->left.expr = expr_copy(org->left.expr);
830a9064fbSMasahiro Yamada 		break;
840a9064fbSMasahiro Yamada 	case E_EQUAL:
850a9064fbSMasahiro Yamada 	case E_UNEQUAL:
860a9064fbSMasahiro Yamada 		e->left.sym = org->left.sym;
870a9064fbSMasahiro Yamada 		e->right.sym = org->right.sym;
880a9064fbSMasahiro Yamada 		break;
890a9064fbSMasahiro Yamada 	case E_AND:
900a9064fbSMasahiro Yamada 	case E_OR:
910a9064fbSMasahiro Yamada 	case E_LIST:
920a9064fbSMasahiro Yamada 		e->left.expr = expr_copy(org->left.expr);
930a9064fbSMasahiro Yamada 		e->right.expr = expr_copy(org->right.expr);
940a9064fbSMasahiro Yamada 		break;
950a9064fbSMasahiro Yamada 	default:
960a9064fbSMasahiro Yamada 		printf("can't copy type %d\n", e->type);
970a9064fbSMasahiro Yamada 		free(e);
980a9064fbSMasahiro Yamada 		e = NULL;
990a9064fbSMasahiro Yamada 		break;
1000a9064fbSMasahiro Yamada 	}
1010a9064fbSMasahiro Yamada 
1020a9064fbSMasahiro Yamada 	return e;
1030a9064fbSMasahiro Yamada }
1040a9064fbSMasahiro Yamada 
1050a9064fbSMasahiro Yamada void expr_free(struct expr *e)
1060a9064fbSMasahiro Yamada {
1070a9064fbSMasahiro Yamada 	if (!e)
1080a9064fbSMasahiro Yamada 		return;
1090a9064fbSMasahiro Yamada 
1100a9064fbSMasahiro Yamada 	switch (e->type) {
1110a9064fbSMasahiro Yamada 	case E_SYMBOL:
1120a9064fbSMasahiro Yamada 		break;
1130a9064fbSMasahiro Yamada 	case E_NOT:
1140a9064fbSMasahiro Yamada 		expr_free(e->left.expr);
1150a9064fbSMasahiro Yamada 		return;
1160a9064fbSMasahiro Yamada 	case E_EQUAL:
1170a9064fbSMasahiro Yamada 	case E_UNEQUAL:
1180a9064fbSMasahiro Yamada 		break;
1190a9064fbSMasahiro Yamada 	case E_OR:
1200a9064fbSMasahiro Yamada 	case E_AND:
1210a9064fbSMasahiro Yamada 		expr_free(e->left.expr);
1220a9064fbSMasahiro Yamada 		expr_free(e->right.expr);
1230a9064fbSMasahiro Yamada 		break;
1240a9064fbSMasahiro Yamada 	default:
1250a9064fbSMasahiro Yamada 		printf("how to free type %d?\n", e->type);
1260a9064fbSMasahiro Yamada 		break;
1270a9064fbSMasahiro Yamada 	}
1280a9064fbSMasahiro Yamada 	free(e);
1290a9064fbSMasahiro Yamada }
1300a9064fbSMasahiro Yamada 
1310a9064fbSMasahiro Yamada static int trans_count;
1320a9064fbSMasahiro Yamada 
1330a9064fbSMasahiro Yamada #define e1 (*ep1)
1340a9064fbSMasahiro Yamada #define e2 (*ep2)
1350a9064fbSMasahiro Yamada 
1360a9064fbSMasahiro Yamada static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
1370a9064fbSMasahiro Yamada {
1380a9064fbSMasahiro Yamada 	if (e1->type == type) {
1390a9064fbSMasahiro Yamada 		__expr_eliminate_eq(type, &e1->left.expr, &e2);
1400a9064fbSMasahiro Yamada 		__expr_eliminate_eq(type, &e1->right.expr, &e2);
1410a9064fbSMasahiro Yamada 		return;
1420a9064fbSMasahiro Yamada 	}
1430a9064fbSMasahiro Yamada 	if (e2->type == type) {
1440a9064fbSMasahiro Yamada 		__expr_eliminate_eq(type, &e1, &e2->left.expr);
1450a9064fbSMasahiro Yamada 		__expr_eliminate_eq(type, &e1, &e2->right.expr);
1460a9064fbSMasahiro Yamada 		return;
1470a9064fbSMasahiro Yamada 	}
1480a9064fbSMasahiro Yamada 	if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
1490a9064fbSMasahiro Yamada 	    e1->left.sym == e2->left.sym &&
1500a9064fbSMasahiro Yamada 	    (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
1510a9064fbSMasahiro Yamada 		return;
1520a9064fbSMasahiro Yamada 	if (!expr_eq(e1, e2))
1530a9064fbSMasahiro Yamada 		return;
1540a9064fbSMasahiro Yamada 	trans_count++;
1550a9064fbSMasahiro Yamada 	expr_free(e1); expr_free(e2);
1560a9064fbSMasahiro Yamada 	switch (type) {
1570a9064fbSMasahiro Yamada 	case E_OR:
1580a9064fbSMasahiro Yamada 		e1 = expr_alloc_symbol(&symbol_no);
1590a9064fbSMasahiro Yamada 		e2 = expr_alloc_symbol(&symbol_no);
1600a9064fbSMasahiro Yamada 		break;
1610a9064fbSMasahiro Yamada 	case E_AND:
1620a9064fbSMasahiro Yamada 		e1 = expr_alloc_symbol(&symbol_yes);
1630a9064fbSMasahiro Yamada 		e2 = expr_alloc_symbol(&symbol_yes);
1640a9064fbSMasahiro Yamada 		break;
1650a9064fbSMasahiro Yamada 	default:
1660a9064fbSMasahiro Yamada 		;
1670a9064fbSMasahiro Yamada 	}
1680a9064fbSMasahiro Yamada }
1690a9064fbSMasahiro Yamada 
1700a9064fbSMasahiro Yamada void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
1710a9064fbSMasahiro Yamada {
1720a9064fbSMasahiro Yamada 	if (!e1 || !e2)
1730a9064fbSMasahiro Yamada 		return;
1740a9064fbSMasahiro Yamada 	switch (e1->type) {
1750a9064fbSMasahiro Yamada 	case E_OR:
1760a9064fbSMasahiro Yamada 	case E_AND:
1770a9064fbSMasahiro Yamada 		__expr_eliminate_eq(e1->type, ep1, ep2);
1780a9064fbSMasahiro Yamada 	default:
1790a9064fbSMasahiro Yamada 		;
1800a9064fbSMasahiro Yamada 	}
1810a9064fbSMasahiro Yamada 	if (e1->type != e2->type) switch (e2->type) {
1820a9064fbSMasahiro Yamada 	case E_OR:
1830a9064fbSMasahiro Yamada 	case E_AND:
1840a9064fbSMasahiro Yamada 		__expr_eliminate_eq(e2->type, ep1, ep2);
1850a9064fbSMasahiro Yamada 	default:
1860a9064fbSMasahiro Yamada 		;
1870a9064fbSMasahiro Yamada 	}
1880a9064fbSMasahiro Yamada 	e1 = expr_eliminate_yn(e1);
1890a9064fbSMasahiro Yamada 	e2 = expr_eliminate_yn(e2);
1900a9064fbSMasahiro Yamada }
1910a9064fbSMasahiro Yamada 
1920a9064fbSMasahiro Yamada #undef e1
1930a9064fbSMasahiro Yamada #undef e2
1940a9064fbSMasahiro Yamada 
195*9b5f0b1dSMasahiro Yamada static int expr_eq(struct expr *e1, struct expr *e2)
1960a9064fbSMasahiro Yamada {
1970a9064fbSMasahiro Yamada 	int res, old_count;
1980a9064fbSMasahiro Yamada 
1990a9064fbSMasahiro Yamada 	if (e1->type != e2->type)
2000a9064fbSMasahiro Yamada 		return 0;
2010a9064fbSMasahiro Yamada 	switch (e1->type) {
2020a9064fbSMasahiro Yamada 	case E_EQUAL:
2030a9064fbSMasahiro Yamada 	case E_UNEQUAL:
2040a9064fbSMasahiro Yamada 		return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
2050a9064fbSMasahiro Yamada 	case E_SYMBOL:
2060a9064fbSMasahiro Yamada 		return e1->left.sym == e2->left.sym;
2070a9064fbSMasahiro Yamada 	case E_NOT:
2080a9064fbSMasahiro Yamada 		return expr_eq(e1->left.expr, e2->left.expr);
2090a9064fbSMasahiro Yamada 	case E_AND:
2100a9064fbSMasahiro Yamada 	case E_OR:
2110a9064fbSMasahiro Yamada 		e1 = expr_copy(e1);
2120a9064fbSMasahiro Yamada 		e2 = expr_copy(e2);
2130a9064fbSMasahiro Yamada 		old_count = trans_count;
2140a9064fbSMasahiro Yamada 		expr_eliminate_eq(&e1, &e2);
2150a9064fbSMasahiro Yamada 		res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
2160a9064fbSMasahiro Yamada 		       e1->left.sym == e2->left.sym);
2170a9064fbSMasahiro Yamada 		expr_free(e1);
2180a9064fbSMasahiro Yamada 		expr_free(e2);
2190a9064fbSMasahiro Yamada 		trans_count = old_count;
2200a9064fbSMasahiro Yamada 		return res;
2210a9064fbSMasahiro Yamada 	case E_LIST:
2220a9064fbSMasahiro Yamada 	case E_RANGE:
2230a9064fbSMasahiro Yamada 	case E_NONE:
2240a9064fbSMasahiro Yamada 		/* panic */;
2250a9064fbSMasahiro Yamada 	}
2260a9064fbSMasahiro Yamada 
2270a9064fbSMasahiro Yamada 	if (DEBUG_EXPR) {
2280a9064fbSMasahiro Yamada 		expr_fprint(e1, stdout);
2290a9064fbSMasahiro Yamada 		printf(" = ");
2300a9064fbSMasahiro Yamada 		expr_fprint(e2, stdout);
2310a9064fbSMasahiro Yamada 		printf(" ?\n");
2320a9064fbSMasahiro Yamada 	}
2330a9064fbSMasahiro Yamada 
2340a9064fbSMasahiro Yamada 	return 0;
2350a9064fbSMasahiro Yamada }
2360a9064fbSMasahiro Yamada 
237*9b5f0b1dSMasahiro Yamada static struct expr *expr_eliminate_yn(struct expr *e)
2380a9064fbSMasahiro Yamada {
2390a9064fbSMasahiro Yamada 	struct expr *tmp;
2400a9064fbSMasahiro Yamada 
2410a9064fbSMasahiro Yamada 	if (e) switch (e->type) {
2420a9064fbSMasahiro Yamada 	case E_AND:
2430a9064fbSMasahiro Yamada 		e->left.expr = expr_eliminate_yn(e->left.expr);
2440a9064fbSMasahiro Yamada 		e->right.expr = expr_eliminate_yn(e->right.expr);
2450a9064fbSMasahiro Yamada 		if (e->left.expr->type == E_SYMBOL) {
2460a9064fbSMasahiro Yamada 			if (e->left.expr->left.sym == &symbol_no) {
2470a9064fbSMasahiro Yamada 				expr_free(e->left.expr);
2480a9064fbSMasahiro Yamada 				expr_free(e->right.expr);
2490a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
2500a9064fbSMasahiro Yamada 				e->left.sym = &symbol_no;
2510a9064fbSMasahiro Yamada 				e->right.expr = NULL;
2520a9064fbSMasahiro Yamada 				return e;
2530a9064fbSMasahiro Yamada 			} else if (e->left.expr->left.sym == &symbol_yes) {
2540a9064fbSMasahiro Yamada 				free(e->left.expr);
2550a9064fbSMasahiro Yamada 				tmp = e->right.expr;
2560a9064fbSMasahiro Yamada 				*e = *(e->right.expr);
2570a9064fbSMasahiro Yamada 				free(tmp);
2580a9064fbSMasahiro Yamada 				return e;
2590a9064fbSMasahiro Yamada 			}
2600a9064fbSMasahiro Yamada 		}
2610a9064fbSMasahiro Yamada 		if (e->right.expr->type == E_SYMBOL) {
2620a9064fbSMasahiro Yamada 			if (e->right.expr->left.sym == &symbol_no) {
2630a9064fbSMasahiro Yamada 				expr_free(e->left.expr);
2640a9064fbSMasahiro Yamada 				expr_free(e->right.expr);
2650a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
2660a9064fbSMasahiro Yamada 				e->left.sym = &symbol_no;
2670a9064fbSMasahiro Yamada 				e->right.expr = NULL;
2680a9064fbSMasahiro Yamada 				return e;
2690a9064fbSMasahiro Yamada 			} else if (e->right.expr->left.sym == &symbol_yes) {
2700a9064fbSMasahiro Yamada 				free(e->right.expr);
2710a9064fbSMasahiro Yamada 				tmp = e->left.expr;
2720a9064fbSMasahiro Yamada 				*e = *(e->left.expr);
2730a9064fbSMasahiro Yamada 				free(tmp);
2740a9064fbSMasahiro Yamada 				return e;
2750a9064fbSMasahiro Yamada 			}
2760a9064fbSMasahiro Yamada 		}
2770a9064fbSMasahiro Yamada 		break;
2780a9064fbSMasahiro Yamada 	case E_OR:
2790a9064fbSMasahiro Yamada 		e->left.expr = expr_eliminate_yn(e->left.expr);
2800a9064fbSMasahiro Yamada 		e->right.expr = expr_eliminate_yn(e->right.expr);
2810a9064fbSMasahiro Yamada 		if (e->left.expr->type == E_SYMBOL) {
2820a9064fbSMasahiro Yamada 			if (e->left.expr->left.sym == &symbol_no) {
2830a9064fbSMasahiro Yamada 				free(e->left.expr);
2840a9064fbSMasahiro Yamada 				tmp = e->right.expr;
2850a9064fbSMasahiro Yamada 				*e = *(e->right.expr);
2860a9064fbSMasahiro Yamada 				free(tmp);
2870a9064fbSMasahiro Yamada 				return e;
2880a9064fbSMasahiro Yamada 			} else if (e->left.expr->left.sym == &symbol_yes) {
2890a9064fbSMasahiro Yamada 				expr_free(e->left.expr);
2900a9064fbSMasahiro Yamada 				expr_free(e->right.expr);
2910a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
2920a9064fbSMasahiro Yamada 				e->left.sym = &symbol_yes;
2930a9064fbSMasahiro Yamada 				e->right.expr = NULL;
2940a9064fbSMasahiro Yamada 				return e;
2950a9064fbSMasahiro Yamada 			}
2960a9064fbSMasahiro Yamada 		}
2970a9064fbSMasahiro Yamada 		if (e->right.expr->type == E_SYMBOL) {
2980a9064fbSMasahiro Yamada 			if (e->right.expr->left.sym == &symbol_no) {
2990a9064fbSMasahiro Yamada 				free(e->right.expr);
3000a9064fbSMasahiro Yamada 				tmp = e->left.expr;
3010a9064fbSMasahiro Yamada 				*e = *(e->left.expr);
3020a9064fbSMasahiro Yamada 				free(tmp);
3030a9064fbSMasahiro Yamada 				return e;
3040a9064fbSMasahiro Yamada 			} else if (e->right.expr->left.sym == &symbol_yes) {
3050a9064fbSMasahiro Yamada 				expr_free(e->left.expr);
3060a9064fbSMasahiro Yamada 				expr_free(e->right.expr);
3070a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
3080a9064fbSMasahiro Yamada 				e->left.sym = &symbol_yes;
3090a9064fbSMasahiro Yamada 				e->right.expr = NULL;
3100a9064fbSMasahiro Yamada 				return e;
3110a9064fbSMasahiro Yamada 			}
3120a9064fbSMasahiro Yamada 		}
3130a9064fbSMasahiro Yamada 		break;
3140a9064fbSMasahiro Yamada 	default:
3150a9064fbSMasahiro Yamada 		;
3160a9064fbSMasahiro Yamada 	}
3170a9064fbSMasahiro Yamada 	return e;
3180a9064fbSMasahiro Yamada }
3190a9064fbSMasahiro Yamada 
3200a9064fbSMasahiro Yamada /*
3210a9064fbSMasahiro Yamada  * bool FOO!=n => FOO
3220a9064fbSMasahiro Yamada  */
3230a9064fbSMasahiro Yamada struct expr *expr_trans_bool(struct expr *e)
3240a9064fbSMasahiro Yamada {
3250a9064fbSMasahiro Yamada 	if (!e)
3260a9064fbSMasahiro Yamada 		return NULL;
3270a9064fbSMasahiro Yamada 	switch (e->type) {
3280a9064fbSMasahiro Yamada 	case E_AND:
3290a9064fbSMasahiro Yamada 	case E_OR:
3300a9064fbSMasahiro Yamada 	case E_NOT:
3310a9064fbSMasahiro Yamada 		e->left.expr = expr_trans_bool(e->left.expr);
3320a9064fbSMasahiro Yamada 		e->right.expr = expr_trans_bool(e->right.expr);
3330a9064fbSMasahiro Yamada 		break;
3340a9064fbSMasahiro Yamada 	case E_UNEQUAL:
3350a9064fbSMasahiro Yamada 		// FOO!=n -> FOO
3360a9064fbSMasahiro Yamada 		if (e->left.sym->type == S_TRISTATE) {
3370a9064fbSMasahiro Yamada 			if (e->right.sym == &symbol_no) {
3380a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
3390a9064fbSMasahiro Yamada 				e->right.sym = NULL;
3400a9064fbSMasahiro Yamada 			}
3410a9064fbSMasahiro Yamada 		}
3420a9064fbSMasahiro Yamada 		break;
3430a9064fbSMasahiro Yamada 	default:
3440a9064fbSMasahiro Yamada 		;
3450a9064fbSMasahiro Yamada 	}
3460a9064fbSMasahiro Yamada 	return e;
3470a9064fbSMasahiro Yamada }
3480a9064fbSMasahiro Yamada 
3490a9064fbSMasahiro Yamada /*
3500a9064fbSMasahiro Yamada  * e1 || e2 -> ?
3510a9064fbSMasahiro Yamada  */
3520a9064fbSMasahiro Yamada static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
3530a9064fbSMasahiro Yamada {
3540a9064fbSMasahiro Yamada 	struct expr *tmp;
3550a9064fbSMasahiro Yamada 	struct symbol *sym1, *sym2;
3560a9064fbSMasahiro Yamada 
3570a9064fbSMasahiro Yamada 	if (expr_eq(e1, e2))
3580a9064fbSMasahiro Yamada 		return expr_copy(e1);
3590a9064fbSMasahiro Yamada 	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
3600a9064fbSMasahiro Yamada 		return NULL;
3610a9064fbSMasahiro Yamada 	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
3620a9064fbSMasahiro Yamada 		return NULL;
3630a9064fbSMasahiro Yamada 	if (e1->type == E_NOT) {
3640a9064fbSMasahiro Yamada 		tmp = e1->left.expr;
3650a9064fbSMasahiro Yamada 		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
3660a9064fbSMasahiro Yamada 			return NULL;
3670a9064fbSMasahiro Yamada 		sym1 = tmp->left.sym;
3680a9064fbSMasahiro Yamada 	} else
3690a9064fbSMasahiro Yamada 		sym1 = e1->left.sym;
3700a9064fbSMasahiro Yamada 	if (e2->type == E_NOT) {
3710a9064fbSMasahiro Yamada 		if (e2->left.expr->type != E_SYMBOL)
3720a9064fbSMasahiro Yamada 			return NULL;
3730a9064fbSMasahiro Yamada 		sym2 = e2->left.expr->left.sym;
3740a9064fbSMasahiro Yamada 	} else
3750a9064fbSMasahiro Yamada 		sym2 = e2->left.sym;
3760a9064fbSMasahiro Yamada 	if (sym1 != sym2)
3770a9064fbSMasahiro Yamada 		return NULL;
3780a9064fbSMasahiro Yamada 	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
3790a9064fbSMasahiro Yamada 		return NULL;
3800a9064fbSMasahiro Yamada 	if (sym1->type == S_TRISTATE) {
3810a9064fbSMasahiro Yamada 		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
3820a9064fbSMasahiro Yamada 		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
3830a9064fbSMasahiro Yamada 		     (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
3840a9064fbSMasahiro Yamada 			// (a='y') || (a='m') -> (a!='n')
3850a9064fbSMasahiro Yamada 			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
3860a9064fbSMasahiro Yamada 		}
3870a9064fbSMasahiro Yamada 		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
3880a9064fbSMasahiro Yamada 		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
3890a9064fbSMasahiro Yamada 		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
3900a9064fbSMasahiro Yamada 			// (a='y') || (a='n') -> (a!='m')
3910a9064fbSMasahiro Yamada 			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
3920a9064fbSMasahiro Yamada 		}
3930a9064fbSMasahiro Yamada 		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
3940a9064fbSMasahiro Yamada 		    ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
3950a9064fbSMasahiro Yamada 		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
3960a9064fbSMasahiro Yamada 			// (a='m') || (a='n') -> (a!='y')
3970a9064fbSMasahiro Yamada 			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
3980a9064fbSMasahiro Yamada 		}
3990a9064fbSMasahiro Yamada 	}
4000a9064fbSMasahiro Yamada 	if (sym1->type == S_BOOLEAN && sym1 == sym2) {
4010a9064fbSMasahiro Yamada 		if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
4020a9064fbSMasahiro Yamada 		    (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
4030a9064fbSMasahiro Yamada 			return expr_alloc_symbol(&symbol_yes);
4040a9064fbSMasahiro Yamada 	}
4050a9064fbSMasahiro Yamada 
4060a9064fbSMasahiro Yamada 	if (DEBUG_EXPR) {
4070a9064fbSMasahiro Yamada 		printf("optimize (");
4080a9064fbSMasahiro Yamada 		expr_fprint(e1, stdout);
4090a9064fbSMasahiro Yamada 		printf(") || (");
4100a9064fbSMasahiro Yamada 		expr_fprint(e2, stdout);
4110a9064fbSMasahiro Yamada 		printf(")?\n");
4120a9064fbSMasahiro Yamada 	}
4130a9064fbSMasahiro Yamada 	return NULL;
4140a9064fbSMasahiro Yamada }
4150a9064fbSMasahiro Yamada 
4160a9064fbSMasahiro Yamada static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
4170a9064fbSMasahiro Yamada {
4180a9064fbSMasahiro Yamada 	struct expr *tmp;
4190a9064fbSMasahiro Yamada 	struct symbol *sym1, *sym2;
4200a9064fbSMasahiro Yamada 
4210a9064fbSMasahiro Yamada 	if (expr_eq(e1, e2))
4220a9064fbSMasahiro Yamada 		return expr_copy(e1);
4230a9064fbSMasahiro Yamada 	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
4240a9064fbSMasahiro Yamada 		return NULL;
4250a9064fbSMasahiro Yamada 	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
4260a9064fbSMasahiro Yamada 		return NULL;
4270a9064fbSMasahiro Yamada 	if (e1->type == E_NOT) {
4280a9064fbSMasahiro Yamada 		tmp = e1->left.expr;
4290a9064fbSMasahiro Yamada 		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
4300a9064fbSMasahiro Yamada 			return NULL;
4310a9064fbSMasahiro Yamada 		sym1 = tmp->left.sym;
4320a9064fbSMasahiro Yamada 	} else
4330a9064fbSMasahiro Yamada 		sym1 = e1->left.sym;
4340a9064fbSMasahiro Yamada 	if (e2->type == E_NOT) {
4350a9064fbSMasahiro Yamada 		if (e2->left.expr->type != E_SYMBOL)
4360a9064fbSMasahiro Yamada 			return NULL;
4370a9064fbSMasahiro Yamada 		sym2 = e2->left.expr->left.sym;
4380a9064fbSMasahiro Yamada 	} else
4390a9064fbSMasahiro Yamada 		sym2 = e2->left.sym;
4400a9064fbSMasahiro Yamada 	if (sym1 != sym2)
4410a9064fbSMasahiro Yamada 		return NULL;
4420a9064fbSMasahiro Yamada 	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
4430a9064fbSMasahiro Yamada 		return NULL;
4440a9064fbSMasahiro Yamada 
4450a9064fbSMasahiro Yamada 	if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
4460a9064fbSMasahiro Yamada 	    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
4470a9064fbSMasahiro Yamada 		// (a) && (a='y') -> (a='y')
4480a9064fbSMasahiro Yamada 		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
4490a9064fbSMasahiro Yamada 
4500a9064fbSMasahiro Yamada 	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
4510a9064fbSMasahiro Yamada 	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
4520a9064fbSMasahiro Yamada 		// (a) && (a!='n') -> (a)
4530a9064fbSMasahiro Yamada 		return expr_alloc_symbol(sym1);
4540a9064fbSMasahiro Yamada 
4550a9064fbSMasahiro Yamada 	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
4560a9064fbSMasahiro Yamada 	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
4570a9064fbSMasahiro Yamada 		// (a) && (a!='m') -> (a='y')
4580a9064fbSMasahiro Yamada 		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
4590a9064fbSMasahiro Yamada 
4600a9064fbSMasahiro Yamada 	if (sym1->type == S_TRISTATE) {
4610a9064fbSMasahiro Yamada 		if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
4620a9064fbSMasahiro Yamada 			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
4630a9064fbSMasahiro Yamada 			sym2 = e1->right.sym;
4640a9064fbSMasahiro Yamada 			if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
4650a9064fbSMasahiro Yamada 				return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
4660a9064fbSMasahiro Yamada 							     : expr_alloc_symbol(&symbol_no);
4670a9064fbSMasahiro Yamada 		}
4680a9064fbSMasahiro Yamada 		if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
4690a9064fbSMasahiro Yamada 			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
4700a9064fbSMasahiro Yamada 			sym2 = e2->right.sym;
4710a9064fbSMasahiro Yamada 			if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
4720a9064fbSMasahiro Yamada 				return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
4730a9064fbSMasahiro Yamada 							     : expr_alloc_symbol(&symbol_no);
4740a9064fbSMasahiro Yamada 		}
4750a9064fbSMasahiro Yamada 		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
4760a9064fbSMasahiro Yamada 			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
4770a9064fbSMasahiro Yamada 			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
4780a9064fbSMasahiro Yamada 			// (a!='y') && (a!='n') -> (a='m')
4790a9064fbSMasahiro Yamada 			return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
4800a9064fbSMasahiro Yamada 
4810a9064fbSMasahiro Yamada 		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
4820a9064fbSMasahiro Yamada 			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
4830a9064fbSMasahiro Yamada 			    (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
4840a9064fbSMasahiro Yamada 			// (a!='y') && (a!='m') -> (a='n')
4850a9064fbSMasahiro Yamada 			return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
4860a9064fbSMasahiro Yamada 
4870a9064fbSMasahiro Yamada 		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
4880a9064fbSMasahiro Yamada 			   ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
4890a9064fbSMasahiro Yamada 			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
4900a9064fbSMasahiro Yamada 			// (a!='m') && (a!='n') -> (a='m')
4910a9064fbSMasahiro Yamada 			return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
4920a9064fbSMasahiro Yamada 
4930a9064fbSMasahiro Yamada 		if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
4940a9064fbSMasahiro Yamada 		    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
4950a9064fbSMasahiro Yamada 		    (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
4960a9064fbSMasahiro Yamada 		    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
4970a9064fbSMasahiro Yamada 			return NULL;
4980a9064fbSMasahiro Yamada 	}
4990a9064fbSMasahiro Yamada 
5000a9064fbSMasahiro Yamada 	if (DEBUG_EXPR) {
5010a9064fbSMasahiro Yamada 		printf("optimize (");
5020a9064fbSMasahiro Yamada 		expr_fprint(e1, stdout);
5030a9064fbSMasahiro Yamada 		printf(") && (");
5040a9064fbSMasahiro Yamada 		expr_fprint(e2, stdout);
5050a9064fbSMasahiro Yamada 		printf(")?\n");
5060a9064fbSMasahiro Yamada 	}
5070a9064fbSMasahiro Yamada 	return NULL;
5080a9064fbSMasahiro Yamada }
5090a9064fbSMasahiro Yamada 
5100a9064fbSMasahiro Yamada static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
5110a9064fbSMasahiro Yamada {
5120a9064fbSMasahiro Yamada #define e1 (*ep1)
5130a9064fbSMasahiro Yamada #define e2 (*ep2)
5140a9064fbSMasahiro Yamada 	struct expr *tmp;
5150a9064fbSMasahiro Yamada 
5160a9064fbSMasahiro Yamada 	if (e1->type == type) {
5170a9064fbSMasahiro Yamada 		expr_eliminate_dups1(type, &e1->left.expr, &e2);
5180a9064fbSMasahiro Yamada 		expr_eliminate_dups1(type, &e1->right.expr, &e2);
5190a9064fbSMasahiro Yamada 		return;
5200a9064fbSMasahiro Yamada 	}
5210a9064fbSMasahiro Yamada 	if (e2->type == type) {
5220a9064fbSMasahiro Yamada 		expr_eliminate_dups1(type, &e1, &e2->left.expr);
5230a9064fbSMasahiro Yamada 		expr_eliminate_dups1(type, &e1, &e2->right.expr);
5240a9064fbSMasahiro Yamada 		return;
5250a9064fbSMasahiro Yamada 	}
5260a9064fbSMasahiro Yamada 	if (e1 == e2)
5270a9064fbSMasahiro Yamada 		return;
5280a9064fbSMasahiro Yamada 
5290a9064fbSMasahiro Yamada 	switch (e1->type) {
5300a9064fbSMasahiro Yamada 	case E_OR: case E_AND:
5310a9064fbSMasahiro Yamada 		expr_eliminate_dups1(e1->type, &e1, &e1);
5320a9064fbSMasahiro Yamada 	default:
5330a9064fbSMasahiro Yamada 		;
5340a9064fbSMasahiro Yamada 	}
5350a9064fbSMasahiro Yamada 
5360a9064fbSMasahiro Yamada 	switch (type) {
5370a9064fbSMasahiro Yamada 	case E_OR:
5380a9064fbSMasahiro Yamada 		tmp = expr_join_or(e1, e2);
5390a9064fbSMasahiro Yamada 		if (tmp) {
5400a9064fbSMasahiro Yamada 			expr_free(e1); expr_free(e2);
5410a9064fbSMasahiro Yamada 			e1 = expr_alloc_symbol(&symbol_no);
5420a9064fbSMasahiro Yamada 			e2 = tmp;
5430a9064fbSMasahiro Yamada 			trans_count++;
5440a9064fbSMasahiro Yamada 		}
5450a9064fbSMasahiro Yamada 		break;
5460a9064fbSMasahiro Yamada 	case E_AND:
5470a9064fbSMasahiro Yamada 		tmp = expr_join_and(e1, e2);
5480a9064fbSMasahiro Yamada 		if (tmp) {
5490a9064fbSMasahiro Yamada 			expr_free(e1); expr_free(e2);
5500a9064fbSMasahiro Yamada 			e1 = expr_alloc_symbol(&symbol_yes);
5510a9064fbSMasahiro Yamada 			e2 = tmp;
5520a9064fbSMasahiro Yamada 			trans_count++;
5530a9064fbSMasahiro Yamada 		}
5540a9064fbSMasahiro Yamada 		break;
5550a9064fbSMasahiro Yamada 	default:
5560a9064fbSMasahiro Yamada 		;
5570a9064fbSMasahiro Yamada 	}
5580a9064fbSMasahiro Yamada #undef e1
5590a9064fbSMasahiro Yamada #undef e2
5600a9064fbSMasahiro Yamada }
5610a9064fbSMasahiro Yamada 
5620a9064fbSMasahiro Yamada static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)
5630a9064fbSMasahiro Yamada {
5640a9064fbSMasahiro Yamada #define e1 (*ep1)
5650a9064fbSMasahiro Yamada #define e2 (*ep2)
5660a9064fbSMasahiro Yamada 	struct expr *tmp, *tmp1, *tmp2;
5670a9064fbSMasahiro Yamada 
5680a9064fbSMasahiro Yamada 	if (e1->type == type) {
5690a9064fbSMasahiro Yamada 		expr_eliminate_dups2(type, &e1->left.expr, &e2);
5700a9064fbSMasahiro Yamada 		expr_eliminate_dups2(type, &e1->right.expr, &e2);
5710a9064fbSMasahiro Yamada 		return;
5720a9064fbSMasahiro Yamada 	}
5730a9064fbSMasahiro Yamada 	if (e2->type == type) {
5740a9064fbSMasahiro Yamada 		expr_eliminate_dups2(type, &e1, &e2->left.expr);
5750a9064fbSMasahiro Yamada 		expr_eliminate_dups2(type, &e1, &e2->right.expr);
5760a9064fbSMasahiro Yamada 	}
5770a9064fbSMasahiro Yamada 	if (e1 == e2)
5780a9064fbSMasahiro Yamada 		return;
5790a9064fbSMasahiro Yamada 
5800a9064fbSMasahiro Yamada 	switch (e1->type) {
5810a9064fbSMasahiro Yamada 	case E_OR:
5820a9064fbSMasahiro Yamada 		expr_eliminate_dups2(e1->type, &e1, &e1);
5830a9064fbSMasahiro Yamada 		// (FOO || BAR) && (!FOO && !BAR) -> n
5840a9064fbSMasahiro Yamada 		tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
5850a9064fbSMasahiro Yamada 		tmp2 = expr_copy(e2);
5860a9064fbSMasahiro Yamada 		tmp = expr_extract_eq_and(&tmp1, &tmp2);
5870a9064fbSMasahiro Yamada 		if (expr_is_yes(tmp1)) {
5880a9064fbSMasahiro Yamada 			expr_free(e1);
5890a9064fbSMasahiro Yamada 			e1 = expr_alloc_symbol(&symbol_no);
5900a9064fbSMasahiro Yamada 			trans_count++;
5910a9064fbSMasahiro Yamada 		}
5920a9064fbSMasahiro Yamada 		expr_free(tmp2);
5930a9064fbSMasahiro Yamada 		expr_free(tmp1);
5940a9064fbSMasahiro Yamada 		expr_free(tmp);
5950a9064fbSMasahiro Yamada 		break;
5960a9064fbSMasahiro Yamada 	case E_AND:
5970a9064fbSMasahiro Yamada 		expr_eliminate_dups2(e1->type, &e1, &e1);
5980a9064fbSMasahiro Yamada 		// (FOO && BAR) || (!FOO || !BAR) -> y
5990a9064fbSMasahiro Yamada 		tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
6000a9064fbSMasahiro Yamada 		tmp2 = expr_copy(e2);
6010a9064fbSMasahiro Yamada 		tmp = expr_extract_eq_or(&tmp1, &tmp2);
6020a9064fbSMasahiro Yamada 		if (expr_is_no(tmp1)) {
6030a9064fbSMasahiro Yamada 			expr_free(e1);
6040a9064fbSMasahiro Yamada 			e1 = expr_alloc_symbol(&symbol_yes);
6050a9064fbSMasahiro Yamada 			trans_count++;
6060a9064fbSMasahiro Yamada 		}
6070a9064fbSMasahiro Yamada 		expr_free(tmp2);
6080a9064fbSMasahiro Yamada 		expr_free(tmp1);
6090a9064fbSMasahiro Yamada 		expr_free(tmp);
6100a9064fbSMasahiro Yamada 		break;
6110a9064fbSMasahiro Yamada 	default:
6120a9064fbSMasahiro Yamada 		;
6130a9064fbSMasahiro Yamada 	}
6140a9064fbSMasahiro Yamada #undef e1
6150a9064fbSMasahiro Yamada #undef e2
6160a9064fbSMasahiro Yamada }
6170a9064fbSMasahiro Yamada 
6180a9064fbSMasahiro Yamada struct expr *expr_eliminate_dups(struct expr *e)
6190a9064fbSMasahiro Yamada {
6200a9064fbSMasahiro Yamada 	int oldcount;
6210a9064fbSMasahiro Yamada 	if (!e)
6220a9064fbSMasahiro Yamada 		return e;
6230a9064fbSMasahiro Yamada 
6240a9064fbSMasahiro Yamada 	oldcount = trans_count;
6250a9064fbSMasahiro Yamada 	while (1) {
6260a9064fbSMasahiro Yamada 		trans_count = 0;
6270a9064fbSMasahiro Yamada 		switch (e->type) {
6280a9064fbSMasahiro Yamada 		case E_OR: case E_AND:
6290a9064fbSMasahiro Yamada 			expr_eliminate_dups1(e->type, &e, &e);
6300a9064fbSMasahiro Yamada 			expr_eliminate_dups2(e->type, &e, &e);
6310a9064fbSMasahiro Yamada 		default:
6320a9064fbSMasahiro Yamada 			;
6330a9064fbSMasahiro Yamada 		}
6340a9064fbSMasahiro Yamada 		if (!trans_count)
6350a9064fbSMasahiro Yamada 			break;
6360a9064fbSMasahiro Yamada 		e = expr_eliminate_yn(e);
6370a9064fbSMasahiro Yamada 	}
6380a9064fbSMasahiro Yamada 	trans_count = oldcount;
6390a9064fbSMasahiro Yamada 	return e;
6400a9064fbSMasahiro Yamada }
6410a9064fbSMasahiro Yamada 
6420a9064fbSMasahiro Yamada struct expr *expr_transform(struct expr *e)
6430a9064fbSMasahiro Yamada {
6440a9064fbSMasahiro Yamada 	struct expr *tmp;
6450a9064fbSMasahiro Yamada 
6460a9064fbSMasahiro Yamada 	if (!e)
6470a9064fbSMasahiro Yamada 		return NULL;
6480a9064fbSMasahiro Yamada 	switch (e->type) {
6490a9064fbSMasahiro Yamada 	case E_EQUAL:
6500a9064fbSMasahiro Yamada 	case E_UNEQUAL:
6510a9064fbSMasahiro Yamada 	case E_SYMBOL:
6520a9064fbSMasahiro Yamada 	case E_LIST:
6530a9064fbSMasahiro Yamada 		break;
6540a9064fbSMasahiro Yamada 	default:
6550a9064fbSMasahiro Yamada 		e->left.expr = expr_transform(e->left.expr);
6560a9064fbSMasahiro Yamada 		e->right.expr = expr_transform(e->right.expr);
6570a9064fbSMasahiro Yamada 	}
6580a9064fbSMasahiro Yamada 
6590a9064fbSMasahiro Yamada 	switch (e->type) {
6600a9064fbSMasahiro Yamada 	case E_EQUAL:
6610a9064fbSMasahiro Yamada 		if (e->left.sym->type != S_BOOLEAN)
6620a9064fbSMasahiro Yamada 			break;
6630a9064fbSMasahiro Yamada 		if (e->right.sym == &symbol_no) {
6640a9064fbSMasahiro Yamada 			e->type = E_NOT;
6650a9064fbSMasahiro Yamada 			e->left.expr = expr_alloc_symbol(e->left.sym);
6660a9064fbSMasahiro Yamada 			e->right.sym = NULL;
6670a9064fbSMasahiro Yamada 			break;
6680a9064fbSMasahiro Yamada 		}
6690a9064fbSMasahiro Yamada 		if (e->right.sym == &symbol_mod) {
6700a9064fbSMasahiro Yamada 			printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
6710a9064fbSMasahiro Yamada 			e->type = E_SYMBOL;
6720a9064fbSMasahiro Yamada 			e->left.sym = &symbol_no;
6730a9064fbSMasahiro Yamada 			e->right.sym = NULL;
6740a9064fbSMasahiro Yamada 			break;
6750a9064fbSMasahiro Yamada 		}
6760a9064fbSMasahiro Yamada 		if (e->right.sym == &symbol_yes) {
6770a9064fbSMasahiro Yamada 			e->type = E_SYMBOL;
6780a9064fbSMasahiro Yamada 			e->right.sym = NULL;
6790a9064fbSMasahiro Yamada 			break;
6800a9064fbSMasahiro Yamada 		}
6810a9064fbSMasahiro Yamada 		break;
6820a9064fbSMasahiro Yamada 	case E_UNEQUAL:
6830a9064fbSMasahiro Yamada 		if (e->left.sym->type != S_BOOLEAN)
6840a9064fbSMasahiro Yamada 			break;
6850a9064fbSMasahiro Yamada 		if (e->right.sym == &symbol_no) {
6860a9064fbSMasahiro Yamada 			e->type = E_SYMBOL;
6870a9064fbSMasahiro Yamada 			e->right.sym = NULL;
6880a9064fbSMasahiro Yamada 			break;
6890a9064fbSMasahiro Yamada 		}
6900a9064fbSMasahiro Yamada 		if (e->right.sym == &symbol_mod) {
6910a9064fbSMasahiro Yamada 			printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
6920a9064fbSMasahiro Yamada 			e->type = E_SYMBOL;
6930a9064fbSMasahiro Yamada 			e->left.sym = &symbol_yes;
6940a9064fbSMasahiro Yamada 			e->right.sym = NULL;
6950a9064fbSMasahiro Yamada 			break;
6960a9064fbSMasahiro Yamada 		}
6970a9064fbSMasahiro Yamada 		if (e->right.sym == &symbol_yes) {
6980a9064fbSMasahiro Yamada 			e->type = E_NOT;
6990a9064fbSMasahiro Yamada 			e->left.expr = expr_alloc_symbol(e->left.sym);
7000a9064fbSMasahiro Yamada 			e->right.sym = NULL;
7010a9064fbSMasahiro Yamada 			break;
7020a9064fbSMasahiro Yamada 		}
7030a9064fbSMasahiro Yamada 		break;
7040a9064fbSMasahiro Yamada 	case E_NOT:
7050a9064fbSMasahiro Yamada 		switch (e->left.expr->type) {
7060a9064fbSMasahiro Yamada 		case E_NOT:
7070a9064fbSMasahiro Yamada 			// !!a -> a
7080a9064fbSMasahiro Yamada 			tmp = e->left.expr->left.expr;
7090a9064fbSMasahiro Yamada 			free(e->left.expr);
7100a9064fbSMasahiro Yamada 			free(e);
7110a9064fbSMasahiro Yamada 			e = tmp;
7120a9064fbSMasahiro Yamada 			e = expr_transform(e);
7130a9064fbSMasahiro Yamada 			break;
7140a9064fbSMasahiro Yamada 		case E_EQUAL:
7150a9064fbSMasahiro Yamada 		case E_UNEQUAL:
7160a9064fbSMasahiro Yamada 			// !a='x' -> a!='x'
7170a9064fbSMasahiro Yamada 			tmp = e->left.expr;
7180a9064fbSMasahiro Yamada 			free(e);
7190a9064fbSMasahiro Yamada 			e = tmp;
7200a9064fbSMasahiro Yamada 			e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
7210a9064fbSMasahiro Yamada 			break;
7220a9064fbSMasahiro Yamada 		case E_OR:
7230a9064fbSMasahiro Yamada 			// !(a || b) -> !a && !b
7240a9064fbSMasahiro Yamada 			tmp = e->left.expr;
7250a9064fbSMasahiro Yamada 			e->type = E_AND;
7260a9064fbSMasahiro Yamada 			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
7270a9064fbSMasahiro Yamada 			tmp->type = E_NOT;
7280a9064fbSMasahiro Yamada 			tmp->right.expr = NULL;
7290a9064fbSMasahiro Yamada 			e = expr_transform(e);
7300a9064fbSMasahiro Yamada 			break;
7310a9064fbSMasahiro Yamada 		case E_AND:
7320a9064fbSMasahiro Yamada 			// !(a && b) -> !a || !b
7330a9064fbSMasahiro Yamada 			tmp = e->left.expr;
7340a9064fbSMasahiro Yamada 			e->type = E_OR;
7350a9064fbSMasahiro Yamada 			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
7360a9064fbSMasahiro Yamada 			tmp->type = E_NOT;
7370a9064fbSMasahiro Yamada 			tmp->right.expr = NULL;
7380a9064fbSMasahiro Yamada 			e = expr_transform(e);
7390a9064fbSMasahiro Yamada 			break;
7400a9064fbSMasahiro Yamada 		case E_SYMBOL:
7410a9064fbSMasahiro Yamada 			if (e->left.expr->left.sym == &symbol_yes) {
7420a9064fbSMasahiro Yamada 				// !'y' -> 'n'
7430a9064fbSMasahiro Yamada 				tmp = e->left.expr;
7440a9064fbSMasahiro Yamada 				free(e);
7450a9064fbSMasahiro Yamada 				e = tmp;
7460a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
7470a9064fbSMasahiro Yamada 				e->left.sym = &symbol_no;
7480a9064fbSMasahiro Yamada 				break;
7490a9064fbSMasahiro Yamada 			}
7500a9064fbSMasahiro Yamada 			if (e->left.expr->left.sym == &symbol_mod) {
7510a9064fbSMasahiro Yamada 				// !'m' -> 'm'
7520a9064fbSMasahiro Yamada 				tmp = e->left.expr;
7530a9064fbSMasahiro Yamada 				free(e);
7540a9064fbSMasahiro Yamada 				e = tmp;
7550a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
7560a9064fbSMasahiro Yamada 				e->left.sym = &symbol_mod;
7570a9064fbSMasahiro Yamada 				break;
7580a9064fbSMasahiro Yamada 			}
7590a9064fbSMasahiro Yamada 			if (e->left.expr->left.sym == &symbol_no) {
7600a9064fbSMasahiro Yamada 				// !'n' -> 'y'
7610a9064fbSMasahiro Yamada 				tmp = e->left.expr;
7620a9064fbSMasahiro Yamada 				free(e);
7630a9064fbSMasahiro Yamada 				e = tmp;
7640a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
7650a9064fbSMasahiro Yamada 				e->left.sym = &symbol_yes;
7660a9064fbSMasahiro Yamada 				break;
7670a9064fbSMasahiro Yamada 			}
7680a9064fbSMasahiro Yamada 			break;
7690a9064fbSMasahiro Yamada 		default:
7700a9064fbSMasahiro Yamada 			;
7710a9064fbSMasahiro Yamada 		}
7720a9064fbSMasahiro Yamada 		break;
7730a9064fbSMasahiro Yamada 	default:
7740a9064fbSMasahiro Yamada 		;
7750a9064fbSMasahiro Yamada 	}
7760a9064fbSMasahiro Yamada 	return e;
7770a9064fbSMasahiro Yamada }
7780a9064fbSMasahiro Yamada 
7790a9064fbSMasahiro Yamada int expr_contains_symbol(struct expr *dep, struct symbol *sym)
7800a9064fbSMasahiro Yamada {
7810a9064fbSMasahiro Yamada 	if (!dep)
7820a9064fbSMasahiro Yamada 		return 0;
7830a9064fbSMasahiro Yamada 
7840a9064fbSMasahiro Yamada 	switch (dep->type) {
7850a9064fbSMasahiro Yamada 	case E_AND:
7860a9064fbSMasahiro Yamada 	case E_OR:
7870a9064fbSMasahiro Yamada 		return expr_contains_symbol(dep->left.expr, sym) ||
7880a9064fbSMasahiro Yamada 		       expr_contains_symbol(dep->right.expr, sym);
7890a9064fbSMasahiro Yamada 	case E_SYMBOL:
7900a9064fbSMasahiro Yamada 		return dep->left.sym == sym;
7910a9064fbSMasahiro Yamada 	case E_EQUAL:
7920a9064fbSMasahiro Yamada 	case E_UNEQUAL:
7930a9064fbSMasahiro Yamada 		return dep->left.sym == sym ||
7940a9064fbSMasahiro Yamada 		       dep->right.sym == sym;
7950a9064fbSMasahiro Yamada 	case E_NOT:
7960a9064fbSMasahiro Yamada 		return expr_contains_symbol(dep->left.expr, sym);
7970a9064fbSMasahiro Yamada 	default:
7980a9064fbSMasahiro Yamada 		;
7990a9064fbSMasahiro Yamada 	}
8000a9064fbSMasahiro Yamada 	return 0;
8010a9064fbSMasahiro Yamada }
8020a9064fbSMasahiro Yamada 
8030a9064fbSMasahiro Yamada bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
8040a9064fbSMasahiro Yamada {
8050a9064fbSMasahiro Yamada 	if (!dep)
8060a9064fbSMasahiro Yamada 		return false;
8070a9064fbSMasahiro Yamada 
8080a9064fbSMasahiro Yamada 	switch (dep->type) {
8090a9064fbSMasahiro Yamada 	case E_AND:
8100a9064fbSMasahiro Yamada 		return expr_depends_symbol(dep->left.expr, sym) ||
8110a9064fbSMasahiro Yamada 		       expr_depends_symbol(dep->right.expr, sym);
8120a9064fbSMasahiro Yamada 	case E_SYMBOL:
8130a9064fbSMasahiro Yamada 		return dep->left.sym == sym;
8140a9064fbSMasahiro Yamada 	case E_EQUAL:
8150a9064fbSMasahiro Yamada 		if (dep->left.sym == sym) {
8160a9064fbSMasahiro Yamada 			if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
8170a9064fbSMasahiro Yamada 				return true;
8180a9064fbSMasahiro Yamada 		}
8190a9064fbSMasahiro Yamada 		break;
8200a9064fbSMasahiro Yamada 	case E_UNEQUAL:
8210a9064fbSMasahiro Yamada 		if (dep->left.sym == sym) {
8220a9064fbSMasahiro Yamada 			if (dep->right.sym == &symbol_no)
8230a9064fbSMasahiro Yamada 				return true;
8240a9064fbSMasahiro Yamada 		}
8250a9064fbSMasahiro Yamada 		break;
8260a9064fbSMasahiro Yamada 	default:
8270a9064fbSMasahiro Yamada 		;
8280a9064fbSMasahiro Yamada 	}
8290a9064fbSMasahiro Yamada  	return false;
8300a9064fbSMasahiro Yamada }
8310a9064fbSMasahiro Yamada 
832*9b5f0b1dSMasahiro Yamada static struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)
8330a9064fbSMasahiro Yamada {
8340a9064fbSMasahiro Yamada 	struct expr *tmp = NULL;
8350a9064fbSMasahiro Yamada 	expr_extract_eq(E_AND, &tmp, ep1, ep2);
8360a9064fbSMasahiro Yamada 	if (tmp) {
8370a9064fbSMasahiro Yamada 		*ep1 = expr_eliminate_yn(*ep1);
8380a9064fbSMasahiro Yamada 		*ep2 = expr_eliminate_yn(*ep2);
8390a9064fbSMasahiro Yamada 	}
8400a9064fbSMasahiro Yamada 	return tmp;
8410a9064fbSMasahiro Yamada }
8420a9064fbSMasahiro Yamada 
843*9b5f0b1dSMasahiro Yamada static struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)
8440a9064fbSMasahiro Yamada {
8450a9064fbSMasahiro Yamada 	struct expr *tmp = NULL;
8460a9064fbSMasahiro Yamada 	expr_extract_eq(E_OR, &tmp, ep1, ep2);
8470a9064fbSMasahiro Yamada 	if (tmp) {
8480a9064fbSMasahiro Yamada 		*ep1 = expr_eliminate_yn(*ep1);
8490a9064fbSMasahiro Yamada 		*ep2 = expr_eliminate_yn(*ep2);
8500a9064fbSMasahiro Yamada 	}
8510a9064fbSMasahiro Yamada 	return tmp;
8520a9064fbSMasahiro Yamada }
8530a9064fbSMasahiro Yamada 
854*9b5f0b1dSMasahiro Yamada static void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)
8550a9064fbSMasahiro Yamada {
8560a9064fbSMasahiro Yamada #define e1 (*ep1)
8570a9064fbSMasahiro Yamada #define e2 (*ep2)
8580a9064fbSMasahiro Yamada 	if (e1->type == type) {
8590a9064fbSMasahiro Yamada 		expr_extract_eq(type, ep, &e1->left.expr, &e2);
8600a9064fbSMasahiro Yamada 		expr_extract_eq(type, ep, &e1->right.expr, &e2);
8610a9064fbSMasahiro Yamada 		return;
8620a9064fbSMasahiro Yamada 	}
8630a9064fbSMasahiro Yamada 	if (e2->type == type) {
8640a9064fbSMasahiro Yamada 		expr_extract_eq(type, ep, ep1, &e2->left.expr);
8650a9064fbSMasahiro Yamada 		expr_extract_eq(type, ep, ep1, &e2->right.expr);
8660a9064fbSMasahiro Yamada 		return;
8670a9064fbSMasahiro Yamada 	}
8680a9064fbSMasahiro Yamada 	if (expr_eq(e1, e2)) {
8690a9064fbSMasahiro Yamada 		*ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;
8700a9064fbSMasahiro Yamada 		expr_free(e2);
8710a9064fbSMasahiro Yamada 		if (type == E_AND) {
8720a9064fbSMasahiro Yamada 			e1 = expr_alloc_symbol(&symbol_yes);
8730a9064fbSMasahiro Yamada 			e2 = expr_alloc_symbol(&symbol_yes);
8740a9064fbSMasahiro Yamada 		} else if (type == E_OR) {
8750a9064fbSMasahiro Yamada 			e1 = expr_alloc_symbol(&symbol_no);
8760a9064fbSMasahiro Yamada 			e2 = expr_alloc_symbol(&symbol_no);
8770a9064fbSMasahiro Yamada 		}
8780a9064fbSMasahiro Yamada 	}
8790a9064fbSMasahiro Yamada #undef e1
8800a9064fbSMasahiro Yamada #undef e2
8810a9064fbSMasahiro Yamada }
8820a9064fbSMasahiro Yamada 
8830a9064fbSMasahiro Yamada struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
8840a9064fbSMasahiro Yamada {
8850a9064fbSMasahiro Yamada 	struct expr *e1, *e2;
8860a9064fbSMasahiro Yamada 
8870a9064fbSMasahiro Yamada 	if (!e) {
8880a9064fbSMasahiro Yamada 		e = expr_alloc_symbol(sym);
8890a9064fbSMasahiro Yamada 		if (type == E_UNEQUAL)
8900a9064fbSMasahiro Yamada 			e = expr_alloc_one(E_NOT, e);
8910a9064fbSMasahiro Yamada 		return e;
8920a9064fbSMasahiro Yamada 	}
8930a9064fbSMasahiro Yamada 	switch (e->type) {
8940a9064fbSMasahiro Yamada 	case E_AND:
8950a9064fbSMasahiro Yamada 		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
8960a9064fbSMasahiro Yamada 		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
8970a9064fbSMasahiro Yamada 		if (sym == &symbol_yes)
8980a9064fbSMasahiro Yamada 			e = expr_alloc_two(E_AND, e1, e2);
8990a9064fbSMasahiro Yamada 		if (sym == &symbol_no)
9000a9064fbSMasahiro Yamada 			e = expr_alloc_two(E_OR, e1, e2);
9010a9064fbSMasahiro Yamada 		if (type == E_UNEQUAL)
9020a9064fbSMasahiro Yamada 			e = expr_alloc_one(E_NOT, e);
9030a9064fbSMasahiro Yamada 		return e;
9040a9064fbSMasahiro Yamada 	case E_OR:
9050a9064fbSMasahiro Yamada 		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
9060a9064fbSMasahiro Yamada 		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
9070a9064fbSMasahiro Yamada 		if (sym == &symbol_yes)
9080a9064fbSMasahiro Yamada 			e = expr_alloc_two(E_OR, e1, e2);
9090a9064fbSMasahiro Yamada 		if (sym == &symbol_no)
9100a9064fbSMasahiro Yamada 			e = expr_alloc_two(E_AND, e1, e2);
9110a9064fbSMasahiro Yamada 		if (type == E_UNEQUAL)
9120a9064fbSMasahiro Yamada 			e = expr_alloc_one(E_NOT, e);
9130a9064fbSMasahiro Yamada 		return e;
9140a9064fbSMasahiro Yamada 	case E_NOT:
9150a9064fbSMasahiro Yamada 		return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
9160a9064fbSMasahiro Yamada 	case E_UNEQUAL:
9170a9064fbSMasahiro Yamada 	case E_EQUAL:
9180a9064fbSMasahiro Yamada 		if (type == E_EQUAL) {
9190a9064fbSMasahiro Yamada 			if (sym == &symbol_yes)
9200a9064fbSMasahiro Yamada 				return expr_copy(e);
9210a9064fbSMasahiro Yamada 			if (sym == &symbol_mod)
9220a9064fbSMasahiro Yamada 				return expr_alloc_symbol(&symbol_no);
9230a9064fbSMasahiro Yamada 			if (sym == &symbol_no)
9240a9064fbSMasahiro Yamada 				return expr_alloc_one(E_NOT, expr_copy(e));
9250a9064fbSMasahiro Yamada 		} else {
9260a9064fbSMasahiro Yamada 			if (sym == &symbol_yes)
9270a9064fbSMasahiro Yamada 				return expr_alloc_one(E_NOT, expr_copy(e));
9280a9064fbSMasahiro Yamada 			if (sym == &symbol_mod)
9290a9064fbSMasahiro Yamada 				return expr_alloc_symbol(&symbol_yes);
9300a9064fbSMasahiro Yamada 			if (sym == &symbol_no)
9310a9064fbSMasahiro Yamada 				return expr_copy(e);
9320a9064fbSMasahiro Yamada 		}
9330a9064fbSMasahiro Yamada 		break;
9340a9064fbSMasahiro Yamada 	case E_SYMBOL:
9350a9064fbSMasahiro Yamada 		return expr_alloc_comp(type, e->left.sym, sym);
9360a9064fbSMasahiro Yamada 	case E_LIST:
9370a9064fbSMasahiro Yamada 	case E_RANGE:
9380a9064fbSMasahiro Yamada 	case E_NONE:
9390a9064fbSMasahiro Yamada 		/* panic */;
9400a9064fbSMasahiro Yamada 	}
9410a9064fbSMasahiro Yamada 	return NULL;
9420a9064fbSMasahiro Yamada }
9430a9064fbSMasahiro Yamada 
9440a9064fbSMasahiro Yamada tristate expr_calc_value(struct expr *e)
9450a9064fbSMasahiro Yamada {
9460a9064fbSMasahiro Yamada 	tristate val1, val2;
9470a9064fbSMasahiro Yamada 	const char *str1, *str2;
9480a9064fbSMasahiro Yamada 
9490a9064fbSMasahiro Yamada 	if (!e)
9500a9064fbSMasahiro Yamada 		return yes;
9510a9064fbSMasahiro Yamada 
9520a9064fbSMasahiro Yamada 	switch (e->type) {
9530a9064fbSMasahiro Yamada 	case E_SYMBOL:
9540a9064fbSMasahiro Yamada 		sym_calc_value(e->left.sym);
9550a9064fbSMasahiro Yamada 		return e->left.sym->curr.tri;
9560a9064fbSMasahiro Yamada 	case E_AND:
9570a9064fbSMasahiro Yamada 		val1 = expr_calc_value(e->left.expr);
9580a9064fbSMasahiro Yamada 		val2 = expr_calc_value(e->right.expr);
9590a9064fbSMasahiro Yamada 		return EXPR_AND(val1, val2);
9600a9064fbSMasahiro Yamada 	case E_OR:
9610a9064fbSMasahiro Yamada 		val1 = expr_calc_value(e->left.expr);
9620a9064fbSMasahiro Yamada 		val2 = expr_calc_value(e->right.expr);
9630a9064fbSMasahiro Yamada 		return EXPR_OR(val1, val2);
9640a9064fbSMasahiro Yamada 	case E_NOT:
9650a9064fbSMasahiro Yamada 		val1 = expr_calc_value(e->left.expr);
9660a9064fbSMasahiro Yamada 		return EXPR_NOT(val1);
9670a9064fbSMasahiro Yamada 	case E_EQUAL:
9680a9064fbSMasahiro Yamada 		sym_calc_value(e->left.sym);
9690a9064fbSMasahiro Yamada 		sym_calc_value(e->right.sym);
9700a9064fbSMasahiro Yamada 		str1 = sym_get_string_value(e->left.sym);
9710a9064fbSMasahiro Yamada 		str2 = sym_get_string_value(e->right.sym);
9720a9064fbSMasahiro Yamada 		return !strcmp(str1, str2) ? yes : no;
9730a9064fbSMasahiro Yamada 	case E_UNEQUAL:
9740a9064fbSMasahiro Yamada 		sym_calc_value(e->left.sym);
9750a9064fbSMasahiro Yamada 		sym_calc_value(e->right.sym);
9760a9064fbSMasahiro Yamada 		str1 = sym_get_string_value(e->left.sym);
9770a9064fbSMasahiro Yamada 		str2 = sym_get_string_value(e->right.sym);
9780a9064fbSMasahiro Yamada 		return !strcmp(str1, str2) ? no : yes;
9790a9064fbSMasahiro Yamada 	default:
9800a9064fbSMasahiro Yamada 		printf("expr_calc_value: %d?\n", e->type);
9810a9064fbSMasahiro Yamada 		return no;
9820a9064fbSMasahiro Yamada 	}
9830a9064fbSMasahiro Yamada }
9840a9064fbSMasahiro Yamada 
985*9b5f0b1dSMasahiro Yamada static int expr_compare_type(enum expr_type t1, enum expr_type t2)
9860a9064fbSMasahiro Yamada {
9870a9064fbSMasahiro Yamada 	if (t1 == t2)
9880a9064fbSMasahiro Yamada 		return 0;
9890a9064fbSMasahiro Yamada 	switch (t1) {
9900a9064fbSMasahiro Yamada 	case E_EQUAL:
9910a9064fbSMasahiro Yamada 	case E_UNEQUAL:
9920a9064fbSMasahiro Yamada 		if (t2 == E_NOT)
9930a9064fbSMasahiro Yamada 			return 1;
9940a9064fbSMasahiro Yamada 	case E_NOT:
9950a9064fbSMasahiro Yamada 		if (t2 == E_AND)
9960a9064fbSMasahiro Yamada 			return 1;
9970a9064fbSMasahiro Yamada 	case E_AND:
9980a9064fbSMasahiro Yamada 		if (t2 == E_OR)
9990a9064fbSMasahiro Yamada 			return 1;
10000a9064fbSMasahiro Yamada 	case E_OR:
10010a9064fbSMasahiro Yamada 		if (t2 == E_LIST)
10020a9064fbSMasahiro Yamada 			return 1;
10030a9064fbSMasahiro Yamada 	case E_LIST:
10040a9064fbSMasahiro Yamada 		if (t2 == 0)
10050a9064fbSMasahiro Yamada 			return 1;
10060a9064fbSMasahiro Yamada 	default:
10070a9064fbSMasahiro Yamada 		return -1;
10080a9064fbSMasahiro Yamada 	}
10090a9064fbSMasahiro Yamada 	printf("[%dgt%d?]", t1, t2);
10100a9064fbSMasahiro Yamada 	return 0;
10110a9064fbSMasahiro Yamada }
10120a9064fbSMasahiro Yamada 
10130a9064fbSMasahiro Yamada static inline struct expr *
10140a9064fbSMasahiro Yamada expr_get_leftmost_symbol(const struct expr *e)
10150a9064fbSMasahiro Yamada {
10160a9064fbSMasahiro Yamada 
10170a9064fbSMasahiro Yamada 	if (e == NULL)
10180a9064fbSMasahiro Yamada 		return NULL;
10190a9064fbSMasahiro Yamada 
10200a9064fbSMasahiro Yamada 	while (e->type != E_SYMBOL)
10210a9064fbSMasahiro Yamada 		e = e->left.expr;
10220a9064fbSMasahiro Yamada 
10230a9064fbSMasahiro Yamada 	return expr_copy(e);
10240a9064fbSMasahiro Yamada }
10250a9064fbSMasahiro Yamada 
10260a9064fbSMasahiro Yamada /*
10270a9064fbSMasahiro Yamada  * Given expression `e1' and `e2', returns the leaf of the longest
10280a9064fbSMasahiro Yamada  * sub-expression of `e1' not containing 'e2.
10290a9064fbSMasahiro Yamada  */
10300a9064fbSMasahiro Yamada struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2)
10310a9064fbSMasahiro Yamada {
10320a9064fbSMasahiro Yamada 	struct expr *ret;
10330a9064fbSMasahiro Yamada 
10340a9064fbSMasahiro Yamada 	switch (e1->type) {
10350a9064fbSMasahiro Yamada 	case E_OR:
10360a9064fbSMasahiro Yamada 		return expr_alloc_and(
10370a9064fbSMasahiro Yamada 		    expr_simplify_unmet_dep(e1->left.expr, e2),
10380a9064fbSMasahiro Yamada 		    expr_simplify_unmet_dep(e1->right.expr, e2));
10390a9064fbSMasahiro Yamada 	case E_AND: {
10400a9064fbSMasahiro Yamada 		struct expr *e;
10410a9064fbSMasahiro Yamada 		e = expr_alloc_and(expr_copy(e1), expr_copy(e2));
10420a9064fbSMasahiro Yamada 		e = expr_eliminate_dups(e);
10430a9064fbSMasahiro Yamada 		ret = (!expr_eq(e, e1)) ? e1 : NULL;
10440a9064fbSMasahiro Yamada 		expr_free(e);
10450a9064fbSMasahiro Yamada 		break;
10460a9064fbSMasahiro Yamada 		}
10470a9064fbSMasahiro Yamada 	default:
10480a9064fbSMasahiro Yamada 		ret = e1;
10490a9064fbSMasahiro Yamada 		break;
10500a9064fbSMasahiro Yamada 	}
10510a9064fbSMasahiro Yamada 
10520a9064fbSMasahiro Yamada 	return expr_get_leftmost_symbol(ret);
10530a9064fbSMasahiro Yamada }
10540a9064fbSMasahiro Yamada 
10550a9064fbSMasahiro Yamada void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
10560a9064fbSMasahiro Yamada {
10570a9064fbSMasahiro Yamada 	if (!e) {
10580a9064fbSMasahiro Yamada 		fn(data, NULL, "y");
10590a9064fbSMasahiro Yamada 		return;
10600a9064fbSMasahiro Yamada 	}
10610a9064fbSMasahiro Yamada 
10620a9064fbSMasahiro Yamada 	if (expr_compare_type(prevtoken, e->type) > 0)
10630a9064fbSMasahiro Yamada 		fn(data, NULL, "(");
10640a9064fbSMasahiro Yamada 	switch (e->type) {
10650a9064fbSMasahiro Yamada 	case E_SYMBOL:
10660a9064fbSMasahiro Yamada 		if (e->left.sym->name)
10670a9064fbSMasahiro Yamada 			fn(data, e->left.sym, e->left.sym->name);
10680a9064fbSMasahiro Yamada 		else
10690a9064fbSMasahiro Yamada 			fn(data, NULL, "<choice>");
10700a9064fbSMasahiro Yamada 		break;
10710a9064fbSMasahiro Yamada 	case E_NOT:
10720a9064fbSMasahiro Yamada 		fn(data, NULL, "!");
10730a9064fbSMasahiro Yamada 		expr_print(e->left.expr, fn, data, E_NOT);
10740a9064fbSMasahiro Yamada 		break;
10750a9064fbSMasahiro Yamada 	case E_EQUAL:
10760a9064fbSMasahiro Yamada 		if (e->left.sym->name)
10770a9064fbSMasahiro Yamada 			fn(data, e->left.sym, e->left.sym->name);
10780a9064fbSMasahiro Yamada 		else
10790a9064fbSMasahiro Yamada 			fn(data, NULL, "<choice>");
10800a9064fbSMasahiro Yamada 		fn(data, NULL, "=");
10810a9064fbSMasahiro Yamada 		fn(data, e->right.sym, e->right.sym->name);
10820a9064fbSMasahiro Yamada 		break;
10830a9064fbSMasahiro Yamada 	case E_UNEQUAL:
10840a9064fbSMasahiro Yamada 		if (e->left.sym->name)
10850a9064fbSMasahiro Yamada 			fn(data, e->left.sym, e->left.sym->name);
10860a9064fbSMasahiro Yamada 		else
10870a9064fbSMasahiro Yamada 			fn(data, NULL, "<choice>");
10880a9064fbSMasahiro Yamada 		fn(data, NULL, "!=");
10890a9064fbSMasahiro Yamada 		fn(data, e->right.sym, e->right.sym->name);
10900a9064fbSMasahiro Yamada 		break;
10910a9064fbSMasahiro Yamada 	case E_OR:
10920a9064fbSMasahiro Yamada 		expr_print(e->left.expr, fn, data, E_OR);
10930a9064fbSMasahiro Yamada 		fn(data, NULL, " || ");
10940a9064fbSMasahiro Yamada 		expr_print(e->right.expr, fn, data, E_OR);
10950a9064fbSMasahiro Yamada 		break;
10960a9064fbSMasahiro Yamada 	case E_AND:
10970a9064fbSMasahiro Yamada 		expr_print(e->left.expr, fn, data, E_AND);
10980a9064fbSMasahiro Yamada 		fn(data, NULL, " && ");
10990a9064fbSMasahiro Yamada 		expr_print(e->right.expr, fn, data, E_AND);
11000a9064fbSMasahiro Yamada 		break;
11010a9064fbSMasahiro Yamada 	case E_LIST:
11020a9064fbSMasahiro Yamada 		fn(data, e->right.sym, e->right.sym->name);
11030a9064fbSMasahiro Yamada 		if (e->left.expr) {
11040a9064fbSMasahiro Yamada 			fn(data, NULL, " ^ ");
11050a9064fbSMasahiro Yamada 			expr_print(e->left.expr, fn, data, E_LIST);
11060a9064fbSMasahiro Yamada 		}
11070a9064fbSMasahiro Yamada 		break;
11080a9064fbSMasahiro Yamada 	case E_RANGE:
11090a9064fbSMasahiro Yamada 		fn(data, NULL, "[");
11100a9064fbSMasahiro Yamada 		fn(data, e->left.sym, e->left.sym->name);
11110a9064fbSMasahiro Yamada 		fn(data, NULL, " ");
11120a9064fbSMasahiro Yamada 		fn(data, e->right.sym, e->right.sym->name);
11130a9064fbSMasahiro Yamada 		fn(data, NULL, "]");
11140a9064fbSMasahiro Yamada 		break;
11150a9064fbSMasahiro Yamada 	default:
11160a9064fbSMasahiro Yamada 	  {
11170a9064fbSMasahiro Yamada 		char buf[32];
11180a9064fbSMasahiro Yamada 		sprintf(buf, "<unknown type %d>", e->type);
11190a9064fbSMasahiro Yamada 		fn(data, NULL, buf);
11200a9064fbSMasahiro Yamada 		break;
11210a9064fbSMasahiro Yamada 	  }
11220a9064fbSMasahiro Yamada 	}
11230a9064fbSMasahiro Yamada 	if (expr_compare_type(prevtoken, e->type) > 0)
11240a9064fbSMasahiro Yamada 		fn(data, NULL, ")");
11250a9064fbSMasahiro Yamada }
11260a9064fbSMasahiro Yamada 
11270a9064fbSMasahiro Yamada static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
11280a9064fbSMasahiro Yamada {
11290a9064fbSMasahiro Yamada 	xfwrite(str, strlen(str), 1, data);
11300a9064fbSMasahiro Yamada }
11310a9064fbSMasahiro Yamada 
11320a9064fbSMasahiro Yamada void expr_fprint(struct expr *e, FILE *out)
11330a9064fbSMasahiro Yamada {
11340a9064fbSMasahiro Yamada 	expr_print(e, expr_print_file_helper, out, E_NONE);
11350a9064fbSMasahiro Yamada }
11360a9064fbSMasahiro Yamada 
11370a9064fbSMasahiro Yamada static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
11380a9064fbSMasahiro Yamada {
11390a9064fbSMasahiro Yamada 	struct gstr *gs = (struct gstr*)data;
11400a9064fbSMasahiro Yamada 	const char *sym_str = NULL;
11410a9064fbSMasahiro Yamada 
11420a9064fbSMasahiro Yamada 	if (sym)
11430a9064fbSMasahiro Yamada 		sym_str = sym_get_string_value(sym);
11440a9064fbSMasahiro Yamada 
11450a9064fbSMasahiro Yamada 	if (gs->max_width) {
11460a9064fbSMasahiro Yamada 		unsigned extra_length = strlen(str);
11470a9064fbSMasahiro Yamada 		const char *last_cr = strrchr(gs->s, '\n');
11480a9064fbSMasahiro Yamada 		unsigned last_line_length;
11490a9064fbSMasahiro Yamada 
11500a9064fbSMasahiro Yamada 		if (sym_str)
11510a9064fbSMasahiro Yamada 			extra_length += 4 + strlen(sym_str);
11520a9064fbSMasahiro Yamada 
11530a9064fbSMasahiro Yamada 		if (!last_cr)
11540a9064fbSMasahiro Yamada 			last_cr = gs->s;
11550a9064fbSMasahiro Yamada 
11560a9064fbSMasahiro Yamada 		last_line_length = strlen(gs->s) - (last_cr - gs->s);
11570a9064fbSMasahiro Yamada 
11580a9064fbSMasahiro Yamada 		if ((last_line_length + extra_length) > gs->max_width)
11590a9064fbSMasahiro Yamada 			str_append(gs, "\\\n");
11600a9064fbSMasahiro Yamada 	}
11610a9064fbSMasahiro Yamada 
11620a9064fbSMasahiro Yamada 	str_append(gs, str);
11630a9064fbSMasahiro Yamada 	if (sym && sym->type != S_UNKNOWN)
11640a9064fbSMasahiro Yamada 		str_printf(gs, " [=%s]", sym_str);
11650a9064fbSMasahiro Yamada }
11660a9064fbSMasahiro Yamada 
11670a9064fbSMasahiro Yamada void expr_gstr_print(struct expr *e, struct gstr *gs)
11680a9064fbSMasahiro Yamada {
11690a9064fbSMasahiro Yamada 	expr_print(e, expr_print_gstr_helper, gs, E_NONE);
11700a9064fbSMasahiro Yamada }
1171