11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Released under the terms of the GNU GPL v2.0.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <stdio.h>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <stdlib.h>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <string.h>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LKC_DIRECT_LINK
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "lkc.h"
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG_EXPR	0
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct expr *expr_alloc_symbol(struct symbol *sym)
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct expr *e = malloc(sizeof(*e));
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(e, 0, sizeof(*e));
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e->type = E_SYMBOL;
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e->left.sym = sym;
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return e;
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct expr *e = malloc(sizeof(*e));
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(e, 0, sizeof(*e));
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e->type = type;
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e->left.expr = ce;
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return e;
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct expr *e = malloc(sizeof(*e));
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(e, 0, sizeof(*e));
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e->type = type;
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e->left.expr = e1;
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e->right.expr = e2;
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return e;
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct expr *e = malloc(sizeof(*e));
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(e, 0, sizeof(*e));
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e->type = type;
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e->left.sym = s1;
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e->right.sym = s2;
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return e;
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!e1)
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return e2;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!e1)
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return e2;
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6717742dc743716eebbf5892add0e0bf91f541fc39Michal Marekstruct expr *expr_copy(const struct expr *org)
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct expr *e;
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!org)
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e = malloc(sizeof(*org));
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(e, org, sizeof(*org));
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (org->type) {
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_SYMBOL:
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e->left = org->left;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_NOT:
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e->left.expr = expr_copy(org->left.expr);
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_EQUAL:
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_UNEQUAL:
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e->left.sym = org->left.sym;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e->right.sym = org->right.sym;
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
907a962923359768e04137125bd479fd0dfa6117d3Roman Zippel	case E_LIST:
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e->left.expr = expr_copy(org->left.expr);
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e->right.expr = expr_copy(org->right.expr);
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printf("can't copy type %d\n", e->type);
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		free(e);
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e = NULL;
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return e;
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid expr_free(struct expr *e)
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!e)
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (e->type) {
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_SYMBOL:
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_NOT:
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_free(e->left.expr);
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_EQUAL:
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_UNEQUAL:
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_free(e->left.expr);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_free(e->right.expr);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printf("how to free type %d?\n", e->type);
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free(e);
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int trans_count;
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define e1 (*ep1)
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define e2 (*ep2)
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e1->type == type) {
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__expr_eliminate_eq(type, &e1->left.expr, &e2);
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__expr_eliminate_eq(type, &e1->right.expr, &e2);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e2->type == type) {
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__expr_eliminate_eq(type, &e1, &e2->left.expr);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__expr_eliminate_eq(type, &e1, &e2->right.expr);
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
148c0e150acde52e4661675539bf5323309270f2e83Roman Zippel	    e1->left.sym == e2->left.sym &&
149c0e150acde52e4661675539bf5323309270f2e83Roman Zippel	    (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!expr_eq(e1, e2))
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	trans_count++;
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	expr_free(e1); expr_free(e2);
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (type) {
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e1 = expr_alloc_symbol(&symbol_no);
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e2 = expr_alloc_symbol(&symbol_no);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e1 = expr_alloc_symbol(&symbol_yes);
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e2 = expr_alloc_symbol(&symbol_yes);
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		;
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!e1 || !e2)
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (e1->type) {
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__expr_eliminate_eq(e1->type, ep1, ep2);
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		;
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e1->type != e2->type) switch (e2->type) {
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__expr_eliminate_eq(e2->type, ep1, ep2);
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		;
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e1 = expr_eliminate_yn(e1);
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	e2 = expr_eliminate_yn(e2);
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef e1
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef e2
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint expr_eq(struct expr *e1, struct expr *e2)
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res, old_count;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e1->type != e2->type)
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (e1->type) {
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_EQUAL:
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_UNEQUAL:
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_SYMBOL:
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return e1->left.sym == e2->left.sym;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_NOT:
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return expr_eq(e1->left.expr, e2->left.expr);
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e1 = expr_copy(e1);
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e2 = expr_copy(e2);
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		old_count = trans_count;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_eliminate_eq(&e1, &e2);
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       e1->left.sym == e2->left.sym);
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_free(e1);
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_free(e2);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		trans_count = old_count;
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return res;
2207a962923359768e04137125bd479fd0dfa6117d3Roman Zippel	case E_LIST:
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_RANGE:
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_NONE:
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* panic */;
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (DEBUG_EXPR) {
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_fprint(e1, stdout);
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printf(" = ");
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_fprint(e2, stdout);
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printf(" ?\n");
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct expr *expr_eliminate_yn(struct expr *e)
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct expr *tmp;
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e) switch (e->type) {
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e->left.expr = expr_eliminate_yn(e->left.expr);
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e->right.expr = expr_eliminate_yn(e->right.expr);
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->left.expr->type == E_SYMBOL) {
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (e->left.expr->left.sym == &symbol_no) {
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				expr_free(e->left.expr);
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				expr_free(e->right.expr);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->type = E_SYMBOL;
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->left.sym = &symbol_no;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->right.expr = NULL;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return e;
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (e->left.expr->left.sym == &symbol_yes) {
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				free(e->left.expr);
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp = e->right.expr;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*e = *(e->right.expr);
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				free(tmp);
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return e;
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->right.expr->type == E_SYMBOL) {
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (e->right.expr->left.sym == &symbol_no) {
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				expr_free(e->left.expr);
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				expr_free(e->right.expr);
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->type = E_SYMBOL;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->left.sym = &symbol_no;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->right.expr = NULL;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return e;
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (e->right.expr->left.sym == &symbol_yes) {
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				free(e->right.expr);
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp = e->left.expr;
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*e = *(e->left.expr);
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				free(tmp);
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return e;
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e->left.expr = expr_eliminate_yn(e->left.expr);
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e->right.expr = expr_eliminate_yn(e->right.expr);
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->left.expr->type == E_SYMBOL) {
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (e->left.expr->left.sym == &symbol_no) {
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				free(e->left.expr);
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp = e->right.expr;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*e = *(e->right.expr);
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				free(tmp);
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return e;
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (e->left.expr->left.sym == &symbol_yes) {
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				expr_free(e->left.expr);
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				expr_free(e->right.expr);
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->type = E_SYMBOL;
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->left.sym = &symbol_yes;
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->right.expr = NULL;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return e;
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->right.expr->type == E_SYMBOL) {
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (e->right.expr->left.sym == &symbol_no) {
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				free(e->right.expr);
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp = e->left.expr;
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*e = *(e->left.expr);
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				free(tmp);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return e;
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (e->right.expr->left.sym == &symbol_yes) {
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				expr_free(e->left.expr);
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				expr_free(e->right.expr);
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->type = E_SYMBOL;
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->left.sym = &symbol_yes;
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->right.expr = NULL;
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return e;
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		;
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return e;
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bool FOO!=n => FOO
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct expr *expr_trans_bool(struct expr *e)
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!e)
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (e->type) {
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_NOT:
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e->left.expr = expr_trans_bool(e->left.expr);
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e->right.expr = expr_trans_bool(e->right.expr);
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_UNEQUAL:
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// FOO!=n -> FOO
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->left.sym->type == S_TRISTATE) {
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (e->right.sym == &symbol_no) {
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->type = E_SYMBOL;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->right.sym = NULL;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		;
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return e;
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * e1 || e2 -> ?
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3514356f4890792a678936c93c9196e8f7742e04535Trevor Keithstatic struct expr *expr_join_or(struct expr *e1, struct expr *e2)
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct expr *tmp;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct symbol *sym1, *sym2;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (expr_eq(e1, e2))
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return expr_copy(e1);
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e1->type == E_NOT) {
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp = e1->left.expr;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return NULL;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sym1 = tmp->left.sym;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sym1 = e1->left.sym;
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e2->type == E_NOT) {
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e2->left.expr->type != E_SYMBOL)
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return NULL;
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sym2 = e2->left.expr->left.sym;
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sym2 = e2->left.sym;
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sym1 != sym2)
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sym1->type == S_TRISTATE) {
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// (a='y') || (a='m') -> (a!='n')
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// (a='y') || (a='n') -> (a!='m')
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// (a='m') || (a='n') -> (a!='y')
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sym1->type == S_BOOLEAN && sym1 == sym2) {
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return expr_alloc_symbol(&symbol_yes);
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (DEBUG_EXPR) {
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printf("optimize (");
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_fprint(e1, stdout);
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printf(") || (");
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_fprint(e2, stdout);
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printf(")?\n");
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4154356f4890792a678936c93c9196e8f7742e04535Trevor Keithstatic struct expr *expr_join_and(struct expr *e1, struct expr *e2)
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct expr *tmp;
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct symbol *sym1, *sym2;
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (expr_eq(e1, e2))
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return expr_copy(e1);
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e1->type == E_NOT) {
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp = e1->left.expr;
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return NULL;
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sym1 = tmp->left.sym;
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sym1 = e1->left.sym;
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e2->type == E_NOT) {
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e2->left.expr->type != E_SYMBOL)
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return NULL;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sym2 = e2->left.expr->left.sym;
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sym2 = e2->left.sym;
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sym1 != sym2)
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// (a) && (a='y') -> (a='y')
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// (a) && (a!='n') -> (a)
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return expr_alloc_symbol(sym1);
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// (a) && (a!='m') -> (a='y')
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sym1->type == S_TRISTATE) {
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sym2 = e1->right.sym;
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							     : expr_alloc_symbol(&symbol_no);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sym2 = e2->right.sym;
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							     : expr_alloc_symbol(&symbol_no);
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// (a!='y') && (a!='n') -> (a='m')
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// (a!='y') && (a!='m') -> (a='n')
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// (a!='m') && (a!='n') -> (a='m')
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return NULL;
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (DEBUG_EXPR) {
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printf("optimize (");
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_fprint(e1, stdout);
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printf(") && (");
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_fprint(e2, stdout);
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printf(")?\n");
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define e1 (*ep1)
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define e2 (*ep2)
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct expr *tmp;
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e1->type == type) {
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_eliminate_dups1(type, &e1->left.expr, &e2);
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_eliminate_dups1(type, &e1->right.expr, &e2);
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e2->type == type) {
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_eliminate_dups1(type, &e1, &e2->left.expr);
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_eliminate_dups1(type, &e1, &e2->right.expr);
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e1 == e2)
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (e1->type) {
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR: case E_AND:
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_eliminate_dups1(e1->type, &e1, &e1);
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		;
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (type) {
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp = expr_join_or(e1, e2);
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tmp) {
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			expr_free(e1); expr_free(e2);
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e1 = expr_alloc_symbol(&symbol_no);
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e2 = tmp;
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			trans_count++;
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp = expr_join_and(e1, e2);
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tmp) {
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			expr_free(e1); expr_free(e2);
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e1 = expr_alloc_symbol(&symbol_yes);
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e2 = tmp;
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			trans_count++;
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		;
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef e1
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef e2
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define e1 (*ep1)
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define e2 (*ep2)
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct expr *tmp, *tmp1, *tmp2;
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e1->type == type) {
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_eliminate_dups2(type, &e1->left.expr, &e2);
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_eliminate_dups2(type, &e1->right.expr, &e2);
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e2->type == type) {
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_eliminate_dups2(type, &e1, &e2->left.expr);
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_eliminate_dups2(type, &e1, &e2->right.expr);
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e1 == e2)
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (e1->type) {
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_eliminate_dups2(e1->type, &e1, &e1);
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// (FOO || BAR) && (!FOO && !BAR) -> n
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp2 = expr_copy(e2);
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp = expr_extract_eq_and(&tmp1, &tmp2);
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (expr_is_yes(tmp1)) {
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			expr_free(e1);
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e1 = expr_alloc_symbol(&symbol_no);
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			trans_count++;
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_free(tmp2);
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_free(tmp1);
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_free(tmp);
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_eliminate_dups2(e1->type, &e1, &e1);
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		// (FOO && BAR) || (!FOO || !BAR) -> y
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp2 = expr_copy(e2);
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp = expr_extract_eq_or(&tmp1, &tmp2);
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (expr_is_no(tmp1)) {
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			expr_free(e1);
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e1 = expr_alloc_symbol(&symbol_yes);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			trans_count++;
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_free(tmp2);
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_free(tmp1);
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_free(tmp);
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		;
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef e1
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef e2
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct expr *expr_eliminate_dups(struct expr *e)
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int oldcount;
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!e)
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return e;
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	oldcount = trans_count;
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (1) {
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		trans_count = 0;
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (e->type) {
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case E_OR: case E_AND:
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			expr_eliminate_dups1(e->type, &e, &e);
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			expr_eliminate_dups2(e->type, &e, &e);
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			;
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!trans_count)
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e = expr_eliminate_yn(e);
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	trans_count = oldcount;
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return e;
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct expr *expr_transform(struct expr *e)
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct expr *tmp;
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!e)
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (e->type) {
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_EQUAL:
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_UNEQUAL:
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_SYMBOL:
6517a962923359768e04137125bd479fd0dfa6117d3Roman Zippel	case E_LIST:
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e->left.expr = expr_transform(e->left.expr);
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e->right.expr = expr_transform(e->right.expr);
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (e->type) {
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_EQUAL:
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->left.sym->type != S_BOOLEAN)
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->right.sym == &symbol_no) {
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->type = E_NOT;
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->left.expr = expr_alloc_symbol(e->left.sym);
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->right.sym = NULL;
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->right.sym == &symbol_mod) {
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->type = E_SYMBOL;
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->left.sym = &symbol_no;
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->right.sym = NULL;
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->right.sym == &symbol_yes) {
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->type = E_SYMBOL;
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->right.sym = NULL;
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_UNEQUAL:
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->left.sym->type != S_BOOLEAN)
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->right.sym == &symbol_no) {
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->type = E_SYMBOL;
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->right.sym = NULL;
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->right.sym == &symbol_mod) {
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->type = E_SYMBOL;
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->left.sym = &symbol_yes;
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->right.sym = NULL;
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->right.sym == &symbol_yes) {
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->type = E_NOT;
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->left.expr = expr_alloc_symbol(e->left.sym);
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->right.sym = NULL;
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_NOT:
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (e->left.expr->type) {
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case E_NOT:
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// !!a -> a
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tmp = e->left.expr->left.expr;
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			free(e->left.expr);
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			free(e);
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e = tmp;
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e = expr_transform(e);
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case E_EQUAL:
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case E_UNEQUAL:
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// !a='x' -> a!='x'
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tmp = e->left.expr;
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			free(e);
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e = tmp;
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case E_OR:
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// !(a || b) -> !a && !b
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tmp = e->left.expr;
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->type = E_AND;
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tmp->type = E_NOT;
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tmp->right.expr = NULL;
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e = expr_transform(e);
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case E_AND:
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			// !(a && b) -> !a || !b
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tmp = e->left.expr;
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->type = E_OR;
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tmp->type = E_NOT;
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tmp->right.expr = NULL;
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e = expr_transform(e);
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case E_SYMBOL:
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (e->left.expr->left.sym == &symbol_yes) {
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// !'y' -> 'n'
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp = e->left.expr;
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				free(e);
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e = tmp;
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->type = E_SYMBOL;
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->left.sym = &symbol_no;
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (e->left.expr->left.sym == &symbol_mod) {
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// !'m' -> 'm'
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp = e->left.expr;
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				free(e);
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e = tmp;
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->type = E_SYMBOL;
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->left.sym = &symbol_mod;
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (e->left.expr->left.sym == &symbol_no) {
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				// !'n' -> 'y'
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tmp = e->left.expr;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				free(e);
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e = tmp;
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->type = E_SYMBOL;
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				e->left.sym = &symbol_yes;
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			;
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		;
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return e;
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint expr_contains_symbol(struct expr *dep, struct symbol *sym)
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dep)
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (dep->type) {
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return expr_contains_symbol(dep->left.expr, sym) ||
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       expr_contains_symbol(dep->right.expr, sym);
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_SYMBOL:
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return dep->left.sym == sym;
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_EQUAL:
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_UNEQUAL:
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return dep->left.sym == sym ||
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       dep->right.sym == sym;
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_NOT:
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return expr_contains_symbol(dep->left.expr, sym);
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		;
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbool expr_depends_symbol(struct expr *dep, struct symbol *sym)
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dep)
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return false;
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (dep->type) {
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return expr_depends_symbol(dep->left.expr, sym) ||
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       expr_depends_symbol(dep->right.expr, sym);
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_SYMBOL:
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return dep->left.sym == sym;
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_EQUAL:
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dep->left.sym == sym) {
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return true;
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_UNEQUAL:
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dep->left.sym == sym) {
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (dep->right.sym == &symbol_no)
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return true;
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		;
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 	return false;
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct expr *tmp = NULL;
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	expr_extract_eq(E_AND, &tmp, ep1, ep2);
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tmp) {
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*ep1 = expr_eliminate_yn(*ep1);
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*ep2 = expr_eliminate_yn(*ep2);
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return tmp;
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct expr *tmp = NULL;
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	expr_extract_eq(E_OR, &tmp, ep1, ep2);
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tmp) {
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*ep1 = expr_eliminate_yn(*ep1);
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*ep2 = expr_eliminate_yn(*ep2);
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return tmp;
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define e1 (*ep1)
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define e2 (*ep2)
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e1->type == type) {
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_extract_eq(type, ep, &e1->left.expr, &e2);
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_extract_eq(type, ep, &e1->right.expr, &e2);
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (e2->type == type) {
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_extract_eq(type, ep, ep1, &e2->left.expr);
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_extract_eq(type, ep, ep1, &e2->right.expr);
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (expr_eq(e1, e2)) {
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_free(e2);
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (type == E_AND) {
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e1 = expr_alloc_symbol(&symbol_yes);
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e2 = expr_alloc_symbol(&symbol_yes);
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if (type == E_OR) {
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e1 = expr_alloc_symbol(&symbol_no);
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e2 = expr_alloc_symbol(&symbol_no);
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef e1
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef e2
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct expr *e1, *e2;
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!e) {
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e = expr_alloc_symbol(sym);
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (type == E_UNEQUAL)
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e = expr_alloc_one(E_NOT, e);
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return e;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (e->type) {
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (sym == &symbol_yes)
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e = expr_alloc_two(E_AND, e1, e2);
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (sym == &symbol_no)
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e = expr_alloc_two(E_OR, e1, e2);
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (type == E_UNEQUAL)
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e = expr_alloc_one(E_NOT, e);
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return e;
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (sym == &symbol_yes)
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e = expr_alloc_two(E_OR, e1, e2);
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (sym == &symbol_no)
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e = expr_alloc_two(E_AND, e1, e2);
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (type == E_UNEQUAL)
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e = expr_alloc_one(E_NOT, e);
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return e;
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_NOT:
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_UNEQUAL:
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_EQUAL:
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (type == E_EQUAL) {
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (sym == &symbol_yes)
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return expr_copy(e);
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (sym == &symbol_mod)
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return expr_alloc_symbol(&symbol_no);
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (sym == &symbol_no)
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return expr_alloc_one(E_NOT, expr_copy(e));
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (sym == &symbol_yes)
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return expr_alloc_one(E_NOT, expr_copy(e));
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (sym == &symbol_mod)
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return expr_alloc_symbol(&symbol_yes);
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (sym == &symbol_no)
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return expr_copy(e);
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_SYMBOL:
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return expr_alloc_comp(type, e->left.sym, sym);
9357a962923359768e04137125bd479fd0dfa6117d3Roman Zippel	case E_LIST:
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_RANGE:
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_NONE:
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* panic */;
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstristate expr_calc_value(struct expr *e)
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tristate val1, val2;
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *str1, *str2;
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!e)
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return yes;
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (e->type) {
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_SYMBOL:
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sym_calc_value(e->left.sym);
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return e->left.sym->curr.tri;
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val1 = expr_calc_value(e->left.expr);
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val2 = expr_calc_value(e->right.expr);
958d6ee35764f270c699e165b15dc59f4e55546bfdaSam Ravnborg		return EXPR_AND(val1, val2);
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val1 = expr_calc_value(e->left.expr);
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val2 = expr_calc_value(e->right.expr);
962d6ee35764f270c699e165b15dc59f4e55546bfdaSam Ravnborg		return EXPR_OR(val1, val2);
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_NOT:
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val1 = expr_calc_value(e->left.expr);
965d6ee35764f270c699e165b15dc59f4e55546bfdaSam Ravnborg		return EXPR_NOT(val1);
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_EQUAL:
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sym_calc_value(e->left.sym);
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sym_calc_value(e->right.sym);
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		str1 = sym_get_string_value(e->left.sym);
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		str2 = sym_get_string_value(e->right.sym);
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return !strcmp(str1, str2) ? yes : no;
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_UNEQUAL:
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sym_calc_value(e->left.sym);
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sym_calc_value(e->right.sym);
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		str1 = sym_get_string_value(e->left.sym);
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		str2 = sym_get_string_value(e->right.sym);
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return !strcmp(str1, str2) ? no : yes;
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printf("expr_calc_value: %d?\n", e->type);
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return no;
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint expr_compare_type(enum expr_type t1, enum expr_type t2)
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (t1 == t2)
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (t1) {
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_EQUAL:
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_UNEQUAL:
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (t2 == E_NOT)
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_NOT:
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (t2 == E_AND)
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (t2 == E_OR)
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
10037a962923359768e04137125bd479fd0dfa6117d3Roman Zippel		if (t2 == E_LIST)
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
10057a962923359768e04137125bd479fd0dfa6117d3Roman Zippel	case E_LIST:
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (t2 == 0)
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printf("[%dgt%d?]", t1, t2);
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10161137c56b7420c801147e0863845c03b07554721aArnaud Lacombestatic inline struct expr *
10171137c56b7420c801147e0863845c03b07554721aArnaud Lacombeexpr_get_leftmost_symbol(const struct expr *e)
10181137c56b7420c801147e0863845c03b07554721aArnaud Lacombe{
10191137c56b7420c801147e0863845c03b07554721aArnaud Lacombe
10201137c56b7420c801147e0863845c03b07554721aArnaud Lacombe	if (e == NULL)
10211137c56b7420c801147e0863845c03b07554721aArnaud Lacombe		return NULL;
10221137c56b7420c801147e0863845c03b07554721aArnaud Lacombe
10231137c56b7420c801147e0863845c03b07554721aArnaud Lacombe	while (e->type != E_SYMBOL)
10241137c56b7420c801147e0863845c03b07554721aArnaud Lacombe		e = e->left.expr;
10251137c56b7420c801147e0863845c03b07554721aArnaud Lacombe
10261137c56b7420c801147e0863845c03b07554721aArnaud Lacombe	return expr_copy(e);
10271137c56b7420c801147e0863845c03b07554721aArnaud Lacombe}
10281137c56b7420c801147e0863845c03b07554721aArnaud Lacombe
10291137c56b7420c801147e0863845c03b07554721aArnaud Lacombe/*
10301137c56b7420c801147e0863845c03b07554721aArnaud Lacombe * Given expression `e1' and `e2', returns the leaf of the longest
10311137c56b7420c801147e0863845c03b07554721aArnaud Lacombe * sub-expression of `e1' not containing 'e2.
10321137c56b7420c801147e0863845c03b07554721aArnaud Lacombe */
10331137c56b7420c801147e0863845c03b07554721aArnaud Lacombestruct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2)
10341137c56b7420c801147e0863845c03b07554721aArnaud Lacombe{
10351137c56b7420c801147e0863845c03b07554721aArnaud Lacombe	struct expr *ret;
10361137c56b7420c801147e0863845c03b07554721aArnaud Lacombe
10371137c56b7420c801147e0863845c03b07554721aArnaud Lacombe	switch (e1->type) {
10381137c56b7420c801147e0863845c03b07554721aArnaud Lacombe	case E_OR:
10391137c56b7420c801147e0863845c03b07554721aArnaud Lacombe		return expr_alloc_and(
10401137c56b7420c801147e0863845c03b07554721aArnaud Lacombe		    expr_simplify_unmet_dep(e1->left.expr, e2),
10411137c56b7420c801147e0863845c03b07554721aArnaud Lacombe		    expr_simplify_unmet_dep(e1->right.expr, e2));
10421137c56b7420c801147e0863845c03b07554721aArnaud Lacombe	case E_AND: {
10431137c56b7420c801147e0863845c03b07554721aArnaud Lacombe		struct expr *e;
10441137c56b7420c801147e0863845c03b07554721aArnaud Lacombe		e = expr_alloc_and(expr_copy(e1), expr_copy(e2));
10451137c56b7420c801147e0863845c03b07554721aArnaud Lacombe		e = expr_eliminate_dups(e);
10461137c56b7420c801147e0863845c03b07554721aArnaud Lacombe		ret = (!expr_eq(e, e1)) ? e1 : NULL;
10471137c56b7420c801147e0863845c03b07554721aArnaud Lacombe		expr_free(e);
10481137c56b7420c801147e0863845c03b07554721aArnaud Lacombe		break;
10491137c56b7420c801147e0863845c03b07554721aArnaud Lacombe		}
10501137c56b7420c801147e0863845c03b07554721aArnaud Lacombe	default:
10511137c56b7420c801147e0863845c03b07554721aArnaud Lacombe		ret = e1;
10521137c56b7420c801147e0863845c03b07554721aArnaud Lacombe		break;
10531137c56b7420c801147e0863845c03b07554721aArnaud Lacombe	}
10541137c56b7420c801147e0863845c03b07554721aArnaud Lacombe
10551137c56b7420c801147e0863845c03b07554721aArnaud Lacombe	return expr_get_leftmost_symbol(ret);
10561137c56b7420c801147e0863845c03b07554721aArnaud Lacombe}
10571137c56b7420c801147e0863845c03b07554721aArnaud Lacombe
1058ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippelvoid expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!e) {
1061ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, NULL, "y");
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (expr_compare_type(prevtoken, e->type) > 0)
1066ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, NULL, "(");
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (e->type) {
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_SYMBOL:
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->left.sym->name)
1070ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel			fn(data, e->left.sym, e->left.sym->name);
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
1072ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel			fn(data, NULL, "<choice>");
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_NOT:
1075ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, NULL, "!");
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_print(e->left.expr, fn, data, E_NOT);
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_EQUAL:
1079f5eaa323eb6819d2f737ead42464efccaf2b98b9Jan Beulich		if (e->left.sym->name)
1080f5eaa323eb6819d2f737ead42464efccaf2b98b9Jan Beulich			fn(data, e->left.sym, e->left.sym->name);
1081f5eaa323eb6819d2f737ead42464efccaf2b98b9Jan Beulich		else
1082f5eaa323eb6819d2f737ead42464efccaf2b98b9Jan Beulich			fn(data, NULL, "<choice>");
1083ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, NULL, "=");
1084ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, e->right.sym, e->right.sym->name);
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_UNEQUAL:
1087f5eaa323eb6819d2f737ead42464efccaf2b98b9Jan Beulich		if (e->left.sym->name)
1088f5eaa323eb6819d2f737ead42464efccaf2b98b9Jan Beulich			fn(data, e->left.sym, e->left.sym->name);
1089f5eaa323eb6819d2f737ead42464efccaf2b98b9Jan Beulich		else
1090f5eaa323eb6819d2f737ead42464efccaf2b98b9Jan Beulich			fn(data, NULL, "<choice>");
1091ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, NULL, "!=");
1092ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, e->right.sym, e->right.sym->name);
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_OR:
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_print(e->left.expr, fn, data, E_OR);
1096ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, NULL, " || ");
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_print(e->right.expr, fn, data, E_OR);
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_AND:
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_print(e->left.expr, fn, data, E_AND);
1101ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, NULL, " && ");
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		expr_print(e->right.expr, fn, data, E_AND);
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11047a962923359768e04137125bd479fd0dfa6117d3Roman Zippel	case E_LIST:
1105ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, e->right.sym, e->right.sym->name);
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (e->left.expr) {
1107ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel			fn(data, NULL, " ^ ");
11087a962923359768e04137125bd479fd0dfa6117d3Roman Zippel			expr_print(e->left.expr, fn, data, E_LIST);
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case E_RANGE:
1112ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, NULL, "[");
1113ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, e->left.sym, e->left.sym->name);
1114ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, NULL, " ");
1115ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, e->right.sym, e->right.sym->name);
1116ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, NULL, "]");
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  {
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		char buf[32];
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sprintf(buf, "<unknown type %d>", e->type);
1122ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, NULL, buf);
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  }
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (expr_compare_type(prevtoken, e->type) > 0)
1127ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippel		fn(data, NULL, ")");
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1130ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippelstatic void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1132bf5e327a300a9ac959a89440e7c67dc89f3bd804Jean Sacren	xfwrite(str, strlen(str), 1, data);
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid expr_fprint(struct expr *e, FILE *out)
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	expr_print(e, expr_print_file_helper, out, E_NONE);
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1140ab45d190fd4acf0b0e5d307294ce24a90a69cc23Roman Zippelstatic void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1142da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)	struct gstr *gs = (struct gstr*)data;
1143da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)	const char *sym_str = NULL;
1144da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)
1145da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)	if (sym)
1146da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)		sym_str = sym_get_string_value(sym);
1147da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)
1148da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)	if (gs->max_width) {
1149da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)		unsigned extra_length = strlen(str);
1150da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)		const char *last_cr = strrchr(gs->s, '\n');
1151da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)		unsigned last_line_length;
1152da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)
1153da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)		if (sym_str)
1154da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)			extra_length += 4 + strlen(sym_str);
1155da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)
1156da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)		if (!last_cr)
1157da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)			last_cr = gs->s;
1158da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)
1159da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)		last_line_length = strlen(gs->s) - (last_cr - gs->s);
1160da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)
1161da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)		if ((last_line_length + extra_length) > gs->max_width)
1162da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)			str_append(gs, "\\\n");
1163da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)	}
1164da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)
1165da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)	str_append(gs, str);
116670ed074718a6704ac2f82d014f372ba25c42ba12Li Zefan	if (sym && sym->type != S_UNKNOWN)
1167da60fbbcb637b37b1d77a41886ae4e275422ca96Vadim Bendebury (вб)		str_printf(gs, " [=%s]", sym_str);
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid expr_gstr_print(struct expr *e, struct gstr *gs)
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	expr_print(e, expr_print_gstr_helper, gs, E_NONE);
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1174