xref: /rk3399_rockchip-uboot/scripts/kconfig/expr.c (revision bf7ab1e70fd7621fea5dea07b6975c576119b86e)
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 
149b5f0b1dSMasahiro Yamada static int expr_eq(struct expr *e1, struct expr *e2);
159b5f0b1dSMasahiro Yamada static struct expr *expr_eliminate_yn(struct expr *e);
169b5f0b1dSMasahiro Yamada 
expr_alloc_symbol(struct symbol * sym)170a9064fbSMasahiro Yamada struct expr *expr_alloc_symbol(struct symbol *sym)
180a9064fbSMasahiro Yamada {
190a9064fbSMasahiro Yamada 	struct expr *e = xcalloc(1, sizeof(*e));
200a9064fbSMasahiro Yamada 	e->type = E_SYMBOL;
210a9064fbSMasahiro Yamada 	e->left.sym = sym;
220a9064fbSMasahiro Yamada 	return e;
230a9064fbSMasahiro Yamada }
240a9064fbSMasahiro Yamada 
expr_alloc_one(enum expr_type type,struct expr * ce)250a9064fbSMasahiro Yamada struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
260a9064fbSMasahiro Yamada {
270a9064fbSMasahiro Yamada 	struct expr *e = xcalloc(1, sizeof(*e));
280a9064fbSMasahiro Yamada 	e->type = type;
290a9064fbSMasahiro Yamada 	e->left.expr = ce;
300a9064fbSMasahiro Yamada 	return e;
310a9064fbSMasahiro Yamada }
320a9064fbSMasahiro Yamada 
expr_alloc_two(enum expr_type type,struct expr * e1,struct expr * e2)330a9064fbSMasahiro Yamada struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
340a9064fbSMasahiro Yamada {
350a9064fbSMasahiro Yamada 	struct expr *e = xcalloc(1, sizeof(*e));
360a9064fbSMasahiro Yamada 	e->type = type;
370a9064fbSMasahiro Yamada 	e->left.expr = e1;
380a9064fbSMasahiro Yamada 	e->right.expr = e2;
390a9064fbSMasahiro Yamada 	return e;
400a9064fbSMasahiro Yamada }
410a9064fbSMasahiro Yamada 
expr_alloc_comp(enum expr_type type,struct symbol * s1,struct symbol * s2)420a9064fbSMasahiro Yamada struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
430a9064fbSMasahiro Yamada {
440a9064fbSMasahiro Yamada 	struct expr *e = xcalloc(1, sizeof(*e));
450a9064fbSMasahiro Yamada 	e->type = type;
460a9064fbSMasahiro Yamada 	e->left.sym = s1;
470a9064fbSMasahiro Yamada 	e->right.sym = s2;
480a9064fbSMasahiro Yamada 	return e;
490a9064fbSMasahiro Yamada }
500a9064fbSMasahiro Yamada 
expr_alloc_and(struct expr * e1,struct expr * e2)510a9064fbSMasahiro Yamada struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
520a9064fbSMasahiro Yamada {
530a9064fbSMasahiro Yamada 	if (!e1)
540a9064fbSMasahiro Yamada 		return e2;
550a9064fbSMasahiro Yamada 	return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
560a9064fbSMasahiro Yamada }
570a9064fbSMasahiro Yamada 
expr_alloc_or(struct expr * e1,struct expr * e2)580a9064fbSMasahiro Yamada struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
590a9064fbSMasahiro Yamada {
600a9064fbSMasahiro Yamada 	if (!e1)
610a9064fbSMasahiro Yamada 		return e2;
620a9064fbSMasahiro Yamada 	return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
630a9064fbSMasahiro Yamada }
640a9064fbSMasahiro Yamada 
expr_copy(const struct expr * org)650a9064fbSMasahiro Yamada struct expr *expr_copy(const struct expr *org)
660a9064fbSMasahiro Yamada {
670a9064fbSMasahiro Yamada 	struct expr *e;
680a9064fbSMasahiro Yamada 
690a9064fbSMasahiro Yamada 	if (!org)
700a9064fbSMasahiro Yamada 		return NULL;
710a9064fbSMasahiro Yamada 
720a9064fbSMasahiro Yamada 	e = xmalloc(sizeof(*org));
730a9064fbSMasahiro Yamada 	memcpy(e, org, sizeof(*org));
740a9064fbSMasahiro Yamada 	switch (org->type) {
750a9064fbSMasahiro Yamada 	case E_SYMBOL:
760a9064fbSMasahiro Yamada 		e->left = org->left;
770a9064fbSMasahiro Yamada 		break;
780a9064fbSMasahiro Yamada 	case E_NOT:
790a9064fbSMasahiro Yamada 		e->left.expr = expr_copy(org->left.expr);
800a9064fbSMasahiro Yamada 		break;
810a9064fbSMasahiro Yamada 	case E_EQUAL:
82*bf7ab1e7SMasahiro Yamada 	case E_GEQ:
83*bf7ab1e7SMasahiro Yamada 	case E_GTH:
84*bf7ab1e7SMasahiro Yamada 	case E_LEQ:
85*bf7ab1e7SMasahiro Yamada 	case E_LTH:
860a9064fbSMasahiro Yamada 	case E_UNEQUAL:
870a9064fbSMasahiro Yamada 		e->left.sym = org->left.sym;
880a9064fbSMasahiro Yamada 		e->right.sym = org->right.sym;
890a9064fbSMasahiro Yamada 		break;
900a9064fbSMasahiro Yamada 	case E_AND:
910a9064fbSMasahiro Yamada 	case E_OR:
920a9064fbSMasahiro Yamada 	case E_LIST:
930a9064fbSMasahiro Yamada 		e->left.expr = expr_copy(org->left.expr);
940a9064fbSMasahiro Yamada 		e->right.expr = expr_copy(org->right.expr);
950a9064fbSMasahiro Yamada 		break;
960a9064fbSMasahiro Yamada 	default:
970a9064fbSMasahiro Yamada 		printf("can't copy type %d\n", e->type);
980a9064fbSMasahiro Yamada 		free(e);
990a9064fbSMasahiro Yamada 		e = NULL;
1000a9064fbSMasahiro Yamada 		break;
1010a9064fbSMasahiro Yamada 	}
1020a9064fbSMasahiro Yamada 
1030a9064fbSMasahiro Yamada 	return e;
1040a9064fbSMasahiro Yamada }
1050a9064fbSMasahiro Yamada 
expr_free(struct expr * e)1060a9064fbSMasahiro Yamada void expr_free(struct expr *e)
1070a9064fbSMasahiro Yamada {
1080a9064fbSMasahiro Yamada 	if (!e)
1090a9064fbSMasahiro Yamada 		return;
1100a9064fbSMasahiro Yamada 
1110a9064fbSMasahiro Yamada 	switch (e->type) {
1120a9064fbSMasahiro Yamada 	case E_SYMBOL:
1130a9064fbSMasahiro Yamada 		break;
1140a9064fbSMasahiro Yamada 	case E_NOT:
1150a9064fbSMasahiro Yamada 		expr_free(e->left.expr);
1160a9064fbSMasahiro Yamada 		return;
1170a9064fbSMasahiro Yamada 	case E_EQUAL:
118*bf7ab1e7SMasahiro Yamada 	case E_GEQ:
119*bf7ab1e7SMasahiro Yamada 	case E_GTH:
120*bf7ab1e7SMasahiro Yamada 	case E_LEQ:
121*bf7ab1e7SMasahiro Yamada 	case E_LTH:
1220a9064fbSMasahiro Yamada 	case E_UNEQUAL:
1230a9064fbSMasahiro Yamada 		break;
1240a9064fbSMasahiro Yamada 	case E_OR:
1250a9064fbSMasahiro Yamada 	case E_AND:
1260a9064fbSMasahiro Yamada 		expr_free(e->left.expr);
1270a9064fbSMasahiro Yamada 		expr_free(e->right.expr);
1280a9064fbSMasahiro Yamada 		break;
1290a9064fbSMasahiro Yamada 	default:
1300a9064fbSMasahiro Yamada 		printf("how to free type %d?\n", e->type);
1310a9064fbSMasahiro Yamada 		break;
1320a9064fbSMasahiro Yamada 	}
1330a9064fbSMasahiro Yamada 	free(e);
1340a9064fbSMasahiro Yamada }
1350a9064fbSMasahiro Yamada 
1360a9064fbSMasahiro Yamada static int trans_count;
1370a9064fbSMasahiro Yamada 
1380a9064fbSMasahiro Yamada #define e1 (*ep1)
1390a9064fbSMasahiro Yamada #define e2 (*ep2)
1400a9064fbSMasahiro Yamada 
__expr_eliminate_eq(enum expr_type type,struct expr ** ep1,struct expr ** ep2)1410a9064fbSMasahiro Yamada static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
1420a9064fbSMasahiro Yamada {
1430a9064fbSMasahiro Yamada 	if (e1->type == type) {
1440a9064fbSMasahiro Yamada 		__expr_eliminate_eq(type, &e1->left.expr, &e2);
1450a9064fbSMasahiro Yamada 		__expr_eliminate_eq(type, &e1->right.expr, &e2);
1460a9064fbSMasahiro Yamada 		return;
1470a9064fbSMasahiro Yamada 	}
1480a9064fbSMasahiro Yamada 	if (e2->type == type) {
1490a9064fbSMasahiro Yamada 		__expr_eliminate_eq(type, &e1, &e2->left.expr);
1500a9064fbSMasahiro Yamada 		__expr_eliminate_eq(type, &e1, &e2->right.expr);
1510a9064fbSMasahiro Yamada 		return;
1520a9064fbSMasahiro Yamada 	}
1530a9064fbSMasahiro Yamada 	if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
1540a9064fbSMasahiro Yamada 	    e1->left.sym == e2->left.sym &&
1550a9064fbSMasahiro Yamada 	    (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
1560a9064fbSMasahiro Yamada 		return;
1570a9064fbSMasahiro Yamada 	if (!expr_eq(e1, e2))
1580a9064fbSMasahiro Yamada 		return;
1590a9064fbSMasahiro Yamada 	trans_count++;
1600a9064fbSMasahiro Yamada 	expr_free(e1); expr_free(e2);
1610a9064fbSMasahiro Yamada 	switch (type) {
1620a9064fbSMasahiro Yamada 	case E_OR:
1630a9064fbSMasahiro Yamada 		e1 = expr_alloc_symbol(&symbol_no);
1640a9064fbSMasahiro Yamada 		e2 = expr_alloc_symbol(&symbol_no);
1650a9064fbSMasahiro Yamada 		break;
1660a9064fbSMasahiro Yamada 	case E_AND:
1670a9064fbSMasahiro Yamada 		e1 = expr_alloc_symbol(&symbol_yes);
1680a9064fbSMasahiro Yamada 		e2 = expr_alloc_symbol(&symbol_yes);
1690a9064fbSMasahiro Yamada 		break;
1700a9064fbSMasahiro Yamada 	default:
1710a9064fbSMasahiro Yamada 		;
1720a9064fbSMasahiro Yamada 	}
1730a9064fbSMasahiro Yamada }
1740a9064fbSMasahiro Yamada 
expr_eliminate_eq(struct expr ** ep1,struct expr ** ep2)1750a9064fbSMasahiro Yamada void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
1760a9064fbSMasahiro Yamada {
1770a9064fbSMasahiro Yamada 	if (!e1 || !e2)
1780a9064fbSMasahiro Yamada 		return;
1790a9064fbSMasahiro Yamada 	switch (e1->type) {
1800a9064fbSMasahiro Yamada 	case E_OR:
1810a9064fbSMasahiro Yamada 	case E_AND:
1820a9064fbSMasahiro Yamada 		__expr_eliminate_eq(e1->type, ep1, ep2);
1830a9064fbSMasahiro Yamada 	default:
1840a9064fbSMasahiro Yamada 		;
1850a9064fbSMasahiro Yamada 	}
1860a9064fbSMasahiro Yamada 	if (e1->type != e2->type) switch (e2->type) {
1870a9064fbSMasahiro Yamada 	case E_OR:
1880a9064fbSMasahiro Yamada 	case E_AND:
1890a9064fbSMasahiro Yamada 		__expr_eliminate_eq(e2->type, ep1, ep2);
1900a9064fbSMasahiro Yamada 	default:
1910a9064fbSMasahiro Yamada 		;
1920a9064fbSMasahiro Yamada 	}
1930a9064fbSMasahiro Yamada 	e1 = expr_eliminate_yn(e1);
1940a9064fbSMasahiro Yamada 	e2 = expr_eliminate_yn(e2);
1950a9064fbSMasahiro Yamada }
1960a9064fbSMasahiro Yamada 
1970a9064fbSMasahiro Yamada #undef e1
1980a9064fbSMasahiro Yamada #undef e2
1990a9064fbSMasahiro Yamada 
expr_eq(struct expr * e1,struct expr * e2)2009b5f0b1dSMasahiro Yamada static int expr_eq(struct expr *e1, struct expr *e2)
2010a9064fbSMasahiro Yamada {
2020a9064fbSMasahiro Yamada 	int res, old_count;
2030a9064fbSMasahiro Yamada 
2040a9064fbSMasahiro Yamada 	if (e1->type != e2->type)
2050a9064fbSMasahiro Yamada 		return 0;
2060a9064fbSMasahiro Yamada 	switch (e1->type) {
2070a9064fbSMasahiro Yamada 	case E_EQUAL:
208*bf7ab1e7SMasahiro Yamada 	case E_GEQ:
209*bf7ab1e7SMasahiro Yamada 	case E_GTH:
210*bf7ab1e7SMasahiro Yamada 	case E_LEQ:
211*bf7ab1e7SMasahiro Yamada 	case E_LTH:
2120a9064fbSMasahiro Yamada 	case E_UNEQUAL:
2130a9064fbSMasahiro Yamada 		return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
2140a9064fbSMasahiro Yamada 	case E_SYMBOL:
2150a9064fbSMasahiro Yamada 		return e1->left.sym == e2->left.sym;
2160a9064fbSMasahiro Yamada 	case E_NOT:
2170a9064fbSMasahiro Yamada 		return expr_eq(e1->left.expr, e2->left.expr);
2180a9064fbSMasahiro Yamada 	case E_AND:
2190a9064fbSMasahiro Yamada 	case E_OR:
2200a9064fbSMasahiro Yamada 		e1 = expr_copy(e1);
2210a9064fbSMasahiro Yamada 		e2 = expr_copy(e2);
2220a9064fbSMasahiro Yamada 		old_count = trans_count;
2230a9064fbSMasahiro Yamada 		expr_eliminate_eq(&e1, &e2);
2240a9064fbSMasahiro Yamada 		res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
2250a9064fbSMasahiro Yamada 		       e1->left.sym == e2->left.sym);
2260a9064fbSMasahiro Yamada 		expr_free(e1);
2270a9064fbSMasahiro Yamada 		expr_free(e2);
2280a9064fbSMasahiro Yamada 		trans_count = old_count;
2290a9064fbSMasahiro Yamada 		return res;
2300a9064fbSMasahiro Yamada 	case E_LIST:
2310a9064fbSMasahiro Yamada 	case E_RANGE:
2320a9064fbSMasahiro Yamada 	case E_NONE:
2330a9064fbSMasahiro Yamada 		/* panic */;
2340a9064fbSMasahiro Yamada 	}
2350a9064fbSMasahiro Yamada 
2360a9064fbSMasahiro Yamada 	if (DEBUG_EXPR) {
2370a9064fbSMasahiro Yamada 		expr_fprint(e1, stdout);
2380a9064fbSMasahiro Yamada 		printf(" = ");
2390a9064fbSMasahiro Yamada 		expr_fprint(e2, stdout);
2400a9064fbSMasahiro Yamada 		printf(" ?\n");
2410a9064fbSMasahiro Yamada 	}
2420a9064fbSMasahiro Yamada 
2430a9064fbSMasahiro Yamada 	return 0;
2440a9064fbSMasahiro Yamada }
2450a9064fbSMasahiro Yamada 
expr_eliminate_yn(struct expr * e)2469b5f0b1dSMasahiro Yamada static struct expr *expr_eliminate_yn(struct expr *e)
2470a9064fbSMasahiro Yamada {
2480a9064fbSMasahiro Yamada 	struct expr *tmp;
2490a9064fbSMasahiro Yamada 
2500a9064fbSMasahiro Yamada 	if (e) switch (e->type) {
2510a9064fbSMasahiro Yamada 	case E_AND:
2520a9064fbSMasahiro Yamada 		e->left.expr = expr_eliminate_yn(e->left.expr);
2530a9064fbSMasahiro Yamada 		e->right.expr = expr_eliminate_yn(e->right.expr);
2540a9064fbSMasahiro Yamada 		if (e->left.expr->type == E_SYMBOL) {
2550a9064fbSMasahiro Yamada 			if (e->left.expr->left.sym == &symbol_no) {
2560a9064fbSMasahiro Yamada 				expr_free(e->left.expr);
2570a9064fbSMasahiro Yamada 				expr_free(e->right.expr);
2580a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
2590a9064fbSMasahiro Yamada 				e->left.sym = &symbol_no;
2600a9064fbSMasahiro Yamada 				e->right.expr = NULL;
2610a9064fbSMasahiro Yamada 				return e;
2620a9064fbSMasahiro Yamada 			} else if (e->left.expr->left.sym == &symbol_yes) {
2630a9064fbSMasahiro Yamada 				free(e->left.expr);
2640a9064fbSMasahiro Yamada 				tmp = e->right.expr;
2650a9064fbSMasahiro Yamada 				*e = *(e->right.expr);
2660a9064fbSMasahiro Yamada 				free(tmp);
2670a9064fbSMasahiro Yamada 				return e;
2680a9064fbSMasahiro Yamada 			}
2690a9064fbSMasahiro Yamada 		}
2700a9064fbSMasahiro Yamada 		if (e->right.expr->type == E_SYMBOL) {
2710a9064fbSMasahiro Yamada 			if (e->right.expr->left.sym == &symbol_no) {
2720a9064fbSMasahiro Yamada 				expr_free(e->left.expr);
2730a9064fbSMasahiro Yamada 				expr_free(e->right.expr);
2740a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
2750a9064fbSMasahiro Yamada 				e->left.sym = &symbol_no;
2760a9064fbSMasahiro Yamada 				e->right.expr = NULL;
2770a9064fbSMasahiro Yamada 				return e;
2780a9064fbSMasahiro Yamada 			} else if (e->right.expr->left.sym == &symbol_yes) {
2790a9064fbSMasahiro Yamada 				free(e->right.expr);
2800a9064fbSMasahiro Yamada 				tmp = e->left.expr;
2810a9064fbSMasahiro Yamada 				*e = *(e->left.expr);
2820a9064fbSMasahiro Yamada 				free(tmp);
2830a9064fbSMasahiro Yamada 				return e;
2840a9064fbSMasahiro Yamada 			}
2850a9064fbSMasahiro Yamada 		}
2860a9064fbSMasahiro Yamada 		break;
2870a9064fbSMasahiro Yamada 	case E_OR:
2880a9064fbSMasahiro Yamada 		e->left.expr = expr_eliminate_yn(e->left.expr);
2890a9064fbSMasahiro Yamada 		e->right.expr = expr_eliminate_yn(e->right.expr);
2900a9064fbSMasahiro Yamada 		if (e->left.expr->type == E_SYMBOL) {
2910a9064fbSMasahiro Yamada 			if (e->left.expr->left.sym == &symbol_no) {
2920a9064fbSMasahiro Yamada 				free(e->left.expr);
2930a9064fbSMasahiro Yamada 				tmp = e->right.expr;
2940a9064fbSMasahiro Yamada 				*e = *(e->right.expr);
2950a9064fbSMasahiro Yamada 				free(tmp);
2960a9064fbSMasahiro Yamada 				return e;
2970a9064fbSMasahiro Yamada 			} else if (e->left.expr->left.sym == &symbol_yes) {
2980a9064fbSMasahiro Yamada 				expr_free(e->left.expr);
2990a9064fbSMasahiro Yamada 				expr_free(e->right.expr);
3000a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
3010a9064fbSMasahiro Yamada 				e->left.sym = &symbol_yes;
3020a9064fbSMasahiro Yamada 				e->right.expr = NULL;
3030a9064fbSMasahiro Yamada 				return e;
3040a9064fbSMasahiro Yamada 			}
3050a9064fbSMasahiro Yamada 		}
3060a9064fbSMasahiro Yamada 		if (e->right.expr->type == E_SYMBOL) {
3070a9064fbSMasahiro Yamada 			if (e->right.expr->left.sym == &symbol_no) {
3080a9064fbSMasahiro Yamada 				free(e->right.expr);
3090a9064fbSMasahiro Yamada 				tmp = e->left.expr;
3100a9064fbSMasahiro Yamada 				*e = *(e->left.expr);
3110a9064fbSMasahiro Yamada 				free(tmp);
3120a9064fbSMasahiro Yamada 				return e;
3130a9064fbSMasahiro Yamada 			} else if (e->right.expr->left.sym == &symbol_yes) {
3140a9064fbSMasahiro Yamada 				expr_free(e->left.expr);
3150a9064fbSMasahiro Yamada 				expr_free(e->right.expr);
3160a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
3170a9064fbSMasahiro Yamada 				e->left.sym = &symbol_yes;
3180a9064fbSMasahiro Yamada 				e->right.expr = NULL;
3190a9064fbSMasahiro Yamada 				return e;
3200a9064fbSMasahiro Yamada 			}
3210a9064fbSMasahiro Yamada 		}
3220a9064fbSMasahiro Yamada 		break;
3230a9064fbSMasahiro Yamada 	default:
3240a9064fbSMasahiro Yamada 		;
3250a9064fbSMasahiro Yamada 	}
3260a9064fbSMasahiro Yamada 	return e;
3270a9064fbSMasahiro Yamada }
3280a9064fbSMasahiro Yamada 
3290a9064fbSMasahiro Yamada /*
3300a9064fbSMasahiro Yamada  * bool FOO!=n => FOO
3310a9064fbSMasahiro Yamada  */
expr_trans_bool(struct expr * e)3320a9064fbSMasahiro Yamada struct expr *expr_trans_bool(struct expr *e)
3330a9064fbSMasahiro Yamada {
3340a9064fbSMasahiro Yamada 	if (!e)
3350a9064fbSMasahiro Yamada 		return NULL;
3360a9064fbSMasahiro Yamada 	switch (e->type) {
3370a9064fbSMasahiro Yamada 	case E_AND:
3380a9064fbSMasahiro Yamada 	case E_OR:
3390a9064fbSMasahiro Yamada 	case E_NOT:
3400a9064fbSMasahiro Yamada 		e->left.expr = expr_trans_bool(e->left.expr);
3410a9064fbSMasahiro Yamada 		e->right.expr = expr_trans_bool(e->right.expr);
3420a9064fbSMasahiro Yamada 		break;
3430a9064fbSMasahiro Yamada 	case E_UNEQUAL:
3440a9064fbSMasahiro Yamada 		// FOO!=n -> FOO
3450a9064fbSMasahiro Yamada 		if (e->left.sym->type == S_TRISTATE) {
3460a9064fbSMasahiro Yamada 			if (e->right.sym == &symbol_no) {
3470a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
3480a9064fbSMasahiro Yamada 				e->right.sym = NULL;
3490a9064fbSMasahiro Yamada 			}
3500a9064fbSMasahiro Yamada 		}
3510a9064fbSMasahiro Yamada 		break;
3520a9064fbSMasahiro Yamada 	default:
3530a9064fbSMasahiro Yamada 		;
3540a9064fbSMasahiro Yamada 	}
3550a9064fbSMasahiro Yamada 	return e;
3560a9064fbSMasahiro Yamada }
3570a9064fbSMasahiro Yamada 
3580a9064fbSMasahiro Yamada /*
3590a9064fbSMasahiro Yamada  * e1 || e2 -> ?
3600a9064fbSMasahiro Yamada  */
expr_join_or(struct expr * e1,struct expr * e2)3610a9064fbSMasahiro Yamada static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
3620a9064fbSMasahiro Yamada {
3630a9064fbSMasahiro Yamada 	struct expr *tmp;
3640a9064fbSMasahiro Yamada 	struct symbol *sym1, *sym2;
3650a9064fbSMasahiro Yamada 
3660a9064fbSMasahiro Yamada 	if (expr_eq(e1, e2))
3670a9064fbSMasahiro Yamada 		return expr_copy(e1);
3680a9064fbSMasahiro Yamada 	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
3690a9064fbSMasahiro Yamada 		return NULL;
3700a9064fbSMasahiro Yamada 	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
3710a9064fbSMasahiro Yamada 		return NULL;
3720a9064fbSMasahiro Yamada 	if (e1->type == E_NOT) {
3730a9064fbSMasahiro Yamada 		tmp = e1->left.expr;
3740a9064fbSMasahiro Yamada 		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
3750a9064fbSMasahiro Yamada 			return NULL;
3760a9064fbSMasahiro Yamada 		sym1 = tmp->left.sym;
3770a9064fbSMasahiro Yamada 	} else
3780a9064fbSMasahiro Yamada 		sym1 = e1->left.sym;
3790a9064fbSMasahiro Yamada 	if (e2->type == E_NOT) {
3800a9064fbSMasahiro Yamada 		if (e2->left.expr->type != E_SYMBOL)
3810a9064fbSMasahiro Yamada 			return NULL;
3820a9064fbSMasahiro Yamada 		sym2 = e2->left.expr->left.sym;
3830a9064fbSMasahiro Yamada 	} else
3840a9064fbSMasahiro Yamada 		sym2 = e2->left.sym;
3850a9064fbSMasahiro Yamada 	if (sym1 != sym2)
3860a9064fbSMasahiro Yamada 		return NULL;
3870a9064fbSMasahiro Yamada 	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
3880a9064fbSMasahiro Yamada 		return NULL;
3890a9064fbSMasahiro Yamada 	if (sym1->type == S_TRISTATE) {
3900a9064fbSMasahiro Yamada 		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
3910a9064fbSMasahiro Yamada 		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
3920a9064fbSMasahiro Yamada 		     (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
3930a9064fbSMasahiro Yamada 			// (a='y') || (a='m') -> (a!='n')
3940a9064fbSMasahiro Yamada 			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
3950a9064fbSMasahiro Yamada 		}
3960a9064fbSMasahiro Yamada 		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
3970a9064fbSMasahiro Yamada 		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
3980a9064fbSMasahiro Yamada 		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
3990a9064fbSMasahiro Yamada 			// (a='y') || (a='n') -> (a!='m')
4000a9064fbSMasahiro Yamada 			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
4010a9064fbSMasahiro Yamada 		}
4020a9064fbSMasahiro Yamada 		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
4030a9064fbSMasahiro Yamada 		    ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
4040a9064fbSMasahiro Yamada 		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
4050a9064fbSMasahiro Yamada 			// (a='m') || (a='n') -> (a!='y')
4060a9064fbSMasahiro Yamada 			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
4070a9064fbSMasahiro Yamada 		}
4080a9064fbSMasahiro Yamada 	}
4090a9064fbSMasahiro Yamada 	if (sym1->type == S_BOOLEAN && sym1 == sym2) {
4100a9064fbSMasahiro Yamada 		if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
4110a9064fbSMasahiro Yamada 		    (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
4120a9064fbSMasahiro Yamada 			return expr_alloc_symbol(&symbol_yes);
4130a9064fbSMasahiro Yamada 	}
4140a9064fbSMasahiro Yamada 
4150a9064fbSMasahiro Yamada 	if (DEBUG_EXPR) {
4160a9064fbSMasahiro Yamada 		printf("optimize (");
4170a9064fbSMasahiro Yamada 		expr_fprint(e1, stdout);
4180a9064fbSMasahiro Yamada 		printf(") || (");
4190a9064fbSMasahiro Yamada 		expr_fprint(e2, stdout);
4200a9064fbSMasahiro Yamada 		printf(")?\n");
4210a9064fbSMasahiro Yamada 	}
4220a9064fbSMasahiro Yamada 	return NULL;
4230a9064fbSMasahiro Yamada }
4240a9064fbSMasahiro Yamada 
expr_join_and(struct expr * e1,struct expr * e2)4250a9064fbSMasahiro Yamada static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
4260a9064fbSMasahiro Yamada {
4270a9064fbSMasahiro Yamada 	struct expr *tmp;
4280a9064fbSMasahiro Yamada 	struct symbol *sym1, *sym2;
4290a9064fbSMasahiro Yamada 
4300a9064fbSMasahiro Yamada 	if (expr_eq(e1, e2))
4310a9064fbSMasahiro Yamada 		return expr_copy(e1);
4320a9064fbSMasahiro Yamada 	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
4330a9064fbSMasahiro Yamada 		return NULL;
4340a9064fbSMasahiro Yamada 	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
4350a9064fbSMasahiro Yamada 		return NULL;
4360a9064fbSMasahiro Yamada 	if (e1->type == E_NOT) {
4370a9064fbSMasahiro Yamada 		tmp = e1->left.expr;
4380a9064fbSMasahiro Yamada 		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
4390a9064fbSMasahiro Yamada 			return NULL;
4400a9064fbSMasahiro Yamada 		sym1 = tmp->left.sym;
4410a9064fbSMasahiro Yamada 	} else
4420a9064fbSMasahiro Yamada 		sym1 = e1->left.sym;
4430a9064fbSMasahiro Yamada 	if (e2->type == E_NOT) {
4440a9064fbSMasahiro Yamada 		if (e2->left.expr->type != E_SYMBOL)
4450a9064fbSMasahiro Yamada 			return NULL;
4460a9064fbSMasahiro Yamada 		sym2 = e2->left.expr->left.sym;
4470a9064fbSMasahiro Yamada 	} else
4480a9064fbSMasahiro Yamada 		sym2 = e2->left.sym;
4490a9064fbSMasahiro Yamada 	if (sym1 != sym2)
4500a9064fbSMasahiro Yamada 		return NULL;
4510a9064fbSMasahiro Yamada 	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
4520a9064fbSMasahiro Yamada 		return NULL;
4530a9064fbSMasahiro Yamada 
4540a9064fbSMasahiro Yamada 	if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
4550a9064fbSMasahiro Yamada 	    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
4560a9064fbSMasahiro Yamada 		// (a) && (a='y') -> (a='y')
4570a9064fbSMasahiro Yamada 		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
4580a9064fbSMasahiro Yamada 
4590a9064fbSMasahiro Yamada 	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
4600a9064fbSMasahiro Yamada 	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
4610a9064fbSMasahiro Yamada 		// (a) && (a!='n') -> (a)
4620a9064fbSMasahiro Yamada 		return expr_alloc_symbol(sym1);
4630a9064fbSMasahiro Yamada 
4640a9064fbSMasahiro Yamada 	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
4650a9064fbSMasahiro Yamada 	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
4660a9064fbSMasahiro Yamada 		// (a) && (a!='m') -> (a='y')
4670a9064fbSMasahiro Yamada 		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
4680a9064fbSMasahiro Yamada 
4690a9064fbSMasahiro Yamada 	if (sym1->type == S_TRISTATE) {
4700a9064fbSMasahiro Yamada 		if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
4710a9064fbSMasahiro Yamada 			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
4720a9064fbSMasahiro Yamada 			sym2 = e1->right.sym;
4730a9064fbSMasahiro Yamada 			if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
4740a9064fbSMasahiro Yamada 				return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
4750a9064fbSMasahiro Yamada 							     : expr_alloc_symbol(&symbol_no);
4760a9064fbSMasahiro Yamada 		}
4770a9064fbSMasahiro Yamada 		if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
4780a9064fbSMasahiro Yamada 			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
4790a9064fbSMasahiro Yamada 			sym2 = e2->right.sym;
4800a9064fbSMasahiro Yamada 			if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
4810a9064fbSMasahiro Yamada 				return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
4820a9064fbSMasahiro Yamada 							     : expr_alloc_symbol(&symbol_no);
4830a9064fbSMasahiro Yamada 		}
4840a9064fbSMasahiro Yamada 		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
4850a9064fbSMasahiro Yamada 			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
4860a9064fbSMasahiro Yamada 			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
4870a9064fbSMasahiro Yamada 			// (a!='y') && (a!='n') -> (a='m')
4880a9064fbSMasahiro Yamada 			return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
4890a9064fbSMasahiro Yamada 
4900a9064fbSMasahiro Yamada 		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
4910a9064fbSMasahiro Yamada 			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
4920a9064fbSMasahiro Yamada 			    (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
4930a9064fbSMasahiro Yamada 			// (a!='y') && (a!='m') -> (a='n')
4940a9064fbSMasahiro Yamada 			return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
4950a9064fbSMasahiro Yamada 
4960a9064fbSMasahiro Yamada 		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
4970a9064fbSMasahiro Yamada 			   ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
4980a9064fbSMasahiro Yamada 			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
4990a9064fbSMasahiro Yamada 			// (a!='m') && (a!='n') -> (a='m')
5000a9064fbSMasahiro Yamada 			return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
5010a9064fbSMasahiro Yamada 
5020a9064fbSMasahiro Yamada 		if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
5030a9064fbSMasahiro Yamada 		    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
5040a9064fbSMasahiro Yamada 		    (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
5050a9064fbSMasahiro Yamada 		    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
5060a9064fbSMasahiro Yamada 			return NULL;
5070a9064fbSMasahiro Yamada 	}
5080a9064fbSMasahiro Yamada 
5090a9064fbSMasahiro Yamada 	if (DEBUG_EXPR) {
5100a9064fbSMasahiro Yamada 		printf("optimize (");
5110a9064fbSMasahiro Yamada 		expr_fprint(e1, stdout);
5120a9064fbSMasahiro Yamada 		printf(") && (");
5130a9064fbSMasahiro Yamada 		expr_fprint(e2, stdout);
5140a9064fbSMasahiro Yamada 		printf(")?\n");
5150a9064fbSMasahiro Yamada 	}
5160a9064fbSMasahiro Yamada 	return NULL;
5170a9064fbSMasahiro Yamada }
5180a9064fbSMasahiro Yamada 
expr_eliminate_dups1(enum expr_type type,struct expr ** ep1,struct expr ** ep2)5190a9064fbSMasahiro Yamada static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
5200a9064fbSMasahiro Yamada {
5210a9064fbSMasahiro Yamada #define e1 (*ep1)
5220a9064fbSMasahiro Yamada #define e2 (*ep2)
5230a9064fbSMasahiro Yamada 	struct expr *tmp;
5240a9064fbSMasahiro Yamada 
5250a9064fbSMasahiro Yamada 	if (e1->type == type) {
5260a9064fbSMasahiro Yamada 		expr_eliminate_dups1(type, &e1->left.expr, &e2);
5270a9064fbSMasahiro Yamada 		expr_eliminate_dups1(type, &e1->right.expr, &e2);
5280a9064fbSMasahiro Yamada 		return;
5290a9064fbSMasahiro Yamada 	}
5300a9064fbSMasahiro Yamada 	if (e2->type == type) {
5310a9064fbSMasahiro Yamada 		expr_eliminate_dups1(type, &e1, &e2->left.expr);
5320a9064fbSMasahiro Yamada 		expr_eliminate_dups1(type, &e1, &e2->right.expr);
5330a9064fbSMasahiro Yamada 		return;
5340a9064fbSMasahiro Yamada 	}
5350a9064fbSMasahiro Yamada 	if (e1 == e2)
5360a9064fbSMasahiro Yamada 		return;
5370a9064fbSMasahiro Yamada 
5380a9064fbSMasahiro Yamada 	switch (e1->type) {
5390a9064fbSMasahiro Yamada 	case E_OR: case E_AND:
5400a9064fbSMasahiro Yamada 		expr_eliminate_dups1(e1->type, &e1, &e1);
5410a9064fbSMasahiro Yamada 	default:
5420a9064fbSMasahiro Yamada 		;
5430a9064fbSMasahiro Yamada 	}
5440a9064fbSMasahiro Yamada 
5450a9064fbSMasahiro Yamada 	switch (type) {
5460a9064fbSMasahiro Yamada 	case E_OR:
5470a9064fbSMasahiro Yamada 		tmp = expr_join_or(e1, e2);
5480a9064fbSMasahiro Yamada 		if (tmp) {
5490a9064fbSMasahiro Yamada 			expr_free(e1); expr_free(e2);
5500a9064fbSMasahiro Yamada 			e1 = expr_alloc_symbol(&symbol_no);
5510a9064fbSMasahiro Yamada 			e2 = tmp;
5520a9064fbSMasahiro Yamada 			trans_count++;
5530a9064fbSMasahiro Yamada 		}
5540a9064fbSMasahiro Yamada 		break;
5550a9064fbSMasahiro Yamada 	case E_AND:
5560a9064fbSMasahiro Yamada 		tmp = expr_join_and(e1, e2);
5570a9064fbSMasahiro Yamada 		if (tmp) {
5580a9064fbSMasahiro Yamada 			expr_free(e1); expr_free(e2);
5590a9064fbSMasahiro Yamada 			e1 = expr_alloc_symbol(&symbol_yes);
5600a9064fbSMasahiro Yamada 			e2 = tmp;
5610a9064fbSMasahiro Yamada 			trans_count++;
5620a9064fbSMasahiro Yamada 		}
5630a9064fbSMasahiro Yamada 		break;
5640a9064fbSMasahiro Yamada 	default:
5650a9064fbSMasahiro Yamada 		;
5660a9064fbSMasahiro Yamada 	}
5670a9064fbSMasahiro Yamada #undef e1
5680a9064fbSMasahiro Yamada #undef e2
5690a9064fbSMasahiro Yamada }
5700a9064fbSMasahiro Yamada 
expr_eliminate_dups(struct expr * e)5710a9064fbSMasahiro Yamada struct expr *expr_eliminate_dups(struct expr *e)
5720a9064fbSMasahiro Yamada {
5730a9064fbSMasahiro Yamada 	int oldcount;
5740a9064fbSMasahiro Yamada 	if (!e)
5750a9064fbSMasahiro Yamada 		return e;
5760a9064fbSMasahiro Yamada 
5770a9064fbSMasahiro Yamada 	oldcount = trans_count;
5780a9064fbSMasahiro Yamada 	while (1) {
5790a9064fbSMasahiro Yamada 		trans_count = 0;
5800a9064fbSMasahiro Yamada 		switch (e->type) {
5810a9064fbSMasahiro Yamada 		case E_OR: case E_AND:
5820a9064fbSMasahiro Yamada 			expr_eliminate_dups1(e->type, &e, &e);
5830a9064fbSMasahiro Yamada 		default:
5840a9064fbSMasahiro Yamada 			;
5850a9064fbSMasahiro Yamada 		}
5860a9064fbSMasahiro Yamada 		if (!trans_count)
5870a9064fbSMasahiro Yamada 			break;
5880a9064fbSMasahiro Yamada 		e = expr_eliminate_yn(e);
5890a9064fbSMasahiro Yamada 	}
5900a9064fbSMasahiro Yamada 	trans_count = oldcount;
5910a9064fbSMasahiro Yamada 	return e;
5920a9064fbSMasahiro Yamada }
5930a9064fbSMasahiro Yamada 
expr_transform(struct expr * e)5940a9064fbSMasahiro Yamada struct expr *expr_transform(struct expr *e)
5950a9064fbSMasahiro Yamada {
5960a9064fbSMasahiro Yamada 	struct expr *tmp;
5970a9064fbSMasahiro Yamada 
5980a9064fbSMasahiro Yamada 	if (!e)
5990a9064fbSMasahiro Yamada 		return NULL;
6000a9064fbSMasahiro Yamada 	switch (e->type) {
6010a9064fbSMasahiro Yamada 	case E_EQUAL:
602*bf7ab1e7SMasahiro Yamada 	case E_GEQ:
603*bf7ab1e7SMasahiro Yamada 	case E_GTH:
604*bf7ab1e7SMasahiro Yamada 	case E_LEQ:
605*bf7ab1e7SMasahiro Yamada 	case E_LTH:
6060a9064fbSMasahiro Yamada 	case E_UNEQUAL:
6070a9064fbSMasahiro Yamada 	case E_SYMBOL:
6080a9064fbSMasahiro Yamada 	case E_LIST:
6090a9064fbSMasahiro Yamada 		break;
6100a9064fbSMasahiro Yamada 	default:
6110a9064fbSMasahiro Yamada 		e->left.expr = expr_transform(e->left.expr);
6120a9064fbSMasahiro Yamada 		e->right.expr = expr_transform(e->right.expr);
6130a9064fbSMasahiro Yamada 	}
6140a9064fbSMasahiro Yamada 
6150a9064fbSMasahiro Yamada 	switch (e->type) {
6160a9064fbSMasahiro Yamada 	case E_EQUAL:
6170a9064fbSMasahiro Yamada 		if (e->left.sym->type != S_BOOLEAN)
6180a9064fbSMasahiro Yamada 			break;
6190a9064fbSMasahiro Yamada 		if (e->right.sym == &symbol_no) {
6200a9064fbSMasahiro Yamada 			e->type = E_NOT;
6210a9064fbSMasahiro Yamada 			e->left.expr = expr_alloc_symbol(e->left.sym);
6220a9064fbSMasahiro Yamada 			e->right.sym = NULL;
6230a9064fbSMasahiro Yamada 			break;
6240a9064fbSMasahiro Yamada 		}
6250a9064fbSMasahiro Yamada 		if (e->right.sym == &symbol_mod) {
6260a9064fbSMasahiro Yamada 			printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
6270a9064fbSMasahiro Yamada 			e->type = E_SYMBOL;
6280a9064fbSMasahiro Yamada 			e->left.sym = &symbol_no;
6290a9064fbSMasahiro Yamada 			e->right.sym = NULL;
6300a9064fbSMasahiro Yamada 			break;
6310a9064fbSMasahiro Yamada 		}
6320a9064fbSMasahiro Yamada 		if (e->right.sym == &symbol_yes) {
6330a9064fbSMasahiro Yamada 			e->type = E_SYMBOL;
6340a9064fbSMasahiro Yamada 			e->right.sym = NULL;
6350a9064fbSMasahiro Yamada 			break;
6360a9064fbSMasahiro Yamada 		}
6370a9064fbSMasahiro Yamada 		break;
6380a9064fbSMasahiro Yamada 	case E_UNEQUAL:
6390a9064fbSMasahiro Yamada 		if (e->left.sym->type != S_BOOLEAN)
6400a9064fbSMasahiro Yamada 			break;
6410a9064fbSMasahiro Yamada 		if (e->right.sym == &symbol_no) {
6420a9064fbSMasahiro Yamada 			e->type = E_SYMBOL;
6430a9064fbSMasahiro Yamada 			e->right.sym = NULL;
6440a9064fbSMasahiro Yamada 			break;
6450a9064fbSMasahiro Yamada 		}
6460a9064fbSMasahiro Yamada 		if (e->right.sym == &symbol_mod) {
6470a9064fbSMasahiro Yamada 			printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
6480a9064fbSMasahiro Yamada 			e->type = E_SYMBOL;
6490a9064fbSMasahiro Yamada 			e->left.sym = &symbol_yes;
6500a9064fbSMasahiro Yamada 			e->right.sym = NULL;
6510a9064fbSMasahiro Yamada 			break;
6520a9064fbSMasahiro Yamada 		}
6530a9064fbSMasahiro Yamada 		if (e->right.sym == &symbol_yes) {
6540a9064fbSMasahiro Yamada 			e->type = E_NOT;
6550a9064fbSMasahiro Yamada 			e->left.expr = expr_alloc_symbol(e->left.sym);
6560a9064fbSMasahiro Yamada 			e->right.sym = NULL;
6570a9064fbSMasahiro Yamada 			break;
6580a9064fbSMasahiro Yamada 		}
6590a9064fbSMasahiro Yamada 		break;
6600a9064fbSMasahiro Yamada 	case E_NOT:
6610a9064fbSMasahiro Yamada 		switch (e->left.expr->type) {
6620a9064fbSMasahiro Yamada 		case E_NOT:
6630a9064fbSMasahiro Yamada 			// !!a -> a
6640a9064fbSMasahiro Yamada 			tmp = e->left.expr->left.expr;
6650a9064fbSMasahiro Yamada 			free(e->left.expr);
6660a9064fbSMasahiro Yamada 			free(e);
6670a9064fbSMasahiro Yamada 			e = tmp;
6680a9064fbSMasahiro Yamada 			e = expr_transform(e);
6690a9064fbSMasahiro Yamada 			break;
6700a9064fbSMasahiro Yamada 		case E_EQUAL:
6710a9064fbSMasahiro Yamada 		case E_UNEQUAL:
6720a9064fbSMasahiro Yamada 			// !a='x' -> a!='x'
6730a9064fbSMasahiro Yamada 			tmp = e->left.expr;
6740a9064fbSMasahiro Yamada 			free(e);
6750a9064fbSMasahiro Yamada 			e = tmp;
6760a9064fbSMasahiro Yamada 			e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
6770a9064fbSMasahiro Yamada 			break;
678*bf7ab1e7SMasahiro Yamada 		case E_LEQ:
679*bf7ab1e7SMasahiro Yamada 		case E_GEQ:
680*bf7ab1e7SMasahiro Yamada 			// !a<='x' -> a>'x'
681*bf7ab1e7SMasahiro Yamada 			tmp = e->left.expr;
682*bf7ab1e7SMasahiro Yamada 			free(e);
683*bf7ab1e7SMasahiro Yamada 			e = tmp;
684*bf7ab1e7SMasahiro Yamada 			e->type = e->type == E_LEQ ? E_GTH : E_LTH;
685*bf7ab1e7SMasahiro Yamada 			break;
686*bf7ab1e7SMasahiro Yamada 		case E_LTH:
687*bf7ab1e7SMasahiro Yamada 		case E_GTH:
688*bf7ab1e7SMasahiro Yamada 			// !a<'x' -> a>='x'
689*bf7ab1e7SMasahiro Yamada 			tmp = e->left.expr;
690*bf7ab1e7SMasahiro Yamada 			free(e);
691*bf7ab1e7SMasahiro Yamada 			e = tmp;
692*bf7ab1e7SMasahiro Yamada 			e->type = e->type == E_LTH ? E_GEQ : E_LEQ;
693*bf7ab1e7SMasahiro Yamada 			break;
6940a9064fbSMasahiro Yamada 		case E_OR:
6950a9064fbSMasahiro Yamada 			// !(a || b) -> !a && !b
6960a9064fbSMasahiro Yamada 			tmp = e->left.expr;
6970a9064fbSMasahiro Yamada 			e->type = E_AND;
6980a9064fbSMasahiro Yamada 			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
6990a9064fbSMasahiro Yamada 			tmp->type = E_NOT;
7000a9064fbSMasahiro Yamada 			tmp->right.expr = NULL;
7010a9064fbSMasahiro Yamada 			e = expr_transform(e);
7020a9064fbSMasahiro Yamada 			break;
7030a9064fbSMasahiro Yamada 		case E_AND:
7040a9064fbSMasahiro Yamada 			// !(a && b) -> !a || !b
7050a9064fbSMasahiro Yamada 			tmp = e->left.expr;
7060a9064fbSMasahiro Yamada 			e->type = E_OR;
7070a9064fbSMasahiro Yamada 			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
7080a9064fbSMasahiro Yamada 			tmp->type = E_NOT;
7090a9064fbSMasahiro Yamada 			tmp->right.expr = NULL;
7100a9064fbSMasahiro Yamada 			e = expr_transform(e);
7110a9064fbSMasahiro Yamada 			break;
7120a9064fbSMasahiro Yamada 		case E_SYMBOL:
7130a9064fbSMasahiro Yamada 			if (e->left.expr->left.sym == &symbol_yes) {
7140a9064fbSMasahiro Yamada 				// !'y' -> 'n'
7150a9064fbSMasahiro Yamada 				tmp = e->left.expr;
7160a9064fbSMasahiro Yamada 				free(e);
7170a9064fbSMasahiro Yamada 				e = tmp;
7180a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
7190a9064fbSMasahiro Yamada 				e->left.sym = &symbol_no;
7200a9064fbSMasahiro Yamada 				break;
7210a9064fbSMasahiro Yamada 			}
7220a9064fbSMasahiro Yamada 			if (e->left.expr->left.sym == &symbol_mod) {
7230a9064fbSMasahiro Yamada 				// !'m' -> 'm'
7240a9064fbSMasahiro Yamada 				tmp = e->left.expr;
7250a9064fbSMasahiro Yamada 				free(e);
7260a9064fbSMasahiro Yamada 				e = tmp;
7270a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
7280a9064fbSMasahiro Yamada 				e->left.sym = &symbol_mod;
7290a9064fbSMasahiro Yamada 				break;
7300a9064fbSMasahiro Yamada 			}
7310a9064fbSMasahiro Yamada 			if (e->left.expr->left.sym == &symbol_no) {
7320a9064fbSMasahiro Yamada 				// !'n' -> 'y'
7330a9064fbSMasahiro Yamada 				tmp = e->left.expr;
7340a9064fbSMasahiro Yamada 				free(e);
7350a9064fbSMasahiro Yamada 				e = tmp;
7360a9064fbSMasahiro Yamada 				e->type = E_SYMBOL;
7370a9064fbSMasahiro Yamada 				e->left.sym = &symbol_yes;
7380a9064fbSMasahiro Yamada 				break;
7390a9064fbSMasahiro Yamada 			}
7400a9064fbSMasahiro Yamada 			break;
7410a9064fbSMasahiro Yamada 		default:
7420a9064fbSMasahiro Yamada 			;
7430a9064fbSMasahiro Yamada 		}
7440a9064fbSMasahiro Yamada 		break;
7450a9064fbSMasahiro Yamada 	default:
7460a9064fbSMasahiro Yamada 		;
7470a9064fbSMasahiro Yamada 	}
7480a9064fbSMasahiro Yamada 	return e;
7490a9064fbSMasahiro Yamada }
7500a9064fbSMasahiro Yamada 
expr_contains_symbol(struct expr * dep,struct symbol * sym)7510a9064fbSMasahiro Yamada int expr_contains_symbol(struct expr *dep, struct symbol *sym)
7520a9064fbSMasahiro Yamada {
7530a9064fbSMasahiro Yamada 	if (!dep)
7540a9064fbSMasahiro Yamada 		return 0;
7550a9064fbSMasahiro Yamada 
7560a9064fbSMasahiro Yamada 	switch (dep->type) {
7570a9064fbSMasahiro Yamada 	case E_AND:
7580a9064fbSMasahiro Yamada 	case E_OR:
7590a9064fbSMasahiro Yamada 		return expr_contains_symbol(dep->left.expr, sym) ||
7600a9064fbSMasahiro Yamada 		       expr_contains_symbol(dep->right.expr, sym);
7610a9064fbSMasahiro Yamada 	case E_SYMBOL:
7620a9064fbSMasahiro Yamada 		return dep->left.sym == sym;
7630a9064fbSMasahiro Yamada 	case E_EQUAL:
764*bf7ab1e7SMasahiro Yamada 	case E_GEQ:
765*bf7ab1e7SMasahiro Yamada 	case E_GTH:
766*bf7ab1e7SMasahiro Yamada 	case E_LEQ:
767*bf7ab1e7SMasahiro Yamada 	case E_LTH:
7680a9064fbSMasahiro Yamada 	case E_UNEQUAL:
7690a9064fbSMasahiro Yamada 		return dep->left.sym == sym ||
7700a9064fbSMasahiro Yamada 		       dep->right.sym == sym;
7710a9064fbSMasahiro Yamada 	case E_NOT:
7720a9064fbSMasahiro Yamada 		return expr_contains_symbol(dep->left.expr, sym);
7730a9064fbSMasahiro Yamada 	default:
7740a9064fbSMasahiro Yamada 		;
7750a9064fbSMasahiro Yamada 	}
7760a9064fbSMasahiro Yamada 	return 0;
7770a9064fbSMasahiro Yamada }
7780a9064fbSMasahiro Yamada 
expr_depends_symbol(struct expr * dep,struct symbol * sym)7790a9064fbSMasahiro Yamada bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
7800a9064fbSMasahiro Yamada {
7810a9064fbSMasahiro Yamada 	if (!dep)
7820a9064fbSMasahiro Yamada 		return false;
7830a9064fbSMasahiro Yamada 
7840a9064fbSMasahiro Yamada 	switch (dep->type) {
7850a9064fbSMasahiro Yamada 	case E_AND:
7860a9064fbSMasahiro Yamada 		return expr_depends_symbol(dep->left.expr, sym) ||
7870a9064fbSMasahiro Yamada 		       expr_depends_symbol(dep->right.expr, sym);
7880a9064fbSMasahiro Yamada 	case E_SYMBOL:
7890a9064fbSMasahiro Yamada 		return dep->left.sym == sym;
7900a9064fbSMasahiro Yamada 	case E_EQUAL:
7910a9064fbSMasahiro Yamada 		if (dep->left.sym == sym) {
7920a9064fbSMasahiro Yamada 			if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
7930a9064fbSMasahiro Yamada 				return true;
7940a9064fbSMasahiro Yamada 		}
7950a9064fbSMasahiro Yamada 		break;
7960a9064fbSMasahiro Yamada 	case E_UNEQUAL:
7970a9064fbSMasahiro Yamada 		if (dep->left.sym == sym) {
7980a9064fbSMasahiro Yamada 			if (dep->right.sym == &symbol_no)
7990a9064fbSMasahiro Yamada 				return true;
8000a9064fbSMasahiro Yamada 		}
8010a9064fbSMasahiro Yamada 		break;
8020a9064fbSMasahiro Yamada 	default:
8030a9064fbSMasahiro Yamada 		;
8040a9064fbSMasahiro Yamada 	}
8050a9064fbSMasahiro Yamada  	return false;
8060a9064fbSMasahiro Yamada }
8070a9064fbSMasahiro Yamada 
expr_trans_compare(struct expr * e,enum expr_type type,struct symbol * sym)8080a9064fbSMasahiro Yamada struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
8090a9064fbSMasahiro Yamada {
8100a9064fbSMasahiro Yamada 	struct expr *e1, *e2;
8110a9064fbSMasahiro Yamada 
8120a9064fbSMasahiro Yamada 	if (!e) {
8130a9064fbSMasahiro Yamada 		e = expr_alloc_symbol(sym);
8140a9064fbSMasahiro Yamada 		if (type == E_UNEQUAL)
8150a9064fbSMasahiro Yamada 			e = expr_alloc_one(E_NOT, e);
8160a9064fbSMasahiro Yamada 		return e;
8170a9064fbSMasahiro Yamada 	}
8180a9064fbSMasahiro Yamada 	switch (e->type) {
8190a9064fbSMasahiro Yamada 	case E_AND:
8200a9064fbSMasahiro Yamada 		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
8210a9064fbSMasahiro Yamada 		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
8220a9064fbSMasahiro Yamada 		if (sym == &symbol_yes)
8230a9064fbSMasahiro Yamada 			e = expr_alloc_two(E_AND, e1, e2);
8240a9064fbSMasahiro Yamada 		if (sym == &symbol_no)
8250a9064fbSMasahiro Yamada 			e = expr_alloc_two(E_OR, e1, e2);
8260a9064fbSMasahiro Yamada 		if (type == E_UNEQUAL)
8270a9064fbSMasahiro Yamada 			e = expr_alloc_one(E_NOT, e);
8280a9064fbSMasahiro Yamada 		return e;
8290a9064fbSMasahiro Yamada 	case E_OR:
8300a9064fbSMasahiro Yamada 		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
8310a9064fbSMasahiro Yamada 		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
8320a9064fbSMasahiro Yamada 		if (sym == &symbol_yes)
8330a9064fbSMasahiro Yamada 			e = expr_alloc_two(E_OR, e1, e2);
8340a9064fbSMasahiro Yamada 		if (sym == &symbol_no)
8350a9064fbSMasahiro Yamada 			e = expr_alloc_two(E_AND, e1, e2);
8360a9064fbSMasahiro Yamada 		if (type == E_UNEQUAL)
8370a9064fbSMasahiro Yamada 			e = expr_alloc_one(E_NOT, e);
8380a9064fbSMasahiro Yamada 		return e;
8390a9064fbSMasahiro Yamada 	case E_NOT:
8400a9064fbSMasahiro Yamada 		return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
8410a9064fbSMasahiro Yamada 	case E_UNEQUAL:
842*bf7ab1e7SMasahiro Yamada 	case E_LTH:
843*bf7ab1e7SMasahiro Yamada 	case E_LEQ:
844*bf7ab1e7SMasahiro Yamada 	case E_GTH:
845*bf7ab1e7SMasahiro Yamada 	case E_GEQ:
8460a9064fbSMasahiro Yamada 	case E_EQUAL:
8470a9064fbSMasahiro Yamada 		if (type == E_EQUAL) {
8480a9064fbSMasahiro Yamada 			if (sym == &symbol_yes)
8490a9064fbSMasahiro Yamada 				return expr_copy(e);
8500a9064fbSMasahiro Yamada 			if (sym == &symbol_mod)
8510a9064fbSMasahiro Yamada 				return expr_alloc_symbol(&symbol_no);
8520a9064fbSMasahiro Yamada 			if (sym == &symbol_no)
8530a9064fbSMasahiro Yamada 				return expr_alloc_one(E_NOT, expr_copy(e));
8540a9064fbSMasahiro Yamada 		} else {
8550a9064fbSMasahiro Yamada 			if (sym == &symbol_yes)
8560a9064fbSMasahiro Yamada 				return expr_alloc_one(E_NOT, expr_copy(e));
8570a9064fbSMasahiro Yamada 			if (sym == &symbol_mod)
8580a9064fbSMasahiro Yamada 				return expr_alloc_symbol(&symbol_yes);
8590a9064fbSMasahiro Yamada 			if (sym == &symbol_no)
8600a9064fbSMasahiro Yamada 				return expr_copy(e);
8610a9064fbSMasahiro Yamada 		}
8620a9064fbSMasahiro Yamada 		break;
8630a9064fbSMasahiro Yamada 	case E_SYMBOL:
8640a9064fbSMasahiro Yamada 		return expr_alloc_comp(type, e->left.sym, sym);
8650a9064fbSMasahiro Yamada 	case E_LIST:
8660a9064fbSMasahiro Yamada 	case E_RANGE:
8670a9064fbSMasahiro Yamada 	case E_NONE:
8680a9064fbSMasahiro Yamada 		/* panic */;
8690a9064fbSMasahiro Yamada 	}
8700a9064fbSMasahiro Yamada 	return NULL;
8710a9064fbSMasahiro Yamada }
8720a9064fbSMasahiro Yamada 
873*bf7ab1e7SMasahiro Yamada enum string_value_kind {
874*bf7ab1e7SMasahiro Yamada 	k_string,
875*bf7ab1e7SMasahiro Yamada 	k_signed,
876*bf7ab1e7SMasahiro Yamada 	k_unsigned,
877*bf7ab1e7SMasahiro Yamada 	k_invalid
878*bf7ab1e7SMasahiro Yamada };
879*bf7ab1e7SMasahiro Yamada 
880*bf7ab1e7SMasahiro Yamada union string_value {
881*bf7ab1e7SMasahiro Yamada 	unsigned long long u;
882*bf7ab1e7SMasahiro Yamada 	signed long long s;
883*bf7ab1e7SMasahiro Yamada };
884*bf7ab1e7SMasahiro Yamada 
expr_parse_string(const char * str,enum symbol_type type,union string_value * val)885*bf7ab1e7SMasahiro Yamada static enum string_value_kind expr_parse_string(const char *str,
886*bf7ab1e7SMasahiro Yamada 						enum symbol_type type,
887*bf7ab1e7SMasahiro Yamada 						union string_value *val)
888*bf7ab1e7SMasahiro Yamada {
889*bf7ab1e7SMasahiro Yamada 	char *tail;
890*bf7ab1e7SMasahiro Yamada 	enum string_value_kind kind;
891*bf7ab1e7SMasahiro Yamada 
892*bf7ab1e7SMasahiro Yamada 	errno = 0;
893*bf7ab1e7SMasahiro Yamada 	switch (type) {
894*bf7ab1e7SMasahiro Yamada 	case S_BOOLEAN:
895*bf7ab1e7SMasahiro Yamada 	case S_TRISTATE:
896*bf7ab1e7SMasahiro Yamada 		return k_string;
897*bf7ab1e7SMasahiro Yamada 	case S_INT:
898*bf7ab1e7SMasahiro Yamada 		val->s = strtoll(str, &tail, 10);
899*bf7ab1e7SMasahiro Yamada 		kind = k_signed;
900*bf7ab1e7SMasahiro Yamada 		break;
901*bf7ab1e7SMasahiro Yamada 	case S_HEX:
902*bf7ab1e7SMasahiro Yamada 		val->u = strtoull(str, &tail, 16);
903*bf7ab1e7SMasahiro Yamada 		kind = k_unsigned;
904*bf7ab1e7SMasahiro Yamada 		break;
905*bf7ab1e7SMasahiro Yamada 	case S_STRING:
906*bf7ab1e7SMasahiro Yamada 	case S_UNKNOWN:
907*bf7ab1e7SMasahiro Yamada 		val->s = strtoll(str, &tail, 0);
908*bf7ab1e7SMasahiro Yamada 		kind = k_signed;
909*bf7ab1e7SMasahiro Yamada 		break;
910*bf7ab1e7SMasahiro Yamada 	default:
911*bf7ab1e7SMasahiro Yamada 		return k_invalid;
912*bf7ab1e7SMasahiro Yamada 	}
913*bf7ab1e7SMasahiro Yamada 	return !errno && !*tail && tail > str && isxdigit(tail[-1])
914*bf7ab1e7SMasahiro Yamada 	       ? kind : k_string;
915*bf7ab1e7SMasahiro Yamada }
916*bf7ab1e7SMasahiro Yamada 
expr_calc_value(struct expr * e)9170a9064fbSMasahiro Yamada tristate expr_calc_value(struct expr *e)
9180a9064fbSMasahiro Yamada {
9190a9064fbSMasahiro Yamada 	tristate val1, val2;
9200a9064fbSMasahiro Yamada 	const char *str1, *str2;
921*bf7ab1e7SMasahiro Yamada 	enum string_value_kind k1 = k_string, k2 = k_string;
922*bf7ab1e7SMasahiro Yamada 	union string_value lval = {}, rval = {};
923*bf7ab1e7SMasahiro Yamada 	int res;
9240a9064fbSMasahiro Yamada 
9250a9064fbSMasahiro Yamada 	if (!e)
9260a9064fbSMasahiro Yamada 		return yes;
9270a9064fbSMasahiro Yamada 
9280a9064fbSMasahiro Yamada 	switch (e->type) {
9290a9064fbSMasahiro Yamada 	case E_SYMBOL:
9300a9064fbSMasahiro Yamada 		sym_calc_value(e->left.sym);
9310a9064fbSMasahiro Yamada 		return e->left.sym->curr.tri;
9320a9064fbSMasahiro Yamada 	case E_AND:
9330a9064fbSMasahiro Yamada 		val1 = expr_calc_value(e->left.expr);
9340a9064fbSMasahiro Yamada 		val2 = expr_calc_value(e->right.expr);
9350a9064fbSMasahiro Yamada 		return EXPR_AND(val1, val2);
9360a9064fbSMasahiro Yamada 	case E_OR:
9370a9064fbSMasahiro Yamada 		val1 = expr_calc_value(e->left.expr);
9380a9064fbSMasahiro Yamada 		val2 = expr_calc_value(e->right.expr);
9390a9064fbSMasahiro Yamada 		return EXPR_OR(val1, val2);
9400a9064fbSMasahiro Yamada 	case E_NOT:
9410a9064fbSMasahiro Yamada 		val1 = expr_calc_value(e->left.expr);
9420a9064fbSMasahiro Yamada 		return EXPR_NOT(val1);
9430a9064fbSMasahiro Yamada 	case E_EQUAL:
944*bf7ab1e7SMasahiro Yamada 	case E_GEQ:
945*bf7ab1e7SMasahiro Yamada 	case E_GTH:
946*bf7ab1e7SMasahiro Yamada 	case E_LEQ:
947*bf7ab1e7SMasahiro Yamada 	case E_LTH:
9480a9064fbSMasahiro Yamada 	case E_UNEQUAL:
949*bf7ab1e7SMasahiro Yamada 		break;
9500a9064fbSMasahiro Yamada 	default:
9510a9064fbSMasahiro Yamada 		printf("expr_calc_value: %d?\n", e->type);
9520a9064fbSMasahiro Yamada 		return no;
9530a9064fbSMasahiro Yamada 	}
954*bf7ab1e7SMasahiro Yamada 
955*bf7ab1e7SMasahiro Yamada 	sym_calc_value(e->left.sym);
956*bf7ab1e7SMasahiro Yamada 	sym_calc_value(e->right.sym);
957*bf7ab1e7SMasahiro Yamada 	str1 = sym_get_string_value(e->left.sym);
958*bf7ab1e7SMasahiro Yamada 	str2 = sym_get_string_value(e->right.sym);
959*bf7ab1e7SMasahiro Yamada 
960*bf7ab1e7SMasahiro Yamada 	if (e->left.sym->type != S_STRING || e->right.sym->type != S_STRING) {
961*bf7ab1e7SMasahiro Yamada 		k1 = expr_parse_string(str1, e->left.sym->type, &lval);
962*bf7ab1e7SMasahiro Yamada 		k2 = expr_parse_string(str2, e->right.sym->type, &rval);
963*bf7ab1e7SMasahiro Yamada 	}
964*bf7ab1e7SMasahiro Yamada 
965*bf7ab1e7SMasahiro Yamada 	if (k1 == k_string || k2 == k_string)
966*bf7ab1e7SMasahiro Yamada 		res = strcmp(str1, str2);
967*bf7ab1e7SMasahiro Yamada 	else if (k1 == k_invalid || k2 == k_invalid) {
968*bf7ab1e7SMasahiro Yamada 		if (e->type != E_EQUAL && e->type != E_UNEQUAL) {
969*bf7ab1e7SMasahiro Yamada 			printf("Cannot compare \"%s\" and \"%s\"\n", str1, str2);
970*bf7ab1e7SMasahiro Yamada 			return no;
971*bf7ab1e7SMasahiro Yamada 		}
972*bf7ab1e7SMasahiro Yamada 		res = strcmp(str1, str2);
973*bf7ab1e7SMasahiro Yamada 	} else if (k1 == k_unsigned || k2 == k_unsigned)
974*bf7ab1e7SMasahiro Yamada 		res = (lval.u > rval.u) - (lval.u < rval.u);
975*bf7ab1e7SMasahiro Yamada 	else /* if (k1 == k_signed && k2 == k_signed) */
976*bf7ab1e7SMasahiro Yamada 		res = (lval.s > rval.s) - (lval.s < rval.s);
977*bf7ab1e7SMasahiro Yamada 
978*bf7ab1e7SMasahiro Yamada 	switch(e->type) {
979*bf7ab1e7SMasahiro Yamada 	case E_EQUAL:
980*bf7ab1e7SMasahiro Yamada 		return res ? no : yes;
981*bf7ab1e7SMasahiro Yamada 	case E_GEQ:
982*bf7ab1e7SMasahiro Yamada 		return res >= 0 ? yes : no;
983*bf7ab1e7SMasahiro Yamada 	case E_GTH:
984*bf7ab1e7SMasahiro Yamada 		return res > 0 ? yes : no;
985*bf7ab1e7SMasahiro Yamada 	case E_LEQ:
986*bf7ab1e7SMasahiro Yamada 		return res <= 0 ? yes : no;
987*bf7ab1e7SMasahiro Yamada 	case E_LTH:
988*bf7ab1e7SMasahiro Yamada 		return res < 0 ? yes : no;
989*bf7ab1e7SMasahiro Yamada 	case E_UNEQUAL:
990*bf7ab1e7SMasahiro Yamada 		return res ? yes : no;
991*bf7ab1e7SMasahiro Yamada 	default:
992*bf7ab1e7SMasahiro Yamada 		printf("expr_calc_value: relation %d?\n", e->type);
993*bf7ab1e7SMasahiro Yamada 		return no;
994*bf7ab1e7SMasahiro Yamada 	}
9950a9064fbSMasahiro Yamada }
9960a9064fbSMasahiro Yamada 
expr_compare_type(enum expr_type t1,enum expr_type t2)9979b5f0b1dSMasahiro Yamada static int expr_compare_type(enum expr_type t1, enum expr_type t2)
9980a9064fbSMasahiro Yamada {
9990a9064fbSMasahiro Yamada 	if (t1 == t2)
10000a9064fbSMasahiro Yamada 		return 0;
10010a9064fbSMasahiro Yamada 	switch (t1) {
1002*bf7ab1e7SMasahiro Yamada 	case E_LEQ:
1003*bf7ab1e7SMasahiro Yamada 	case E_LTH:
1004*bf7ab1e7SMasahiro Yamada 	case E_GEQ:
1005*bf7ab1e7SMasahiro Yamada 	case E_GTH:
1006*bf7ab1e7SMasahiro Yamada 		if (t2 == E_EQUAL || t2 == E_UNEQUAL)
1007*bf7ab1e7SMasahiro Yamada 			return 1;
10080a9064fbSMasahiro Yamada 	case E_EQUAL:
10090a9064fbSMasahiro Yamada 	case E_UNEQUAL:
10100a9064fbSMasahiro Yamada 		if (t2 == E_NOT)
10110a9064fbSMasahiro Yamada 			return 1;
10120a9064fbSMasahiro Yamada 	case E_NOT:
10130a9064fbSMasahiro Yamada 		if (t2 == E_AND)
10140a9064fbSMasahiro Yamada 			return 1;
10150a9064fbSMasahiro Yamada 	case E_AND:
10160a9064fbSMasahiro Yamada 		if (t2 == E_OR)
10170a9064fbSMasahiro Yamada 			return 1;
10180a9064fbSMasahiro Yamada 	case E_OR:
10190a9064fbSMasahiro Yamada 		if (t2 == E_LIST)
10200a9064fbSMasahiro Yamada 			return 1;
10210a9064fbSMasahiro Yamada 	case E_LIST:
10220a9064fbSMasahiro Yamada 		if (t2 == 0)
10230a9064fbSMasahiro Yamada 			return 1;
10240a9064fbSMasahiro Yamada 	default:
10250a9064fbSMasahiro Yamada 		return -1;
10260a9064fbSMasahiro Yamada 	}
10270a9064fbSMasahiro Yamada 	printf("[%dgt%d?]", t1, t2);
10280a9064fbSMasahiro Yamada 	return 0;
10290a9064fbSMasahiro Yamada }
10300a9064fbSMasahiro Yamada 
10310a9064fbSMasahiro Yamada static inline struct expr *
expr_get_leftmost_symbol(const struct expr * e)10320a9064fbSMasahiro Yamada expr_get_leftmost_symbol(const struct expr *e)
10330a9064fbSMasahiro Yamada {
10340a9064fbSMasahiro Yamada 
10350a9064fbSMasahiro Yamada 	if (e == NULL)
10360a9064fbSMasahiro Yamada 		return NULL;
10370a9064fbSMasahiro Yamada 
10380a9064fbSMasahiro Yamada 	while (e->type != E_SYMBOL)
10390a9064fbSMasahiro Yamada 		e = e->left.expr;
10400a9064fbSMasahiro Yamada 
10410a9064fbSMasahiro Yamada 	return expr_copy(e);
10420a9064fbSMasahiro Yamada }
10430a9064fbSMasahiro Yamada 
10440a9064fbSMasahiro Yamada /*
10450a9064fbSMasahiro Yamada  * Given expression `e1' and `e2', returns the leaf of the longest
10460a9064fbSMasahiro Yamada  * sub-expression of `e1' not containing 'e2.
10470a9064fbSMasahiro Yamada  */
expr_simplify_unmet_dep(struct expr * e1,struct expr * e2)10480a9064fbSMasahiro Yamada struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2)
10490a9064fbSMasahiro Yamada {
10500a9064fbSMasahiro Yamada 	struct expr *ret;
10510a9064fbSMasahiro Yamada 
10520a9064fbSMasahiro Yamada 	switch (e1->type) {
10530a9064fbSMasahiro Yamada 	case E_OR:
10540a9064fbSMasahiro Yamada 		return expr_alloc_and(
10550a9064fbSMasahiro Yamada 		    expr_simplify_unmet_dep(e1->left.expr, e2),
10560a9064fbSMasahiro Yamada 		    expr_simplify_unmet_dep(e1->right.expr, e2));
10570a9064fbSMasahiro Yamada 	case E_AND: {
10580a9064fbSMasahiro Yamada 		struct expr *e;
10590a9064fbSMasahiro Yamada 		e = expr_alloc_and(expr_copy(e1), expr_copy(e2));
10600a9064fbSMasahiro Yamada 		e = expr_eliminate_dups(e);
10610a9064fbSMasahiro Yamada 		ret = (!expr_eq(e, e1)) ? e1 : NULL;
10620a9064fbSMasahiro Yamada 		expr_free(e);
10630a9064fbSMasahiro Yamada 		break;
10640a9064fbSMasahiro Yamada 		}
10650a9064fbSMasahiro Yamada 	default:
10660a9064fbSMasahiro Yamada 		ret = e1;
10670a9064fbSMasahiro Yamada 		break;
10680a9064fbSMasahiro Yamada 	}
10690a9064fbSMasahiro Yamada 
10700a9064fbSMasahiro Yamada 	return expr_get_leftmost_symbol(ret);
10710a9064fbSMasahiro Yamada }
10720a9064fbSMasahiro Yamada 
expr_print(struct expr * e,void (* fn)(void *,struct symbol *,const char *),void * data,int prevtoken)10730a9064fbSMasahiro Yamada void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
10740a9064fbSMasahiro Yamada {
10750a9064fbSMasahiro Yamada 	if (!e) {
10760a9064fbSMasahiro Yamada 		fn(data, NULL, "y");
10770a9064fbSMasahiro Yamada 		return;
10780a9064fbSMasahiro Yamada 	}
10790a9064fbSMasahiro Yamada 
10800a9064fbSMasahiro Yamada 	if (expr_compare_type(prevtoken, e->type) > 0)
10810a9064fbSMasahiro Yamada 		fn(data, NULL, "(");
10820a9064fbSMasahiro Yamada 	switch (e->type) {
10830a9064fbSMasahiro Yamada 	case E_SYMBOL:
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 		break;
10890a9064fbSMasahiro Yamada 	case E_NOT:
10900a9064fbSMasahiro Yamada 		fn(data, NULL, "!");
10910a9064fbSMasahiro Yamada 		expr_print(e->left.expr, fn, data, E_NOT);
10920a9064fbSMasahiro Yamada 		break;
10930a9064fbSMasahiro Yamada 	case E_EQUAL:
10940a9064fbSMasahiro Yamada 		if (e->left.sym->name)
10950a9064fbSMasahiro Yamada 			fn(data, e->left.sym, e->left.sym->name);
10960a9064fbSMasahiro Yamada 		else
10970a9064fbSMasahiro Yamada 			fn(data, NULL, "<choice>");
10980a9064fbSMasahiro Yamada 		fn(data, NULL, "=");
10990a9064fbSMasahiro Yamada 		fn(data, e->right.sym, e->right.sym->name);
11000a9064fbSMasahiro Yamada 		break;
1101*bf7ab1e7SMasahiro Yamada 	case E_LEQ:
1102*bf7ab1e7SMasahiro Yamada 	case E_LTH:
1103*bf7ab1e7SMasahiro Yamada 		if (e->left.sym->name)
1104*bf7ab1e7SMasahiro Yamada 			fn(data, e->left.sym, e->left.sym->name);
1105*bf7ab1e7SMasahiro Yamada 		else
1106*bf7ab1e7SMasahiro Yamada 			fn(data, NULL, "<choice>");
1107*bf7ab1e7SMasahiro Yamada 		fn(data, NULL, e->type == E_LEQ ? "<=" : "<");
1108*bf7ab1e7SMasahiro Yamada 		fn(data, e->right.sym, e->right.sym->name);
1109*bf7ab1e7SMasahiro Yamada 		break;
1110*bf7ab1e7SMasahiro Yamada 	case E_GEQ:
1111*bf7ab1e7SMasahiro Yamada 	case E_GTH:
1112*bf7ab1e7SMasahiro Yamada 		if (e->left.sym->name)
1113*bf7ab1e7SMasahiro Yamada 			fn(data, e->left.sym, e->left.sym->name);
1114*bf7ab1e7SMasahiro Yamada 		else
1115*bf7ab1e7SMasahiro Yamada 			fn(data, NULL, "<choice>");
1116*bf7ab1e7SMasahiro Yamada 		fn(data, NULL, e->type == E_GEQ ? ">=" : ">");
1117*bf7ab1e7SMasahiro Yamada 		fn(data, e->right.sym, e->right.sym->name);
1118*bf7ab1e7SMasahiro Yamada 		break;
11190a9064fbSMasahiro Yamada 	case E_UNEQUAL:
11200a9064fbSMasahiro Yamada 		if (e->left.sym->name)
11210a9064fbSMasahiro Yamada 			fn(data, e->left.sym, e->left.sym->name);
11220a9064fbSMasahiro Yamada 		else
11230a9064fbSMasahiro Yamada 			fn(data, NULL, "<choice>");
11240a9064fbSMasahiro Yamada 		fn(data, NULL, "!=");
11250a9064fbSMasahiro Yamada 		fn(data, e->right.sym, e->right.sym->name);
11260a9064fbSMasahiro Yamada 		break;
11270a9064fbSMasahiro Yamada 	case E_OR:
11280a9064fbSMasahiro Yamada 		expr_print(e->left.expr, fn, data, E_OR);
11290a9064fbSMasahiro Yamada 		fn(data, NULL, " || ");
11300a9064fbSMasahiro Yamada 		expr_print(e->right.expr, fn, data, E_OR);
11310a9064fbSMasahiro Yamada 		break;
11320a9064fbSMasahiro Yamada 	case E_AND:
11330a9064fbSMasahiro Yamada 		expr_print(e->left.expr, fn, data, E_AND);
11340a9064fbSMasahiro Yamada 		fn(data, NULL, " && ");
11350a9064fbSMasahiro Yamada 		expr_print(e->right.expr, fn, data, E_AND);
11360a9064fbSMasahiro Yamada 		break;
11370a9064fbSMasahiro Yamada 	case E_LIST:
11380a9064fbSMasahiro Yamada 		fn(data, e->right.sym, e->right.sym->name);
11390a9064fbSMasahiro Yamada 		if (e->left.expr) {
11400a9064fbSMasahiro Yamada 			fn(data, NULL, " ^ ");
11410a9064fbSMasahiro Yamada 			expr_print(e->left.expr, fn, data, E_LIST);
11420a9064fbSMasahiro Yamada 		}
11430a9064fbSMasahiro Yamada 		break;
11440a9064fbSMasahiro Yamada 	case E_RANGE:
11450a9064fbSMasahiro Yamada 		fn(data, NULL, "[");
11460a9064fbSMasahiro Yamada 		fn(data, e->left.sym, e->left.sym->name);
11470a9064fbSMasahiro Yamada 		fn(data, NULL, " ");
11480a9064fbSMasahiro Yamada 		fn(data, e->right.sym, e->right.sym->name);
11490a9064fbSMasahiro Yamada 		fn(data, NULL, "]");
11500a9064fbSMasahiro Yamada 		break;
11510a9064fbSMasahiro Yamada 	default:
11520a9064fbSMasahiro Yamada 	  {
11530a9064fbSMasahiro Yamada 		char buf[32];
11540a9064fbSMasahiro Yamada 		sprintf(buf, "<unknown type %d>", e->type);
11550a9064fbSMasahiro Yamada 		fn(data, NULL, buf);
11560a9064fbSMasahiro Yamada 		break;
11570a9064fbSMasahiro Yamada 	  }
11580a9064fbSMasahiro Yamada 	}
11590a9064fbSMasahiro Yamada 	if (expr_compare_type(prevtoken, e->type) > 0)
11600a9064fbSMasahiro Yamada 		fn(data, NULL, ")");
11610a9064fbSMasahiro Yamada }
11620a9064fbSMasahiro Yamada 
expr_print_file_helper(void * data,struct symbol * sym,const char * str)11630a9064fbSMasahiro Yamada static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
11640a9064fbSMasahiro Yamada {
11650a9064fbSMasahiro Yamada 	xfwrite(str, strlen(str), 1, data);
11660a9064fbSMasahiro Yamada }
11670a9064fbSMasahiro Yamada 
expr_fprint(struct expr * e,FILE * out)11680a9064fbSMasahiro Yamada void expr_fprint(struct expr *e, FILE *out)
11690a9064fbSMasahiro Yamada {
11700a9064fbSMasahiro Yamada 	expr_print(e, expr_print_file_helper, out, E_NONE);
11710a9064fbSMasahiro Yamada }
11720a9064fbSMasahiro Yamada 
expr_print_gstr_helper(void * data,struct symbol * sym,const char * str)11730a9064fbSMasahiro Yamada static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
11740a9064fbSMasahiro Yamada {
11750a9064fbSMasahiro Yamada 	struct gstr *gs = (struct gstr*)data;
11760a9064fbSMasahiro Yamada 	const char *sym_str = NULL;
11770a9064fbSMasahiro Yamada 
11780a9064fbSMasahiro Yamada 	if (sym)
11790a9064fbSMasahiro Yamada 		sym_str = sym_get_string_value(sym);
11800a9064fbSMasahiro Yamada 
11810a9064fbSMasahiro Yamada 	if (gs->max_width) {
11820a9064fbSMasahiro Yamada 		unsigned extra_length = strlen(str);
11830a9064fbSMasahiro Yamada 		const char *last_cr = strrchr(gs->s, '\n');
11840a9064fbSMasahiro Yamada 		unsigned last_line_length;
11850a9064fbSMasahiro Yamada 
11860a9064fbSMasahiro Yamada 		if (sym_str)
11870a9064fbSMasahiro Yamada 			extra_length += 4 + strlen(sym_str);
11880a9064fbSMasahiro Yamada 
11890a9064fbSMasahiro Yamada 		if (!last_cr)
11900a9064fbSMasahiro Yamada 			last_cr = gs->s;
11910a9064fbSMasahiro Yamada 
11920a9064fbSMasahiro Yamada 		last_line_length = strlen(gs->s) - (last_cr - gs->s);
11930a9064fbSMasahiro Yamada 
11940a9064fbSMasahiro Yamada 		if ((last_line_length + extra_length) > gs->max_width)
11950a9064fbSMasahiro Yamada 			str_append(gs, "\\\n");
11960a9064fbSMasahiro Yamada 	}
11970a9064fbSMasahiro Yamada 
11980a9064fbSMasahiro Yamada 	str_append(gs, str);
11990a9064fbSMasahiro Yamada 	if (sym && sym->type != S_UNKNOWN)
12000a9064fbSMasahiro Yamada 		str_printf(gs, " [=%s]", sym_str);
12010a9064fbSMasahiro Yamada }
12020a9064fbSMasahiro Yamada 
expr_gstr_print(struct expr * e,struct gstr * gs)12030a9064fbSMasahiro Yamada void expr_gstr_print(struct expr *e, struct gstr *gs)
12040a9064fbSMasahiro Yamada {
12050a9064fbSMasahiro Yamada 	expr_print(e, expr_print_gstr_helper, gs, E_NONE);
12060a9064fbSMasahiro Yamada }
1207