15257cf54a5810105bc4a75703a06740d756d8e8landley/*
25257cf54a5810105bc4a75703a06740d756d8e8landley * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
35257cf54a5810105bc4a75703a06740d756d8e8landley * Released under the terms of the GNU GPL v2.0.
45257cf54a5810105bc4a75703a06740d756d8e8landley */
55257cf54a5810105bc4a75703a06740d756d8e8landley
65257cf54a5810105bc4a75703a06740d756d8e8landley#include <stdio.h>
75257cf54a5810105bc4a75703a06740d756d8e8landley#include <stdlib.h>
85257cf54a5810105bc4a75703a06740d756d8e8landley#include <string.h>
95257cf54a5810105bc4a75703a06740d756d8e8landley
105257cf54a5810105bc4a75703a06740d756d8e8landley#define LKC_DIRECT_LINK
115257cf54a5810105bc4a75703a06740d756d8e8landley#include "lkc.h"
125257cf54a5810105bc4a75703a06740d756d8e8landley
135257cf54a5810105bc4a75703a06740d756d8e8landley#define DEBUG_EXPR	0
145257cf54a5810105bc4a75703a06740d756d8e8landley
155257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_alloc_symbol(struct symbol *sym)
165257cf54a5810105bc4a75703a06740d756d8e8landley{
175257cf54a5810105bc4a75703a06740d756d8e8landley	struct expr *e = malloc(sizeof(*e));
185257cf54a5810105bc4a75703a06740d756d8e8landley	memset(e, 0, sizeof(*e));
195257cf54a5810105bc4a75703a06740d756d8e8landley	e->type = E_SYMBOL;
205257cf54a5810105bc4a75703a06740d756d8e8landley	e->left.sym = sym;
215257cf54a5810105bc4a75703a06740d756d8e8landley	return e;
225257cf54a5810105bc4a75703a06740d756d8e8landley}
235257cf54a5810105bc4a75703a06740d756d8e8landley
245257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
255257cf54a5810105bc4a75703a06740d756d8e8landley{
265257cf54a5810105bc4a75703a06740d756d8e8landley	struct expr *e = malloc(sizeof(*e));
275257cf54a5810105bc4a75703a06740d756d8e8landley	memset(e, 0, sizeof(*e));
285257cf54a5810105bc4a75703a06740d756d8e8landley	e->type = type;
295257cf54a5810105bc4a75703a06740d756d8e8landley	e->left.expr = ce;
305257cf54a5810105bc4a75703a06740d756d8e8landley	return e;
315257cf54a5810105bc4a75703a06740d756d8e8landley}
325257cf54a5810105bc4a75703a06740d756d8e8landley
335257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
345257cf54a5810105bc4a75703a06740d756d8e8landley{
355257cf54a5810105bc4a75703a06740d756d8e8landley	struct expr *e = malloc(sizeof(*e));
365257cf54a5810105bc4a75703a06740d756d8e8landley	memset(e, 0, sizeof(*e));
375257cf54a5810105bc4a75703a06740d756d8e8landley	e->type = type;
385257cf54a5810105bc4a75703a06740d756d8e8landley	e->left.expr = e1;
395257cf54a5810105bc4a75703a06740d756d8e8landley	e->right.expr = e2;
405257cf54a5810105bc4a75703a06740d756d8e8landley	return e;
415257cf54a5810105bc4a75703a06740d756d8e8landley}
425257cf54a5810105bc4a75703a06740d756d8e8landley
435257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
445257cf54a5810105bc4a75703a06740d756d8e8landley{
455257cf54a5810105bc4a75703a06740d756d8e8landley	struct expr *e = malloc(sizeof(*e));
465257cf54a5810105bc4a75703a06740d756d8e8landley	memset(e, 0, sizeof(*e));
475257cf54a5810105bc4a75703a06740d756d8e8landley	e->type = type;
485257cf54a5810105bc4a75703a06740d756d8e8landley	e->left.sym = s1;
495257cf54a5810105bc4a75703a06740d756d8e8landley	e->right.sym = s2;
505257cf54a5810105bc4a75703a06740d756d8e8landley	return e;
515257cf54a5810105bc4a75703a06740d756d8e8landley}
525257cf54a5810105bc4a75703a06740d756d8e8landley
535257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
545257cf54a5810105bc4a75703a06740d756d8e8landley{
555257cf54a5810105bc4a75703a06740d756d8e8landley	if (!e1)
565257cf54a5810105bc4a75703a06740d756d8e8landley		return e2;
575257cf54a5810105bc4a75703a06740d756d8e8landley	return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
585257cf54a5810105bc4a75703a06740d756d8e8landley}
595257cf54a5810105bc4a75703a06740d756d8e8landley
605257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
615257cf54a5810105bc4a75703a06740d756d8e8landley{
625257cf54a5810105bc4a75703a06740d756d8e8landley	if (!e1)
635257cf54a5810105bc4a75703a06740d756d8e8landley		return e2;
645257cf54a5810105bc4a75703a06740d756d8e8landley	return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
655257cf54a5810105bc4a75703a06740d756d8e8landley}
665257cf54a5810105bc4a75703a06740d756d8e8landley
675257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_copy(struct expr *org)
685257cf54a5810105bc4a75703a06740d756d8e8landley{
695257cf54a5810105bc4a75703a06740d756d8e8landley	struct expr *e;
705257cf54a5810105bc4a75703a06740d756d8e8landley
715257cf54a5810105bc4a75703a06740d756d8e8landley	if (!org)
725257cf54a5810105bc4a75703a06740d756d8e8landley		return NULL;
735257cf54a5810105bc4a75703a06740d756d8e8landley
745257cf54a5810105bc4a75703a06740d756d8e8landley	e = malloc(sizeof(*org));
755257cf54a5810105bc4a75703a06740d756d8e8landley	memcpy(e, org, sizeof(*org));
765257cf54a5810105bc4a75703a06740d756d8e8landley	switch (org->type) {
775257cf54a5810105bc4a75703a06740d756d8e8landley	case E_SYMBOL:
785257cf54a5810105bc4a75703a06740d756d8e8landley		e->left = org->left;
795257cf54a5810105bc4a75703a06740d756d8e8landley		break;
805257cf54a5810105bc4a75703a06740d756d8e8landley	case E_NOT:
815257cf54a5810105bc4a75703a06740d756d8e8landley		e->left.expr = expr_copy(org->left.expr);
825257cf54a5810105bc4a75703a06740d756d8e8landley		break;
835257cf54a5810105bc4a75703a06740d756d8e8landley	case E_EQUAL:
845257cf54a5810105bc4a75703a06740d756d8e8landley	case E_UNEQUAL:
855257cf54a5810105bc4a75703a06740d756d8e8landley		e->left.sym = org->left.sym;
865257cf54a5810105bc4a75703a06740d756d8e8landley		e->right.sym = org->right.sym;
875257cf54a5810105bc4a75703a06740d756d8e8landley		break;
885257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
895257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
905257cf54a5810105bc4a75703a06740d756d8e8landley	case E_CHOICE:
915257cf54a5810105bc4a75703a06740d756d8e8landley		e->left.expr = expr_copy(org->left.expr);
925257cf54a5810105bc4a75703a06740d756d8e8landley		e->right.expr = expr_copy(org->right.expr);
935257cf54a5810105bc4a75703a06740d756d8e8landley		break;
945257cf54a5810105bc4a75703a06740d756d8e8landley	default:
955257cf54a5810105bc4a75703a06740d756d8e8landley		printf("can't copy type %d\n", e->type);
965257cf54a5810105bc4a75703a06740d756d8e8landley		free(e);
975257cf54a5810105bc4a75703a06740d756d8e8landley		e = NULL;
985257cf54a5810105bc4a75703a06740d756d8e8landley		break;
995257cf54a5810105bc4a75703a06740d756d8e8landley	}
1005257cf54a5810105bc4a75703a06740d756d8e8landley
1015257cf54a5810105bc4a75703a06740d756d8e8landley	return e;
1025257cf54a5810105bc4a75703a06740d756d8e8landley}
1035257cf54a5810105bc4a75703a06740d756d8e8landley
1045257cf54a5810105bc4a75703a06740d756d8e8landleyvoid expr_free(struct expr *e)
1055257cf54a5810105bc4a75703a06740d756d8e8landley{
1065257cf54a5810105bc4a75703a06740d756d8e8landley	if (!e)
1075257cf54a5810105bc4a75703a06740d756d8e8landley		return;
1085257cf54a5810105bc4a75703a06740d756d8e8landley
1095257cf54a5810105bc4a75703a06740d756d8e8landley	switch (e->type) {
1105257cf54a5810105bc4a75703a06740d756d8e8landley	case E_SYMBOL:
1115257cf54a5810105bc4a75703a06740d756d8e8landley		break;
1125257cf54a5810105bc4a75703a06740d756d8e8landley	case E_NOT:
1135257cf54a5810105bc4a75703a06740d756d8e8landley		expr_free(e->left.expr);
1145257cf54a5810105bc4a75703a06740d756d8e8landley		return;
1155257cf54a5810105bc4a75703a06740d756d8e8landley	case E_EQUAL:
1165257cf54a5810105bc4a75703a06740d756d8e8landley	case E_UNEQUAL:
1175257cf54a5810105bc4a75703a06740d756d8e8landley		break;
1185257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
1195257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
1205257cf54a5810105bc4a75703a06740d756d8e8landley		expr_free(e->left.expr);
1215257cf54a5810105bc4a75703a06740d756d8e8landley		expr_free(e->right.expr);
1225257cf54a5810105bc4a75703a06740d756d8e8landley		break;
1235257cf54a5810105bc4a75703a06740d756d8e8landley	default:
1245257cf54a5810105bc4a75703a06740d756d8e8landley		printf("how to free type %d?\n", e->type);
1255257cf54a5810105bc4a75703a06740d756d8e8landley		break;
1265257cf54a5810105bc4a75703a06740d756d8e8landley	}
1275257cf54a5810105bc4a75703a06740d756d8e8landley	free(e);
1285257cf54a5810105bc4a75703a06740d756d8e8landley}
1295257cf54a5810105bc4a75703a06740d756d8e8landley
1305257cf54a5810105bc4a75703a06740d756d8e8landleystatic int trans_count;
1315257cf54a5810105bc4a75703a06740d756d8e8landley
1325257cf54a5810105bc4a75703a06740d756d8e8landley#define e1 (*ep1)
1335257cf54a5810105bc4a75703a06740d756d8e8landley#define e2 (*ep2)
1345257cf54a5810105bc4a75703a06740d756d8e8landley
1355257cf54a5810105bc4a75703a06740d756d8e8landleystatic void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
1365257cf54a5810105bc4a75703a06740d756d8e8landley{
1375257cf54a5810105bc4a75703a06740d756d8e8landley	if (e1->type == type) {
1385257cf54a5810105bc4a75703a06740d756d8e8landley		__expr_eliminate_eq(type, &e1->left.expr, &e2);
1395257cf54a5810105bc4a75703a06740d756d8e8landley		__expr_eliminate_eq(type, &e1->right.expr, &e2);
1405257cf54a5810105bc4a75703a06740d756d8e8landley		return;
1415257cf54a5810105bc4a75703a06740d756d8e8landley	}
1425257cf54a5810105bc4a75703a06740d756d8e8landley	if (e2->type == type) {
1435257cf54a5810105bc4a75703a06740d756d8e8landley		__expr_eliminate_eq(type, &e1, &e2->left.expr);
1445257cf54a5810105bc4a75703a06740d756d8e8landley		__expr_eliminate_eq(type, &e1, &e2->right.expr);
1455257cf54a5810105bc4a75703a06740d756d8e8landley		return;
1465257cf54a5810105bc4a75703a06740d756d8e8landley	}
1475257cf54a5810105bc4a75703a06740d756d8e8landley	if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
1485257cf54a5810105bc4a75703a06740d756d8e8landley	    e1->left.sym == e2->left.sym &&
1495257cf54a5810105bc4a75703a06740d756d8e8landley	    (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
1505257cf54a5810105bc4a75703a06740d756d8e8landley		return;
1515257cf54a5810105bc4a75703a06740d756d8e8landley	if (!expr_eq(e1, e2))
1525257cf54a5810105bc4a75703a06740d756d8e8landley		return;
1535257cf54a5810105bc4a75703a06740d756d8e8landley	trans_count++;
1545257cf54a5810105bc4a75703a06740d756d8e8landley	expr_free(e1); expr_free(e2);
1555257cf54a5810105bc4a75703a06740d756d8e8landley	switch (type) {
1565257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
1575257cf54a5810105bc4a75703a06740d756d8e8landley		e1 = expr_alloc_symbol(&symbol_no);
1585257cf54a5810105bc4a75703a06740d756d8e8landley		e2 = expr_alloc_symbol(&symbol_no);
1595257cf54a5810105bc4a75703a06740d756d8e8landley		break;
1605257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
1615257cf54a5810105bc4a75703a06740d756d8e8landley		e1 = expr_alloc_symbol(&symbol_yes);
1625257cf54a5810105bc4a75703a06740d756d8e8landley		e2 = expr_alloc_symbol(&symbol_yes);
1635257cf54a5810105bc4a75703a06740d756d8e8landley		break;
1645257cf54a5810105bc4a75703a06740d756d8e8landley	default:
1655257cf54a5810105bc4a75703a06740d756d8e8landley		;
1665257cf54a5810105bc4a75703a06740d756d8e8landley	}
1675257cf54a5810105bc4a75703a06740d756d8e8landley}
1685257cf54a5810105bc4a75703a06740d756d8e8landley
1695257cf54a5810105bc4a75703a06740d756d8e8landleyvoid expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
1705257cf54a5810105bc4a75703a06740d756d8e8landley{
1715257cf54a5810105bc4a75703a06740d756d8e8landley	if (!e1 || !e2)
1725257cf54a5810105bc4a75703a06740d756d8e8landley		return;
1735257cf54a5810105bc4a75703a06740d756d8e8landley	switch (e1->type) {
1745257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
1755257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
1765257cf54a5810105bc4a75703a06740d756d8e8landley		__expr_eliminate_eq(e1->type, ep1, ep2);
1775257cf54a5810105bc4a75703a06740d756d8e8landley	default:
1785257cf54a5810105bc4a75703a06740d756d8e8landley		;
1795257cf54a5810105bc4a75703a06740d756d8e8landley	}
1805257cf54a5810105bc4a75703a06740d756d8e8landley	if (e1->type != e2->type) switch (e2->type) {
1815257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
1825257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
1835257cf54a5810105bc4a75703a06740d756d8e8landley		__expr_eliminate_eq(e2->type, ep1, ep2);
1845257cf54a5810105bc4a75703a06740d756d8e8landley	default:
1855257cf54a5810105bc4a75703a06740d756d8e8landley		;
1865257cf54a5810105bc4a75703a06740d756d8e8landley	}
1875257cf54a5810105bc4a75703a06740d756d8e8landley	e1 = expr_eliminate_yn(e1);
1885257cf54a5810105bc4a75703a06740d756d8e8landley	e2 = expr_eliminate_yn(e2);
1895257cf54a5810105bc4a75703a06740d756d8e8landley}
1905257cf54a5810105bc4a75703a06740d756d8e8landley
1915257cf54a5810105bc4a75703a06740d756d8e8landley#undef e1
1925257cf54a5810105bc4a75703a06740d756d8e8landley#undef e2
1935257cf54a5810105bc4a75703a06740d756d8e8landley
1945257cf54a5810105bc4a75703a06740d756d8e8landleyint expr_eq(struct expr *e1, struct expr *e2)
1955257cf54a5810105bc4a75703a06740d756d8e8landley{
1965257cf54a5810105bc4a75703a06740d756d8e8landley	int res, old_count;
1975257cf54a5810105bc4a75703a06740d756d8e8landley
1985257cf54a5810105bc4a75703a06740d756d8e8landley	if (e1->type != e2->type)
1995257cf54a5810105bc4a75703a06740d756d8e8landley		return 0;
2005257cf54a5810105bc4a75703a06740d756d8e8landley	switch (e1->type) {
2015257cf54a5810105bc4a75703a06740d756d8e8landley	case E_EQUAL:
2025257cf54a5810105bc4a75703a06740d756d8e8landley	case E_UNEQUAL:
2035257cf54a5810105bc4a75703a06740d756d8e8landley		return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
2045257cf54a5810105bc4a75703a06740d756d8e8landley	case E_SYMBOL:
2055257cf54a5810105bc4a75703a06740d756d8e8landley		return e1->left.sym == e2->left.sym;
2065257cf54a5810105bc4a75703a06740d756d8e8landley	case E_NOT:
2075257cf54a5810105bc4a75703a06740d756d8e8landley		return expr_eq(e1->left.expr, e2->left.expr);
2085257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
2095257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
2105257cf54a5810105bc4a75703a06740d756d8e8landley		e1 = expr_copy(e1);
2115257cf54a5810105bc4a75703a06740d756d8e8landley		e2 = expr_copy(e2);
2125257cf54a5810105bc4a75703a06740d756d8e8landley		old_count = trans_count;
2135257cf54a5810105bc4a75703a06740d756d8e8landley		expr_eliminate_eq(&e1, &e2);
2145257cf54a5810105bc4a75703a06740d756d8e8landley		res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
2155257cf54a5810105bc4a75703a06740d756d8e8landley		       e1->left.sym == e2->left.sym);
2165257cf54a5810105bc4a75703a06740d756d8e8landley		expr_free(e1);
2175257cf54a5810105bc4a75703a06740d756d8e8landley		expr_free(e2);
2185257cf54a5810105bc4a75703a06740d756d8e8landley		trans_count = old_count;
2195257cf54a5810105bc4a75703a06740d756d8e8landley		return res;
2205257cf54a5810105bc4a75703a06740d756d8e8landley	case E_CHOICE:
2215257cf54a5810105bc4a75703a06740d756d8e8landley	case E_RANGE:
2225257cf54a5810105bc4a75703a06740d756d8e8landley	case E_NONE:
2235257cf54a5810105bc4a75703a06740d756d8e8landley		/* panic */;
2245257cf54a5810105bc4a75703a06740d756d8e8landley	}
2255257cf54a5810105bc4a75703a06740d756d8e8landley
2265257cf54a5810105bc4a75703a06740d756d8e8landley	if (DEBUG_EXPR) {
2275257cf54a5810105bc4a75703a06740d756d8e8landley		expr_fprint(e1, stdout);
2285257cf54a5810105bc4a75703a06740d756d8e8landley		printf(" = ");
2295257cf54a5810105bc4a75703a06740d756d8e8landley		expr_fprint(e2, stdout);
2305257cf54a5810105bc4a75703a06740d756d8e8landley		printf(" ?\n");
2315257cf54a5810105bc4a75703a06740d756d8e8landley	}
2325257cf54a5810105bc4a75703a06740d756d8e8landley
2335257cf54a5810105bc4a75703a06740d756d8e8landley	return 0;
2345257cf54a5810105bc4a75703a06740d756d8e8landley}
2355257cf54a5810105bc4a75703a06740d756d8e8landley
2365257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_eliminate_yn(struct expr *e)
2375257cf54a5810105bc4a75703a06740d756d8e8landley{
2385257cf54a5810105bc4a75703a06740d756d8e8landley	struct expr *tmp;
2395257cf54a5810105bc4a75703a06740d756d8e8landley
2405257cf54a5810105bc4a75703a06740d756d8e8landley	if (e) switch (e->type) {
2415257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
2425257cf54a5810105bc4a75703a06740d756d8e8landley		e->left.expr = expr_eliminate_yn(e->left.expr);
2435257cf54a5810105bc4a75703a06740d756d8e8landley		e->right.expr = expr_eliminate_yn(e->right.expr);
2445257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->left.expr->type == E_SYMBOL) {
2455257cf54a5810105bc4a75703a06740d756d8e8landley			if (e->left.expr->left.sym == &symbol_no) {
2465257cf54a5810105bc4a75703a06740d756d8e8landley				expr_free(e->left.expr);
2475257cf54a5810105bc4a75703a06740d756d8e8landley				expr_free(e->right.expr);
2485257cf54a5810105bc4a75703a06740d756d8e8landley				e->type = E_SYMBOL;
2495257cf54a5810105bc4a75703a06740d756d8e8landley				e->left.sym = &symbol_no;
2505257cf54a5810105bc4a75703a06740d756d8e8landley				e->right.expr = NULL;
2515257cf54a5810105bc4a75703a06740d756d8e8landley				return e;
2525257cf54a5810105bc4a75703a06740d756d8e8landley			} else if (e->left.expr->left.sym == &symbol_yes) {
2535257cf54a5810105bc4a75703a06740d756d8e8landley				free(e->left.expr);
2545257cf54a5810105bc4a75703a06740d756d8e8landley				tmp = e->right.expr;
2555257cf54a5810105bc4a75703a06740d756d8e8landley				*e = *(e->right.expr);
2565257cf54a5810105bc4a75703a06740d756d8e8landley				free(tmp);
2575257cf54a5810105bc4a75703a06740d756d8e8landley				return e;
2585257cf54a5810105bc4a75703a06740d756d8e8landley			}
2595257cf54a5810105bc4a75703a06740d756d8e8landley		}
2605257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->right.expr->type == E_SYMBOL) {
2615257cf54a5810105bc4a75703a06740d756d8e8landley			if (e->right.expr->left.sym == &symbol_no) {
2625257cf54a5810105bc4a75703a06740d756d8e8landley				expr_free(e->left.expr);
2635257cf54a5810105bc4a75703a06740d756d8e8landley				expr_free(e->right.expr);
2645257cf54a5810105bc4a75703a06740d756d8e8landley				e->type = E_SYMBOL;
2655257cf54a5810105bc4a75703a06740d756d8e8landley				e->left.sym = &symbol_no;
2665257cf54a5810105bc4a75703a06740d756d8e8landley				e->right.expr = NULL;
2675257cf54a5810105bc4a75703a06740d756d8e8landley				return e;
2685257cf54a5810105bc4a75703a06740d756d8e8landley			} else if (e->right.expr->left.sym == &symbol_yes) {
2695257cf54a5810105bc4a75703a06740d756d8e8landley				free(e->right.expr);
2705257cf54a5810105bc4a75703a06740d756d8e8landley				tmp = e->left.expr;
2715257cf54a5810105bc4a75703a06740d756d8e8landley				*e = *(e->left.expr);
2725257cf54a5810105bc4a75703a06740d756d8e8landley				free(tmp);
2735257cf54a5810105bc4a75703a06740d756d8e8landley				return e;
2745257cf54a5810105bc4a75703a06740d756d8e8landley			}
2755257cf54a5810105bc4a75703a06740d756d8e8landley		}
2765257cf54a5810105bc4a75703a06740d756d8e8landley		break;
2775257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
2785257cf54a5810105bc4a75703a06740d756d8e8landley		e->left.expr = expr_eliminate_yn(e->left.expr);
2795257cf54a5810105bc4a75703a06740d756d8e8landley		e->right.expr = expr_eliminate_yn(e->right.expr);
2805257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->left.expr->type == E_SYMBOL) {
2815257cf54a5810105bc4a75703a06740d756d8e8landley			if (e->left.expr->left.sym == &symbol_no) {
2825257cf54a5810105bc4a75703a06740d756d8e8landley				free(e->left.expr);
2835257cf54a5810105bc4a75703a06740d756d8e8landley				tmp = e->right.expr;
2845257cf54a5810105bc4a75703a06740d756d8e8landley				*e = *(e->right.expr);
2855257cf54a5810105bc4a75703a06740d756d8e8landley				free(tmp);
2865257cf54a5810105bc4a75703a06740d756d8e8landley				return e;
2875257cf54a5810105bc4a75703a06740d756d8e8landley			} else if (e->left.expr->left.sym == &symbol_yes) {
2885257cf54a5810105bc4a75703a06740d756d8e8landley				expr_free(e->left.expr);
2895257cf54a5810105bc4a75703a06740d756d8e8landley				expr_free(e->right.expr);
2905257cf54a5810105bc4a75703a06740d756d8e8landley				e->type = E_SYMBOL;
2915257cf54a5810105bc4a75703a06740d756d8e8landley				e->left.sym = &symbol_yes;
2925257cf54a5810105bc4a75703a06740d756d8e8landley				e->right.expr = NULL;
2935257cf54a5810105bc4a75703a06740d756d8e8landley				return e;
2945257cf54a5810105bc4a75703a06740d756d8e8landley			}
2955257cf54a5810105bc4a75703a06740d756d8e8landley		}
2965257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->right.expr->type == E_SYMBOL) {
2975257cf54a5810105bc4a75703a06740d756d8e8landley			if (e->right.expr->left.sym == &symbol_no) {
2985257cf54a5810105bc4a75703a06740d756d8e8landley				free(e->right.expr);
2995257cf54a5810105bc4a75703a06740d756d8e8landley				tmp = e->left.expr;
3005257cf54a5810105bc4a75703a06740d756d8e8landley				*e = *(e->left.expr);
3015257cf54a5810105bc4a75703a06740d756d8e8landley				free(tmp);
3025257cf54a5810105bc4a75703a06740d756d8e8landley				return e;
3035257cf54a5810105bc4a75703a06740d756d8e8landley			} else if (e->right.expr->left.sym == &symbol_yes) {
3045257cf54a5810105bc4a75703a06740d756d8e8landley				expr_free(e->left.expr);
3055257cf54a5810105bc4a75703a06740d756d8e8landley				expr_free(e->right.expr);
3065257cf54a5810105bc4a75703a06740d756d8e8landley				e->type = E_SYMBOL;
3075257cf54a5810105bc4a75703a06740d756d8e8landley				e->left.sym = &symbol_yes;
3085257cf54a5810105bc4a75703a06740d756d8e8landley				e->right.expr = NULL;
3095257cf54a5810105bc4a75703a06740d756d8e8landley				return e;
3105257cf54a5810105bc4a75703a06740d756d8e8landley			}
3115257cf54a5810105bc4a75703a06740d756d8e8landley		}
3125257cf54a5810105bc4a75703a06740d756d8e8landley		break;
3135257cf54a5810105bc4a75703a06740d756d8e8landley	default:
3145257cf54a5810105bc4a75703a06740d756d8e8landley		;
3155257cf54a5810105bc4a75703a06740d756d8e8landley	}
3165257cf54a5810105bc4a75703a06740d756d8e8landley	return e;
3175257cf54a5810105bc4a75703a06740d756d8e8landley}
3185257cf54a5810105bc4a75703a06740d756d8e8landley
3195257cf54a5810105bc4a75703a06740d756d8e8landley/*
3205257cf54a5810105bc4a75703a06740d756d8e8landley * bool FOO!=n => FOO
3215257cf54a5810105bc4a75703a06740d756d8e8landley */
3225257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_trans_bool(struct expr *e)
3235257cf54a5810105bc4a75703a06740d756d8e8landley{
3245257cf54a5810105bc4a75703a06740d756d8e8landley	if (!e)
3255257cf54a5810105bc4a75703a06740d756d8e8landley		return NULL;
3265257cf54a5810105bc4a75703a06740d756d8e8landley	switch (e->type) {
3275257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
3285257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
3295257cf54a5810105bc4a75703a06740d756d8e8landley	case E_NOT:
3305257cf54a5810105bc4a75703a06740d756d8e8landley		e->left.expr = expr_trans_bool(e->left.expr);
3315257cf54a5810105bc4a75703a06740d756d8e8landley		e->right.expr = expr_trans_bool(e->right.expr);
3325257cf54a5810105bc4a75703a06740d756d8e8landley		break;
3335257cf54a5810105bc4a75703a06740d756d8e8landley	case E_UNEQUAL:
3345257cf54a5810105bc4a75703a06740d756d8e8landley		// FOO!=n -> FOO
3355257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->left.sym->type == S_TRISTATE) {
3365257cf54a5810105bc4a75703a06740d756d8e8landley			if (e->right.sym == &symbol_no) {
3375257cf54a5810105bc4a75703a06740d756d8e8landley				e->type = E_SYMBOL;
3385257cf54a5810105bc4a75703a06740d756d8e8landley				e->right.sym = NULL;
3395257cf54a5810105bc4a75703a06740d756d8e8landley			}
3405257cf54a5810105bc4a75703a06740d756d8e8landley		}
3415257cf54a5810105bc4a75703a06740d756d8e8landley		break;
3425257cf54a5810105bc4a75703a06740d756d8e8landley	default:
3435257cf54a5810105bc4a75703a06740d756d8e8landley		;
3445257cf54a5810105bc4a75703a06740d756d8e8landley	}
3455257cf54a5810105bc4a75703a06740d756d8e8landley	return e;
3465257cf54a5810105bc4a75703a06740d756d8e8landley}
3475257cf54a5810105bc4a75703a06740d756d8e8landley
3485257cf54a5810105bc4a75703a06740d756d8e8landley/*
3495257cf54a5810105bc4a75703a06740d756d8e8landley * e1 || e2 -> ?
3505257cf54a5810105bc4a75703a06740d756d8e8landley */
3515257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_join_or(struct expr *e1, struct expr *e2)
3525257cf54a5810105bc4a75703a06740d756d8e8landley{
3535257cf54a5810105bc4a75703a06740d756d8e8landley	struct expr *tmp;
3545257cf54a5810105bc4a75703a06740d756d8e8landley	struct symbol *sym1, *sym2;
3555257cf54a5810105bc4a75703a06740d756d8e8landley
3565257cf54a5810105bc4a75703a06740d756d8e8landley	if (expr_eq(e1, e2))
3575257cf54a5810105bc4a75703a06740d756d8e8landley		return expr_copy(e1);
3585257cf54a5810105bc4a75703a06740d756d8e8landley	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
3595257cf54a5810105bc4a75703a06740d756d8e8landley		return NULL;
3605257cf54a5810105bc4a75703a06740d756d8e8landley	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
3615257cf54a5810105bc4a75703a06740d756d8e8landley		return NULL;
3625257cf54a5810105bc4a75703a06740d756d8e8landley	if (e1->type == E_NOT) {
3635257cf54a5810105bc4a75703a06740d756d8e8landley		tmp = e1->left.expr;
3645257cf54a5810105bc4a75703a06740d756d8e8landley		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
3655257cf54a5810105bc4a75703a06740d756d8e8landley			return NULL;
3665257cf54a5810105bc4a75703a06740d756d8e8landley		sym1 = tmp->left.sym;
3675257cf54a5810105bc4a75703a06740d756d8e8landley	} else
3685257cf54a5810105bc4a75703a06740d756d8e8landley		sym1 = e1->left.sym;
3695257cf54a5810105bc4a75703a06740d756d8e8landley	if (e2->type == E_NOT) {
3705257cf54a5810105bc4a75703a06740d756d8e8landley		if (e2->left.expr->type != E_SYMBOL)
3715257cf54a5810105bc4a75703a06740d756d8e8landley			return NULL;
3725257cf54a5810105bc4a75703a06740d756d8e8landley		sym2 = e2->left.expr->left.sym;
3735257cf54a5810105bc4a75703a06740d756d8e8landley	} else
3745257cf54a5810105bc4a75703a06740d756d8e8landley		sym2 = e2->left.sym;
3755257cf54a5810105bc4a75703a06740d756d8e8landley	if (sym1 != sym2)
3765257cf54a5810105bc4a75703a06740d756d8e8landley		return NULL;
3775257cf54a5810105bc4a75703a06740d756d8e8landley	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
3785257cf54a5810105bc4a75703a06740d756d8e8landley		return NULL;
3795257cf54a5810105bc4a75703a06740d756d8e8landley	if (sym1->type == S_TRISTATE) {
3805257cf54a5810105bc4a75703a06740d756d8e8landley		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
3815257cf54a5810105bc4a75703a06740d756d8e8landley		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
3825257cf54a5810105bc4a75703a06740d756d8e8landley		     (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
3835257cf54a5810105bc4a75703a06740d756d8e8landley			// (a='y') || (a='m') -> (a!='n')
3845257cf54a5810105bc4a75703a06740d756d8e8landley			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
3855257cf54a5810105bc4a75703a06740d756d8e8landley		}
3865257cf54a5810105bc4a75703a06740d756d8e8landley		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
3875257cf54a5810105bc4a75703a06740d756d8e8landley		    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
3885257cf54a5810105bc4a75703a06740d756d8e8landley		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
3895257cf54a5810105bc4a75703a06740d756d8e8landley			// (a='y') || (a='n') -> (a!='m')
3905257cf54a5810105bc4a75703a06740d756d8e8landley			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
3915257cf54a5810105bc4a75703a06740d756d8e8landley		}
3925257cf54a5810105bc4a75703a06740d756d8e8landley		if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
3935257cf54a5810105bc4a75703a06740d756d8e8landley		    ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
3945257cf54a5810105bc4a75703a06740d756d8e8landley		     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
3955257cf54a5810105bc4a75703a06740d756d8e8landley			// (a='m') || (a='n') -> (a!='y')
3965257cf54a5810105bc4a75703a06740d756d8e8landley			return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
3975257cf54a5810105bc4a75703a06740d756d8e8landley		}
3985257cf54a5810105bc4a75703a06740d756d8e8landley	}
3995257cf54a5810105bc4a75703a06740d756d8e8landley	if (sym1->type == S_BOOLEAN && sym1 == sym2) {
4005257cf54a5810105bc4a75703a06740d756d8e8landley		if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
4015257cf54a5810105bc4a75703a06740d756d8e8landley		    (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
4025257cf54a5810105bc4a75703a06740d756d8e8landley			return expr_alloc_symbol(&symbol_yes);
4035257cf54a5810105bc4a75703a06740d756d8e8landley	}
4045257cf54a5810105bc4a75703a06740d756d8e8landley
4055257cf54a5810105bc4a75703a06740d756d8e8landley	if (DEBUG_EXPR) {
4065257cf54a5810105bc4a75703a06740d756d8e8landley		printf("optimize (");
4075257cf54a5810105bc4a75703a06740d756d8e8landley		expr_fprint(e1, stdout);
4085257cf54a5810105bc4a75703a06740d756d8e8landley		printf(") || (");
4095257cf54a5810105bc4a75703a06740d756d8e8landley		expr_fprint(e2, stdout);
4105257cf54a5810105bc4a75703a06740d756d8e8landley		printf(")?\n");
4115257cf54a5810105bc4a75703a06740d756d8e8landley	}
4125257cf54a5810105bc4a75703a06740d756d8e8landley	return NULL;
4135257cf54a5810105bc4a75703a06740d756d8e8landley}
4145257cf54a5810105bc4a75703a06740d756d8e8landley
4155257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_join_and(struct expr *e1, struct expr *e2)
4165257cf54a5810105bc4a75703a06740d756d8e8landley{
4175257cf54a5810105bc4a75703a06740d756d8e8landley	struct expr *tmp;
4185257cf54a5810105bc4a75703a06740d756d8e8landley	struct symbol *sym1, *sym2;
4195257cf54a5810105bc4a75703a06740d756d8e8landley
4205257cf54a5810105bc4a75703a06740d756d8e8landley	if (expr_eq(e1, e2))
4215257cf54a5810105bc4a75703a06740d756d8e8landley		return expr_copy(e1);
4225257cf54a5810105bc4a75703a06740d756d8e8landley	if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
4235257cf54a5810105bc4a75703a06740d756d8e8landley		return NULL;
4245257cf54a5810105bc4a75703a06740d756d8e8landley	if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
4255257cf54a5810105bc4a75703a06740d756d8e8landley		return NULL;
4265257cf54a5810105bc4a75703a06740d756d8e8landley	if (e1->type == E_NOT) {
4275257cf54a5810105bc4a75703a06740d756d8e8landley		tmp = e1->left.expr;
4285257cf54a5810105bc4a75703a06740d756d8e8landley		if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
4295257cf54a5810105bc4a75703a06740d756d8e8landley			return NULL;
4305257cf54a5810105bc4a75703a06740d756d8e8landley		sym1 = tmp->left.sym;
4315257cf54a5810105bc4a75703a06740d756d8e8landley	} else
4325257cf54a5810105bc4a75703a06740d756d8e8landley		sym1 = e1->left.sym;
4335257cf54a5810105bc4a75703a06740d756d8e8landley	if (e2->type == E_NOT) {
4345257cf54a5810105bc4a75703a06740d756d8e8landley		if (e2->left.expr->type != E_SYMBOL)
4355257cf54a5810105bc4a75703a06740d756d8e8landley			return NULL;
4365257cf54a5810105bc4a75703a06740d756d8e8landley		sym2 = e2->left.expr->left.sym;
4375257cf54a5810105bc4a75703a06740d756d8e8landley	} else
4385257cf54a5810105bc4a75703a06740d756d8e8landley		sym2 = e2->left.sym;
4395257cf54a5810105bc4a75703a06740d756d8e8landley	if (sym1 != sym2)
4405257cf54a5810105bc4a75703a06740d756d8e8landley		return NULL;
4415257cf54a5810105bc4a75703a06740d756d8e8landley	if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
4425257cf54a5810105bc4a75703a06740d756d8e8landley		return NULL;
4435257cf54a5810105bc4a75703a06740d756d8e8landley
4445257cf54a5810105bc4a75703a06740d756d8e8landley	if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
4455257cf54a5810105bc4a75703a06740d756d8e8landley	    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
4465257cf54a5810105bc4a75703a06740d756d8e8landley		// (a) && (a='y') -> (a='y')
4475257cf54a5810105bc4a75703a06740d756d8e8landley		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
4485257cf54a5810105bc4a75703a06740d756d8e8landley
4495257cf54a5810105bc4a75703a06740d756d8e8landley	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
4505257cf54a5810105bc4a75703a06740d756d8e8landley	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
4515257cf54a5810105bc4a75703a06740d756d8e8landley		// (a) && (a!='n') -> (a)
4525257cf54a5810105bc4a75703a06740d756d8e8landley		return expr_alloc_symbol(sym1);
4535257cf54a5810105bc4a75703a06740d756d8e8landley
4545257cf54a5810105bc4a75703a06740d756d8e8landley	if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
4555257cf54a5810105bc4a75703a06740d756d8e8landley	    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
4565257cf54a5810105bc4a75703a06740d756d8e8landley		// (a) && (a!='m') -> (a='y')
4575257cf54a5810105bc4a75703a06740d756d8e8landley		return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
4585257cf54a5810105bc4a75703a06740d756d8e8landley
4595257cf54a5810105bc4a75703a06740d756d8e8landley	if (sym1->type == S_TRISTATE) {
4605257cf54a5810105bc4a75703a06740d756d8e8landley		if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
4615257cf54a5810105bc4a75703a06740d756d8e8landley			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
4625257cf54a5810105bc4a75703a06740d756d8e8landley			sym2 = e1->right.sym;
4635257cf54a5810105bc4a75703a06740d756d8e8landley			if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
4645257cf54a5810105bc4a75703a06740d756d8e8landley				return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
4655257cf54a5810105bc4a75703a06740d756d8e8landley							     : expr_alloc_symbol(&symbol_no);
4665257cf54a5810105bc4a75703a06740d756d8e8landley		}
4675257cf54a5810105bc4a75703a06740d756d8e8landley		if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
4685257cf54a5810105bc4a75703a06740d756d8e8landley			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
4695257cf54a5810105bc4a75703a06740d756d8e8landley			sym2 = e2->right.sym;
4705257cf54a5810105bc4a75703a06740d756d8e8landley			if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
4715257cf54a5810105bc4a75703a06740d756d8e8landley				return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
4725257cf54a5810105bc4a75703a06740d756d8e8landley							     : expr_alloc_symbol(&symbol_no);
4735257cf54a5810105bc4a75703a06740d756d8e8landley		}
4745257cf54a5810105bc4a75703a06740d756d8e8landley		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
4755257cf54a5810105bc4a75703a06740d756d8e8landley			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
4765257cf54a5810105bc4a75703a06740d756d8e8landley			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
4775257cf54a5810105bc4a75703a06740d756d8e8landley			// (a!='y') && (a!='n') -> (a='m')
4785257cf54a5810105bc4a75703a06740d756d8e8landley			return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
4795257cf54a5810105bc4a75703a06740d756d8e8landley
4805257cf54a5810105bc4a75703a06740d756d8e8landley		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
4815257cf54a5810105bc4a75703a06740d756d8e8landley			   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
4825257cf54a5810105bc4a75703a06740d756d8e8landley			    (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
4835257cf54a5810105bc4a75703a06740d756d8e8landley			// (a!='y') && (a!='m') -> (a='n')
4845257cf54a5810105bc4a75703a06740d756d8e8landley			return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
4855257cf54a5810105bc4a75703a06740d756d8e8landley
4865257cf54a5810105bc4a75703a06740d756d8e8landley		if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
4875257cf54a5810105bc4a75703a06740d756d8e8landley			   ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
4885257cf54a5810105bc4a75703a06740d756d8e8landley			    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
4895257cf54a5810105bc4a75703a06740d756d8e8landley			// (a!='m') && (a!='n') -> (a='m')
4905257cf54a5810105bc4a75703a06740d756d8e8landley			return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
4915257cf54a5810105bc4a75703a06740d756d8e8landley
4925257cf54a5810105bc4a75703a06740d756d8e8landley		if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
4935257cf54a5810105bc4a75703a06740d756d8e8landley		    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
4945257cf54a5810105bc4a75703a06740d756d8e8landley		    (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
4955257cf54a5810105bc4a75703a06740d756d8e8landley		    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
4965257cf54a5810105bc4a75703a06740d756d8e8landley			return NULL;
4975257cf54a5810105bc4a75703a06740d756d8e8landley	}
4985257cf54a5810105bc4a75703a06740d756d8e8landley
4995257cf54a5810105bc4a75703a06740d756d8e8landley	if (DEBUG_EXPR) {
5005257cf54a5810105bc4a75703a06740d756d8e8landley		printf("optimize (");
5015257cf54a5810105bc4a75703a06740d756d8e8landley		expr_fprint(e1, stdout);
5025257cf54a5810105bc4a75703a06740d756d8e8landley		printf(") && (");
5035257cf54a5810105bc4a75703a06740d756d8e8landley		expr_fprint(e2, stdout);
5045257cf54a5810105bc4a75703a06740d756d8e8landley		printf(")?\n");
5055257cf54a5810105bc4a75703a06740d756d8e8landley	}
5065257cf54a5810105bc4a75703a06740d756d8e8landley	return NULL;
5075257cf54a5810105bc4a75703a06740d756d8e8landley}
5085257cf54a5810105bc4a75703a06740d756d8e8landley
5095257cf54a5810105bc4a75703a06740d756d8e8landleystatic void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
5105257cf54a5810105bc4a75703a06740d756d8e8landley{
5115257cf54a5810105bc4a75703a06740d756d8e8landley#define e1 (*ep1)
5125257cf54a5810105bc4a75703a06740d756d8e8landley#define e2 (*ep2)
5135257cf54a5810105bc4a75703a06740d756d8e8landley	struct expr *tmp;
5145257cf54a5810105bc4a75703a06740d756d8e8landley
5155257cf54a5810105bc4a75703a06740d756d8e8landley	if (e1->type == type) {
5165257cf54a5810105bc4a75703a06740d756d8e8landley		expr_eliminate_dups1(type, &e1->left.expr, &e2);
5175257cf54a5810105bc4a75703a06740d756d8e8landley		expr_eliminate_dups1(type, &e1->right.expr, &e2);
5185257cf54a5810105bc4a75703a06740d756d8e8landley		return;
5195257cf54a5810105bc4a75703a06740d756d8e8landley	}
5205257cf54a5810105bc4a75703a06740d756d8e8landley	if (e2->type == type) {
5215257cf54a5810105bc4a75703a06740d756d8e8landley		expr_eliminate_dups1(type, &e1, &e2->left.expr);
5225257cf54a5810105bc4a75703a06740d756d8e8landley		expr_eliminate_dups1(type, &e1, &e2->right.expr);
5235257cf54a5810105bc4a75703a06740d756d8e8landley		return;
5245257cf54a5810105bc4a75703a06740d756d8e8landley	}
5255257cf54a5810105bc4a75703a06740d756d8e8landley	if (e1 == e2)
5265257cf54a5810105bc4a75703a06740d756d8e8landley		return;
5275257cf54a5810105bc4a75703a06740d756d8e8landley
5285257cf54a5810105bc4a75703a06740d756d8e8landley	switch (e1->type) {
5295257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR: case E_AND:
5305257cf54a5810105bc4a75703a06740d756d8e8landley		expr_eliminate_dups1(e1->type, &e1, &e1);
5315257cf54a5810105bc4a75703a06740d756d8e8landley	default:
5325257cf54a5810105bc4a75703a06740d756d8e8landley		;
5335257cf54a5810105bc4a75703a06740d756d8e8landley	}
5345257cf54a5810105bc4a75703a06740d756d8e8landley
5355257cf54a5810105bc4a75703a06740d756d8e8landley	switch (type) {
5365257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
5375257cf54a5810105bc4a75703a06740d756d8e8landley		tmp = expr_join_or(e1, e2);
5385257cf54a5810105bc4a75703a06740d756d8e8landley		if (tmp) {
5395257cf54a5810105bc4a75703a06740d756d8e8landley			expr_free(e1); expr_free(e2);
5405257cf54a5810105bc4a75703a06740d756d8e8landley			e1 = expr_alloc_symbol(&symbol_no);
5415257cf54a5810105bc4a75703a06740d756d8e8landley			e2 = tmp;
5425257cf54a5810105bc4a75703a06740d756d8e8landley			trans_count++;
5435257cf54a5810105bc4a75703a06740d756d8e8landley		}
5445257cf54a5810105bc4a75703a06740d756d8e8landley		break;
5455257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
5465257cf54a5810105bc4a75703a06740d756d8e8landley		tmp = expr_join_and(e1, e2);
5475257cf54a5810105bc4a75703a06740d756d8e8landley		if (tmp) {
5485257cf54a5810105bc4a75703a06740d756d8e8landley			expr_free(e1); expr_free(e2);
5495257cf54a5810105bc4a75703a06740d756d8e8landley			e1 = expr_alloc_symbol(&symbol_yes);
5505257cf54a5810105bc4a75703a06740d756d8e8landley			e2 = tmp;
5515257cf54a5810105bc4a75703a06740d756d8e8landley			trans_count++;
5525257cf54a5810105bc4a75703a06740d756d8e8landley		}
5535257cf54a5810105bc4a75703a06740d756d8e8landley		break;
5545257cf54a5810105bc4a75703a06740d756d8e8landley	default:
5555257cf54a5810105bc4a75703a06740d756d8e8landley		;
5565257cf54a5810105bc4a75703a06740d756d8e8landley	}
5575257cf54a5810105bc4a75703a06740d756d8e8landley#undef e1
5585257cf54a5810105bc4a75703a06740d756d8e8landley#undef e2
5595257cf54a5810105bc4a75703a06740d756d8e8landley}
5605257cf54a5810105bc4a75703a06740d756d8e8landley
5615257cf54a5810105bc4a75703a06740d756d8e8landleystatic void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)
5625257cf54a5810105bc4a75703a06740d756d8e8landley{
5635257cf54a5810105bc4a75703a06740d756d8e8landley#define e1 (*ep1)
5645257cf54a5810105bc4a75703a06740d756d8e8landley#define e2 (*ep2)
5655257cf54a5810105bc4a75703a06740d756d8e8landley	struct expr *tmp, *tmp1, *tmp2;
5665257cf54a5810105bc4a75703a06740d756d8e8landley
5675257cf54a5810105bc4a75703a06740d756d8e8landley	if (e1->type == type) {
5685257cf54a5810105bc4a75703a06740d756d8e8landley		expr_eliminate_dups2(type, &e1->left.expr, &e2);
5695257cf54a5810105bc4a75703a06740d756d8e8landley		expr_eliminate_dups2(type, &e1->right.expr, &e2);
5705257cf54a5810105bc4a75703a06740d756d8e8landley		return;
5715257cf54a5810105bc4a75703a06740d756d8e8landley	}
5725257cf54a5810105bc4a75703a06740d756d8e8landley	if (e2->type == type) {
5735257cf54a5810105bc4a75703a06740d756d8e8landley		expr_eliminate_dups2(type, &e1, &e2->left.expr);
5745257cf54a5810105bc4a75703a06740d756d8e8landley		expr_eliminate_dups2(type, &e1, &e2->right.expr);
5755257cf54a5810105bc4a75703a06740d756d8e8landley	}
5765257cf54a5810105bc4a75703a06740d756d8e8landley	if (e1 == e2)
5775257cf54a5810105bc4a75703a06740d756d8e8landley		return;
5785257cf54a5810105bc4a75703a06740d756d8e8landley
5795257cf54a5810105bc4a75703a06740d756d8e8landley	switch (e1->type) {
5805257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
5815257cf54a5810105bc4a75703a06740d756d8e8landley		expr_eliminate_dups2(e1->type, &e1, &e1);
5825257cf54a5810105bc4a75703a06740d756d8e8landley		// (FOO || BAR) && (!FOO && !BAR) -> n
5835257cf54a5810105bc4a75703a06740d756d8e8landley		tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
5845257cf54a5810105bc4a75703a06740d756d8e8landley		tmp2 = expr_copy(e2);
5855257cf54a5810105bc4a75703a06740d756d8e8landley		tmp = expr_extract_eq_and(&tmp1, &tmp2);
5865257cf54a5810105bc4a75703a06740d756d8e8landley		if (expr_is_yes(tmp1)) {
5875257cf54a5810105bc4a75703a06740d756d8e8landley			expr_free(e1);
5885257cf54a5810105bc4a75703a06740d756d8e8landley			e1 = expr_alloc_symbol(&symbol_no);
5895257cf54a5810105bc4a75703a06740d756d8e8landley			trans_count++;
5905257cf54a5810105bc4a75703a06740d756d8e8landley		}
5915257cf54a5810105bc4a75703a06740d756d8e8landley		expr_free(tmp2);
5925257cf54a5810105bc4a75703a06740d756d8e8landley		expr_free(tmp1);
5935257cf54a5810105bc4a75703a06740d756d8e8landley		expr_free(tmp);
5945257cf54a5810105bc4a75703a06740d756d8e8landley		break;
5955257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
5965257cf54a5810105bc4a75703a06740d756d8e8landley		expr_eliminate_dups2(e1->type, &e1, &e1);
5975257cf54a5810105bc4a75703a06740d756d8e8landley		// (FOO && BAR) || (!FOO || !BAR) -> y
5985257cf54a5810105bc4a75703a06740d756d8e8landley		tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
5995257cf54a5810105bc4a75703a06740d756d8e8landley		tmp2 = expr_copy(e2);
6005257cf54a5810105bc4a75703a06740d756d8e8landley		tmp = expr_extract_eq_or(&tmp1, &tmp2);
6015257cf54a5810105bc4a75703a06740d756d8e8landley		if (expr_is_no(tmp1)) {
6025257cf54a5810105bc4a75703a06740d756d8e8landley			expr_free(e1);
6035257cf54a5810105bc4a75703a06740d756d8e8landley			e1 = expr_alloc_symbol(&symbol_yes);
6045257cf54a5810105bc4a75703a06740d756d8e8landley			trans_count++;
6055257cf54a5810105bc4a75703a06740d756d8e8landley		}
6065257cf54a5810105bc4a75703a06740d756d8e8landley		expr_free(tmp2);
6075257cf54a5810105bc4a75703a06740d756d8e8landley		expr_free(tmp1);
6085257cf54a5810105bc4a75703a06740d756d8e8landley		expr_free(tmp);
6095257cf54a5810105bc4a75703a06740d756d8e8landley		break;
6105257cf54a5810105bc4a75703a06740d756d8e8landley	default:
6115257cf54a5810105bc4a75703a06740d756d8e8landley		;
6125257cf54a5810105bc4a75703a06740d756d8e8landley	}
6135257cf54a5810105bc4a75703a06740d756d8e8landley#undef e1
6145257cf54a5810105bc4a75703a06740d756d8e8landley#undef e2
6155257cf54a5810105bc4a75703a06740d756d8e8landley}
6165257cf54a5810105bc4a75703a06740d756d8e8landley
6175257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_eliminate_dups(struct expr *e)
6185257cf54a5810105bc4a75703a06740d756d8e8landley{
6195257cf54a5810105bc4a75703a06740d756d8e8landley	int oldcount;
6205257cf54a5810105bc4a75703a06740d756d8e8landley	if (!e)
6215257cf54a5810105bc4a75703a06740d756d8e8landley		return e;
6225257cf54a5810105bc4a75703a06740d756d8e8landley
6235257cf54a5810105bc4a75703a06740d756d8e8landley	oldcount = trans_count;
6245257cf54a5810105bc4a75703a06740d756d8e8landley	while (1) {
6255257cf54a5810105bc4a75703a06740d756d8e8landley		trans_count = 0;
6265257cf54a5810105bc4a75703a06740d756d8e8landley		switch (e->type) {
6275257cf54a5810105bc4a75703a06740d756d8e8landley		case E_OR: case E_AND:
6285257cf54a5810105bc4a75703a06740d756d8e8landley			expr_eliminate_dups1(e->type, &e, &e);
6295257cf54a5810105bc4a75703a06740d756d8e8landley			expr_eliminate_dups2(e->type, &e, &e);
6305257cf54a5810105bc4a75703a06740d756d8e8landley		default:
6315257cf54a5810105bc4a75703a06740d756d8e8landley			;
6325257cf54a5810105bc4a75703a06740d756d8e8landley		}
6335257cf54a5810105bc4a75703a06740d756d8e8landley		if (!trans_count)
6345257cf54a5810105bc4a75703a06740d756d8e8landley			break;
6355257cf54a5810105bc4a75703a06740d756d8e8landley		e = expr_eliminate_yn(e);
6365257cf54a5810105bc4a75703a06740d756d8e8landley	}
6375257cf54a5810105bc4a75703a06740d756d8e8landley	trans_count = oldcount;
6385257cf54a5810105bc4a75703a06740d756d8e8landley	return e;
6395257cf54a5810105bc4a75703a06740d756d8e8landley}
6405257cf54a5810105bc4a75703a06740d756d8e8landley
6415257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_transform(struct expr *e)
6425257cf54a5810105bc4a75703a06740d756d8e8landley{
6435257cf54a5810105bc4a75703a06740d756d8e8landley	struct expr *tmp;
6445257cf54a5810105bc4a75703a06740d756d8e8landley
6455257cf54a5810105bc4a75703a06740d756d8e8landley	if (!e)
6465257cf54a5810105bc4a75703a06740d756d8e8landley		return NULL;
6475257cf54a5810105bc4a75703a06740d756d8e8landley	switch (e->type) {
6485257cf54a5810105bc4a75703a06740d756d8e8landley	case E_EQUAL:
6495257cf54a5810105bc4a75703a06740d756d8e8landley	case E_UNEQUAL:
6505257cf54a5810105bc4a75703a06740d756d8e8landley	case E_SYMBOL:
6515257cf54a5810105bc4a75703a06740d756d8e8landley	case E_CHOICE:
6525257cf54a5810105bc4a75703a06740d756d8e8landley		break;
6535257cf54a5810105bc4a75703a06740d756d8e8landley	default:
6545257cf54a5810105bc4a75703a06740d756d8e8landley		e->left.expr = expr_transform(e->left.expr);
6555257cf54a5810105bc4a75703a06740d756d8e8landley		e->right.expr = expr_transform(e->right.expr);
6565257cf54a5810105bc4a75703a06740d756d8e8landley	}
6575257cf54a5810105bc4a75703a06740d756d8e8landley
6585257cf54a5810105bc4a75703a06740d756d8e8landley	switch (e->type) {
6595257cf54a5810105bc4a75703a06740d756d8e8landley	case E_EQUAL:
6605257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->left.sym->type != S_BOOLEAN)
6615257cf54a5810105bc4a75703a06740d756d8e8landley			break;
6625257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->right.sym == &symbol_no) {
6635257cf54a5810105bc4a75703a06740d756d8e8landley			e->type = E_NOT;
6645257cf54a5810105bc4a75703a06740d756d8e8landley			e->left.expr = expr_alloc_symbol(e->left.sym);
6655257cf54a5810105bc4a75703a06740d756d8e8landley			e->right.sym = NULL;
6665257cf54a5810105bc4a75703a06740d756d8e8landley			break;
6675257cf54a5810105bc4a75703a06740d756d8e8landley		}
6685257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->right.sym == &symbol_mod) {
6695257cf54a5810105bc4a75703a06740d756d8e8landley			printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
6705257cf54a5810105bc4a75703a06740d756d8e8landley			e->type = E_SYMBOL;
6715257cf54a5810105bc4a75703a06740d756d8e8landley			e->left.sym = &symbol_no;
6725257cf54a5810105bc4a75703a06740d756d8e8landley			e->right.sym = NULL;
6735257cf54a5810105bc4a75703a06740d756d8e8landley			break;
6745257cf54a5810105bc4a75703a06740d756d8e8landley		}
6755257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->right.sym == &symbol_yes) {
6765257cf54a5810105bc4a75703a06740d756d8e8landley			e->type = E_SYMBOL;
6775257cf54a5810105bc4a75703a06740d756d8e8landley			e->right.sym = NULL;
6785257cf54a5810105bc4a75703a06740d756d8e8landley			break;
6795257cf54a5810105bc4a75703a06740d756d8e8landley		}
6805257cf54a5810105bc4a75703a06740d756d8e8landley		break;
6815257cf54a5810105bc4a75703a06740d756d8e8landley	case E_UNEQUAL:
6825257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->left.sym->type != S_BOOLEAN)
6835257cf54a5810105bc4a75703a06740d756d8e8landley			break;
6845257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->right.sym == &symbol_no) {
6855257cf54a5810105bc4a75703a06740d756d8e8landley			e->type = E_SYMBOL;
6865257cf54a5810105bc4a75703a06740d756d8e8landley			e->right.sym = NULL;
6875257cf54a5810105bc4a75703a06740d756d8e8landley			break;
6885257cf54a5810105bc4a75703a06740d756d8e8landley		}
6895257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->right.sym == &symbol_mod) {
6905257cf54a5810105bc4a75703a06740d756d8e8landley			printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
6915257cf54a5810105bc4a75703a06740d756d8e8landley			e->type = E_SYMBOL;
6925257cf54a5810105bc4a75703a06740d756d8e8landley			e->left.sym = &symbol_yes;
6935257cf54a5810105bc4a75703a06740d756d8e8landley			e->right.sym = NULL;
6945257cf54a5810105bc4a75703a06740d756d8e8landley			break;
6955257cf54a5810105bc4a75703a06740d756d8e8landley		}
6965257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->right.sym == &symbol_yes) {
6975257cf54a5810105bc4a75703a06740d756d8e8landley			e->type = E_NOT;
6985257cf54a5810105bc4a75703a06740d756d8e8landley			e->left.expr = expr_alloc_symbol(e->left.sym);
6995257cf54a5810105bc4a75703a06740d756d8e8landley			e->right.sym = NULL;
7005257cf54a5810105bc4a75703a06740d756d8e8landley			break;
7015257cf54a5810105bc4a75703a06740d756d8e8landley		}
7025257cf54a5810105bc4a75703a06740d756d8e8landley		break;
7035257cf54a5810105bc4a75703a06740d756d8e8landley	case E_NOT:
7045257cf54a5810105bc4a75703a06740d756d8e8landley		switch (e->left.expr->type) {
7055257cf54a5810105bc4a75703a06740d756d8e8landley		case E_NOT:
7065257cf54a5810105bc4a75703a06740d756d8e8landley			// !!a -> a
7075257cf54a5810105bc4a75703a06740d756d8e8landley			tmp = e->left.expr->left.expr;
7085257cf54a5810105bc4a75703a06740d756d8e8landley			free(e->left.expr);
7095257cf54a5810105bc4a75703a06740d756d8e8landley			free(e);
7105257cf54a5810105bc4a75703a06740d756d8e8landley			e = tmp;
7115257cf54a5810105bc4a75703a06740d756d8e8landley			e = expr_transform(e);
7125257cf54a5810105bc4a75703a06740d756d8e8landley			break;
7135257cf54a5810105bc4a75703a06740d756d8e8landley		case E_EQUAL:
7145257cf54a5810105bc4a75703a06740d756d8e8landley		case E_UNEQUAL:
7155257cf54a5810105bc4a75703a06740d756d8e8landley			// !a='x' -> a!='x'
7165257cf54a5810105bc4a75703a06740d756d8e8landley			tmp = e->left.expr;
7175257cf54a5810105bc4a75703a06740d756d8e8landley			free(e);
7185257cf54a5810105bc4a75703a06740d756d8e8landley			e = tmp;
7195257cf54a5810105bc4a75703a06740d756d8e8landley			e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
7205257cf54a5810105bc4a75703a06740d756d8e8landley			break;
7215257cf54a5810105bc4a75703a06740d756d8e8landley		case E_OR:
7225257cf54a5810105bc4a75703a06740d756d8e8landley			// !(a || b) -> !a && !b
7235257cf54a5810105bc4a75703a06740d756d8e8landley			tmp = e->left.expr;
7245257cf54a5810105bc4a75703a06740d756d8e8landley			e->type = E_AND;
7255257cf54a5810105bc4a75703a06740d756d8e8landley			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
7265257cf54a5810105bc4a75703a06740d756d8e8landley			tmp->type = E_NOT;
7275257cf54a5810105bc4a75703a06740d756d8e8landley			tmp->right.expr = NULL;
7285257cf54a5810105bc4a75703a06740d756d8e8landley			e = expr_transform(e);
7295257cf54a5810105bc4a75703a06740d756d8e8landley			break;
7305257cf54a5810105bc4a75703a06740d756d8e8landley		case E_AND:
7315257cf54a5810105bc4a75703a06740d756d8e8landley			// !(a && b) -> !a || !b
7325257cf54a5810105bc4a75703a06740d756d8e8landley			tmp = e->left.expr;
7335257cf54a5810105bc4a75703a06740d756d8e8landley			e->type = E_OR;
7345257cf54a5810105bc4a75703a06740d756d8e8landley			e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
7355257cf54a5810105bc4a75703a06740d756d8e8landley			tmp->type = E_NOT;
7365257cf54a5810105bc4a75703a06740d756d8e8landley			tmp->right.expr = NULL;
7375257cf54a5810105bc4a75703a06740d756d8e8landley			e = expr_transform(e);
7385257cf54a5810105bc4a75703a06740d756d8e8landley			break;
7395257cf54a5810105bc4a75703a06740d756d8e8landley		case E_SYMBOL:
7405257cf54a5810105bc4a75703a06740d756d8e8landley			if (e->left.expr->left.sym == &symbol_yes) {
7415257cf54a5810105bc4a75703a06740d756d8e8landley				// !'y' -> 'n'
7425257cf54a5810105bc4a75703a06740d756d8e8landley				tmp = e->left.expr;
7435257cf54a5810105bc4a75703a06740d756d8e8landley				free(e);
7445257cf54a5810105bc4a75703a06740d756d8e8landley				e = tmp;
7455257cf54a5810105bc4a75703a06740d756d8e8landley				e->type = E_SYMBOL;
7465257cf54a5810105bc4a75703a06740d756d8e8landley				e->left.sym = &symbol_no;
7475257cf54a5810105bc4a75703a06740d756d8e8landley				break;
7485257cf54a5810105bc4a75703a06740d756d8e8landley			}
7495257cf54a5810105bc4a75703a06740d756d8e8landley			if (e->left.expr->left.sym == &symbol_mod) {
7505257cf54a5810105bc4a75703a06740d756d8e8landley				// !'m' -> 'm'
7515257cf54a5810105bc4a75703a06740d756d8e8landley				tmp = e->left.expr;
7525257cf54a5810105bc4a75703a06740d756d8e8landley				free(e);
7535257cf54a5810105bc4a75703a06740d756d8e8landley				e = tmp;
7545257cf54a5810105bc4a75703a06740d756d8e8landley				e->type = E_SYMBOL;
7555257cf54a5810105bc4a75703a06740d756d8e8landley				e->left.sym = &symbol_mod;
7565257cf54a5810105bc4a75703a06740d756d8e8landley				break;
7575257cf54a5810105bc4a75703a06740d756d8e8landley			}
7585257cf54a5810105bc4a75703a06740d756d8e8landley			if (e->left.expr->left.sym == &symbol_no) {
7595257cf54a5810105bc4a75703a06740d756d8e8landley				// !'n' -> 'y'
7605257cf54a5810105bc4a75703a06740d756d8e8landley				tmp = e->left.expr;
7615257cf54a5810105bc4a75703a06740d756d8e8landley				free(e);
7625257cf54a5810105bc4a75703a06740d756d8e8landley				e = tmp;
7635257cf54a5810105bc4a75703a06740d756d8e8landley				e->type = E_SYMBOL;
7645257cf54a5810105bc4a75703a06740d756d8e8landley				e->left.sym = &symbol_yes;
7655257cf54a5810105bc4a75703a06740d756d8e8landley				break;
7665257cf54a5810105bc4a75703a06740d756d8e8landley			}
7675257cf54a5810105bc4a75703a06740d756d8e8landley			break;
7685257cf54a5810105bc4a75703a06740d756d8e8landley		default:
7695257cf54a5810105bc4a75703a06740d756d8e8landley			;
7705257cf54a5810105bc4a75703a06740d756d8e8landley		}
7715257cf54a5810105bc4a75703a06740d756d8e8landley		break;
7725257cf54a5810105bc4a75703a06740d756d8e8landley	default:
7735257cf54a5810105bc4a75703a06740d756d8e8landley		;
7745257cf54a5810105bc4a75703a06740d756d8e8landley	}
7755257cf54a5810105bc4a75703a06740d756d8e8landley	return e;
7765257cf54a5810105bc4a75703a06740d756d8e8landley}
7775257cf54a5810105bc4a75703a06740d756d8e8landley
7785257cf54a5810105bc4a75703a06740d756d8e8landleyint expr_contains_symbol(struct expr *dep, struct symbol *sym)
7795257cf54a5810105bc4a75703a06740d756d8e8landley{
7805257cf54a5810105bc4a75703a06740d756d8e8landley	if (!dep)
7815257cf54a5810105bc4a75703a06740d756d8e8landley		return 0;
7825257cf54a5810105bc4a75703a06740d756d8e8landley
7835257cf54a5810105bc4a75703a06740d756d8e8landley	switch (dep->type) {
7845257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
7855257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
7865257cf54a5810105bc4a75703a06740d756d8e8landley		return expr_contains_symbol(dep->left.expr, sym) ||
7875257cf54a5810105bc4a75703a06740d756d8e8landley		       expr_contains_symbol(dep->right.expr, sym);
7885257cf54a5810105bc4a75703a06740d756d8e8landley	case E_SYMBOL:
7895257cf54a5810105bc4a75703a06740d756d8e8landley		return dep->left.sym == sym;
7905257cf54a5810105bc4a75703a06740d756d8e8landley	case E_EQUAL:
7915257cf54a5810105bc4a75703a06740d756d8e8landley	case E_UNEQUAL:
7925257cf54a5810105bc4a75703a06740d756d8e8landley		return dep->left.sym == sym ||
7935257cf54a5810105bc4a75703a06740d756d8e8landley		       dep->right.sym == sym;
7945257cf54a5810105bc4a75703a06740d756d8e8landley	case E_NOT:
7955257cf54a5810105bc4a75703a06740d756d8e8landley		return expr_contains_symbol(dep->left.expr, sym);
7965257cf54a5810105bc4a75703a06740d756d8e8landley	default:
7975257cf54a5810105bc4a75703a06740d756d8e8landley		;
7985257cf54a5810105bc4a75703a06740d756d8e8landley	}
7995257cf54a5810105bc4a75703a06740d756d8e8landley	return 0;
8005257cf54a5810105bc4a75703a06740d756d8e8landley}
8015257cf54a5810105bc4a75703a06740d756d8e8landley
8025257cf54a5810105bc4a75703a06740d756d8e8landleybool expr_depends_symbol(struct expr *dep, struct symbol *sym)
8035257cf54a5810105bc4a75703a06740d756d8e8landley{
8045257cf54a5810105bc4a75703a06740d756d8e8landley	if (!dep)
8055257cf54a5810105bc4a75703a06740d756d8e8landley		return false;
8065257cf54a5810105bc4a75703a06740d756d8e8landley
8075257cf54a5810105bc4a75703a06740d756d8e8landley	switch (dep->type) {
8085257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
8095257cf54a5810105bc4a75703a06740d756d8e8landley		return expr_depends_symbol(dep->left.expr, sym) ||
8105257cf54a5810105bc4a75703a06740d756d8e8landley		       expr_depends_symbol(dep->right.expr, sym);
8115257cf54a5810105bc4a75703a06740d756d8e8landley	case E_SYMBOL:
8125257cf54a5810105bc4a75703a06740d756d8e8landley		return dep->left.sym == sym;
8135257cf54a5810105bc4a75703a06740d756d8e8landley	case E_EQUAL:
8145257cf54a5810105bc4a75703a06740d756d8e8landley		if (dep->left.sym == sym) {
8155257cf54a5810105bc4a75703a06740d756d8e8landley			if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
8165257cf54a5810105bc4a75703a06740d756d8e8landley				return true;
8175257cf54a5810105bc4a75703a06740d756d8e8landley		}
8185257cf54a5810105bc4a75703a06740d756d8e8landley		break;
8195257cf54a5810105bc4a75703a06740d756d8e8landley	case E_UNEQUAL:
8205257cf54a5810105bc4a75703a06740d756d8e8landley		if (dep->left.sym == sym) {
8215257cf54a5810105bc4a75703a06740d756d8e8landley			if (dep->right.sym == &symbol_no)
8225257cf54a5810105bc4a75703a06740d756d8e8landley				return true;
8235257cf54a5810105bc4a75703a06740d756d8e8landley		}
8245257cf54a5810105bc4a75703a06740d756d8e8landley		break;
8255257cf54a5810105bc4a75703a06740d756d8e8landley	default:
8265257cf54a5810105bc4a75703a06740d756d8e8landley		;
8275257cf54a5810105bc4a75703a06740d756d8e8landley	}
8285257cf54a5810105bc4a75703a06740d756d8e8landley 	return false;
8295257cf54a5810105bc4a75703a06740d756d8e8landley}
8305257cf54a5810105bc4a75703a06740d756d8e8landley
8315257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)
8325257cf54a5810105bc4a75703a06740d756d8e8landley{
8335257cf54a5810105bc4a75703a06740d756d8e8landley	struct expr *tmp = NULL;
8345257cf54a5810105bc4a75703a06740d756d8e8landley	expr_extract_eq(E_AND, &tmp, ep1, ep2);
8355257cf54a5810105bc4a75703a06740d756d8e8landley	if (tmp) {
8365257cf54a5810105bc4a75703a06740d756d8e8landley		*ep1 = expr_eliminate_yn(*ep1);
8375257cf54a5810105bc4a75703a06740d756d8e8landley		*ep2 = expr_eliminate_yn(*ep2);
8385257cf54a5810105bc4a75703a06740d756d8e8landley	}
8395257cf54a5810105bc4a75703a06740d756d8e8landley	return tmp;
8405257cf54a5810105bc4a75703a06740d756d8e8landley}
8415257cf54a5810105bc4a75703a06740d756d8e8landley
8425257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)
8435257cf54a5810105bc4a75703a06740d756d8e8landley{
8445257cf54a5810105bc4a75703a06740d756d8e8landley	struct expr *tmp = NULL;
8455257cf54a5810105bc4a75703a06740d756d8e8landley	expr_extract_eq(E_OR, &tmp, ep1, ep2);
8465257cf54a5810105bc4a75703a06740d756d8e8landley	if (tmp) {
8475257cf54a5810105bc4a75703a06740d756d8e8landley		*ep1 = expr_eliminate_yn(*ep1);
8485257cf54a5810105bc4a75703a06740d756d8e8landley		*ep2 = expr_eliminate_yn(*ep2);
8495257cf54a5810105bc4a75703a06740d756d8e8landley	}
8505257cf54a5810105bc4a75703a06740d756d8e8landley	return tmp;
8515257cf54a5810105bc4a75703a06740d756d8e8landley}
8525257cf54a5810105bc4a75703a06740d756d8e8landley
8535257cf54a5810105bc4a75703a06740d756d8e8landleyvoid expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)
8545257cf54a5810105bc4a75703a06740d756d8e8landley{
8555257cf54a5810105bc4a75703a06740d756d8e8landley#define e1 (*ep1)
8565257cf54a5810105bc4a75703a06740d756d8e8landley#define e2 (*ep2)
8575257cf54a5810105bc4a75703a06740d756d8e8landley	if (e1->type == type) {
8585257cf54a5810105bc4a75703a06740d756d8e8landley		expr_extract_eq(type, ep, &e1->left.expr, &e2);
8595257cf54a5810105bc4a75703a06740d756d8e8landley		expr_extract_eq(type, ep, &e1->right.expr, &e2);
8605257cf54a5810105bc4a75703a06740d756d8e8landley		return;
8615257cf54a5810105bc4a75703a06740d756d8e8landley	}
8625257cf54a5810105bc4a75703a06740d756d8e8landley	if (e2->type == type) {
8635257cf54a5810105bc4a75703a06740d756d8e8landley		expr_extract_eq(type, ep, ep1, &e2->left.expr);
8645257cf54a5810105bc4a75703a06740d756d8e8landley		expr_extract_eq(type, ep, ep1, &e2->right.expr);
8655257cf54a5810105bc4a75703a06740d756d8e8landley		return;
8665257cf54a5810105bc4a75703a06740d756d8e8landley	}
8675257cf54a5810105bc4a75703a06740d756d8e8landley	if (expr_eq(e1, e2)) {
8685257cf54a5810105bc4a75703a06740d756d8e8landley		*ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;
8695257cf54a5810105bc4a75703a06740d756d8e8landley		expr_free(e2);
8705257cf54a5810105bc4a75703a06740d756d8e8landley		if (type == E_AND) {
8715257cf54a5810105bc4a75703a06740d756d8e8landley			e1 = expr_alloc_symbol(&symbol_yes);
8725257cf54a5810105bc4a75703a06740d756d8e8landley			e2 = expr_alloc_symbol(&symbol_yes);
8735257cf54a5810105bc4a75703a06740d756d8e8landley		} else if (type == E_OR) {
8745257cf54a5810105bc4a75703a06740d756d8e8landley			e1 = expr_alloc_symbol(&symbol_no);
8755257cf54a5810105bc4a75703a06740d756d8e8landley			e2 = expr_alloc_symbol(&symbol_no);
8765257cf54a5810105bc4a75703a06740d756d8e8landley		}
8775257cf54a5810105bc4a75703a06740d756d8e8landley	}
8785257cf54a5810105bc4a75703a06740d756d8e8landley#undef e1
8795257cf54a5810105bc4a75703a06740d756d8e8landley#undef e2
8805257cf54a5810105bc4a75703a06740d756d8e8landley}
8815257cf54a5810105bc4a75703a06740d756d8e8landley
8825257cf54a5810105bc4a75703a06740d756d8e8landleystruct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
8835257cf54a5810105bc4a75703a06740d756d8e8landley{
8845257cf54a5810105bc4a75703a06740d756d8e8landley	struct expr *e1, *e2;
8855257cf54a5810105bc4a75703a06740d756d8e8landley
8865257cf54a5810105bc4a75703a06740d756d8e8landley	if (!e) {
8875257cf54a5810105bc4a75703a06740d756d8e8landley		e = expr_alloc_symbol(sym);
8885257cf54a5810105bc4a75703a06740d756d8e8landley		if (type == E_UNEQUAL)
8895257cf54a5810105bc4a75703a06740d756d8e8landley			e = expr_alloc_one(E_NOT, e);
8905257cf54a5810105bc4a75703a06740d756d8e8landley		return e;
8915257cf54a5810105bc4a75703a06740d756d8e8landley	}
8925257cf54a5810105bc4a75703a06740d756d8e8landley	switch (e->type) {
8935257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
8945257cf54a5810105bc4a75703a06740d756d8e8landley		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
8955257cf54a5810105bc4a75703a06740d756d8e8landley		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
8965257cf54a5810105bc4a75703a06740d756d8e8landley		if (sym == &symbol_yes)
8975257cf54a5810105bc4a75703a06740d756d8e8landley			e = expr_alloc_two(E_AND, e1, e2);
8985257cf54a5810105bc4a75703a06740d756d8e8landley		if (sym == &symbol_no)
8995257cf54a5810105bc4a75703a06740d756d8e8landley			e = expr_alloc_two(E_OR, e1, e2);
9005257cf54a5810105bc4a75703a06740d756d8e8landley		if (type == E_UNEQUAL)
9015257cf54a5810105bc4a75703a06740d756d8e8landley			e = expr_alloc_one(E_NOT, e);
9025257cf54a5810105bc4a75703a06740d756d8e8landley		return e;
9035257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
9045257cf54a5810105bc4a75703a06740d756d8e8landley		e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
9055257cf54a5810105bc4a75703a06740d756d8e8landley		e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
9065257cf54a5810105bc4a75703a06740d756d8e8landley		if (sym == &symbol_yes)
9075257cf54a5810105bc4a75703a06740d756d8e8landley			e = expr_alloc_two(E_OR, e1, e2);
9085257cf54a5810105bc4a75703a06740d756d8e8landley		if (sym == &symbol_no)
9095257cf54a5810105bc4a75703a06740d756d8e8landley			e = expr_alloc_two(E_AND, e1, e2);
9105257cf54a5810105bc4a75703a06740d756d8e8landley		if (type == E_UNEQUAL)
9115257cf54a5810105bc4a75703a06740d756d8e8landley			e = expr_alloc_one(E_NOT, e);
9125257cf54a5810105bc4a75703a06740d756d8e8landley		return e;
9135257cf54a5810105bc4a75703a06740d756d8e8landley	case E_NOT:
9145257cf54a5810105bc4a75703a06740d756d8e8landley		return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
9155257cf54a5810105bc4a75703a06740d756d8e8landley	case E_UNEQUAL:
9165257cf54a5810105bc4a75703a06740d756d8e8landley	case E_EQUAL:
9175257cf54a5810105bc4a75703a06740d756d8e8landley		if (type == E_EQUAL) {
9185257cf54a5810105bc4a75703a06740d756d8e8landley			if (sym == &symbol_yes)
9195257cf54a5810105bc4a75703a06740d756d8e8landley				return expr_copy(e);
9205257cf54a5810105bc4a75703a06740d756d8e8landley			if (sym == &symbol_mod)
9215257cf54a5810105bc4a75703a06740d756d8e8landley				return expr_alloc_symbol(&symbol_no);
9225257cf54a5810105bc4a75703a06740d756d8e8landley			if (sym == &symbol_no)
9235257cf54a5810105bc4a75703a06740d756d8e8landley				return expr_alloc_one(E_NOT, expr_copy(e));
9245257cf54a5810105bc4a75703a06740d756d8e8landley		} else {
9255257cf54a5810105bc4a75703a06740d756d8e8landley			if (sym == &symbol_yes)
9265257cf54a5810105bc4a75703a06740d756d8e8landley				return expr_alloc_one(E_NOT, expr_copy(e));
9275257cf54a5810105bc4a75703a06740d756d8e8landley			if (sym == &symbol_mod)
9285257cf54a5810105bc4a75703a06740d756d8e8landley				return expr_alloc_symbol(&symbol_yes);
9295257cf54a5810105bc4a75703a06740d756d8e8landley			if (sym == &symbol_no)
9305257cf54a5810105bc4a75703a06740d756d8e8landley				return expr_copy(e);
9315257cf54a5810105bc4a75703a06740d756d8e8landley		}
9325257cf54a5810105bc4a75703a06740d756d8e8landley		break;
9335257cf54a5810105bc4a75703a06740d756d8e8landley	case E_SYMBOL:
9345257cf54a5810105bc4a75703a06740d756d8e8landley		return expr_alloc_comp(type, e->left.sym, sym);
9355257cf54a5810105bc4a75703a06740d756d8e8landley	case E_CHOICE:
9365257cf54a5810105bc4a75703a06740d756d8e8landley	case E_RANGE:
9375257cf54a5810105bc4a75703a06740d756d8e8landley	case E_NONE:
9385257cf54a5810105bc4a75703a06740d756d8e8landley		/* panic */;
9395257cf54a5810105bc4a75703a06740d756d8e8landley	}
9405257cf54a5810105bc4a75703a06740d756d8e8landley	return NULL;
9415257cf54a5810105bc4a75703a06740d756d8e8landley}
9425257cf54a5810105bc4a75703a06740d756d8e8landley
9435257cf54a5810105bc4a75703a06740d756d8e8landleytristate expr_calc_value(struct expr *e)
9445257cf54a5810105bc4a75703a06740d756d8e8landley{
9455257cf54a5810105bc4a75703a06740d756d8e8landley	tristate val1, val2;
9465257cf54a5810105bc4a75703a06740d756d8e8landley	const char *str1, *str2;
9475257cf54a5810105bc4a75703a06740d756d8e8landley
9485257cf54a5810105bc4a75703a06740d756d8e8landley	if (!e)
9495257cf54a5810105bc4a75703a06740d756d8e8landley		return yes;
9505257cf54a5810105bc4a75703a06740d756d8e8landley
9515257cf54a5810105bc4a75703a06740d756d8e8landley	switch (e->type) {
9525257cf54a5810105bc4a75703a06740d756d8e8landley	case E_SYMBOL:
9535257cf54a5810105bc4a75703a06740d756d8e8landley		sym_calc_value(e->left.sym);
9545257cf54a5810105bc4a75703a06740d756d8e8landley		return e->left.sym->curr.tri;
9555257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
9565257cf54a5810105bc4a75703a06740d756d8e8landley		val1 = expr_calc_value(e->left.expr);
9575257cf54a5810105bc4a75703a06740d756d8e8landley		val2 = expr_calc_value(e->right.expr);
9585257cf54a5810105bc4a75703a06740d756d8e8landley		return E_AND(val1, val2);
9595257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
9605257cf54a5810105bc4a75703a06740d756d8e8landley		val1 = expr_calc_value(e->left.expr);
9615257cf54a5810105bc4a75703a06740d756d8e8landley		val2 = expr_calc_value(e->right.expr);
9625257cf54a5810105bc4a75703a06740d756d8e8landley		return E_OR(val1, val2);
9635257cf54a5810105bc4a75703a06740d756d8e8landley	case E_NOT:
9645257cf54a5810105bc4a75703a06740d756d8e8landley		val1 = expr_calc_value(e->left.expr);
9655257cf54a5810105bc4a75703a06740d756d8e8landley		return E_NOT(val1);
9665257cf54a5810105bc4a75703a06740d756d8e8landley	case E_EQUAL:
9675257cf54a5810105bc4a75703a06740d756d8e8landley		sym_calc_value(e->left.sym);
9685257cf54a5810105bc4a75703a06740d756d8e8landley		sym_calc_value(e->right.sym);
9695257cf54a5810105bc4a75703a06740d756d8e8landley		str1 = sym_get_string_value(e->left.sym);
9705257cf54a5810105bc4a75703a06740d756d8e8landley		str2 = sym_get_string_value(e->right.sym);
9715257cf54a5810105bc4a75703a06740d756d8e8landley		return !strcmp(str1, str2) ? yes : no;
9725257cf54a5810105bc4a75703a06740d756d8e8landley	case E_UNEQUAL:
9735257cf54a5810105bc4a75703a06740d756d8e8landley		sym_calc_value(e->left.sym);
9745257cf54a5810105bc4a75703a06740d756d8e8landley		sym_calc_value(e->right.sym);
9755257cf54a5810105bc4a75703a06740d756d8e8landley		str1 = sym_get_string_value(e->left.sym);
9765257cf54a5810105bc4a75703a06740d756d8e8landley		str2 = sym_get_string_value(e->right.sym);
9775257cf54a5810105bc4a75703a06740d756d8e8landley		return !strcmp(str1, str2) ? no : yes;
9785257cf54a5810105bc4a75703a06740d756d8e8landley	default:
9795257cf54a5810105bc4a75703a06740d756d8e8landley		printf("expr_calc_value: %d?\n", e->type);
9805257cf54a5810105bc4a75703a06740d756d8e8landley		return no;
9815257cf54a5810105bc4a75703a06740d756d8e8landley	}
9825257cf54a5810105bc4a75703a06740d756d8e8landley}
9835257cf54a5810105bc4a75703a06740d756d8e8landley
9845257cf54a5810105bc4a75703a06740d756d8e8landleyint expr_compare_type(enum expr_type t1, enum expr_type t2)
9855257cf54a5810105bc4a75703a06740d756d8e8landley{
9865257cf54a5810105bc4a75703a06740d756d8e8landley#if 0
9875257cf54a5810105bc4a75703a06740d756d8e8landley	return 1;
9885257cf54a5810105bc4a75703a06740d756d8e8landley#else
9895257cf54a5810105bc4a75703a06740d756d8e8landley	if (t1 == t2)
9905257cf54a5810105bc4a75703a06740d756d8e8landley		return 0;
9915257cf54a5810105bc4a75703a06740d756d8e8landley	switch (t1) {
9925257cf54a5810105bc4a75703a06740d756d8e8landley	case E_EQUAL:
9935257cf54a5810105bc4a75703a06740d756d8e8landley	case E_UNEQUAL:
9945257cf54a5810105bc4a75703a06740d756d8e8landley		if (t2 == E_NOT)
9955257cf54a5810105bc4a75703a06740d756d8e8landley			return 1;
9965257cf54a5810105bc4a75703a06740d756d8e8landley	case E_NOT:
9975257cf54a5810105bc4a75703a06740d756d8e8landley		if (t2 == E_AND)
9985257cf54a5810105bc4a75703a06740d756d8e8landley			return 1;
9995257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
10005257cf54a5810105bc4a75703a06740d756d8e8landley		if (t2 == E_OR)
10015257cf54a5810105bc4a75703a06740d756d8e8landley			return 1;
10025257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
10035257cf54a5810105bc4a75703a06740d756d8e8landley		if (t2 == E_CHOICE)
10045257cf54a5810105bc4a75703a06740d756d8e8landley			return 1;
10055257cf54a5810105bc4a75703a06740d756d8e8landley	case E_CHOICE:
10065257cf54a5810105bc4a75703a06740d756d8e8landley		if (t2 == 0)
10075257cf54a5810105bc4a75703a06740d756d8e8landley			return 1;
10085257cf54a5810105bc4a75703a06740d756d8e8landley	default:
10095257cf54a5810105bc4a75703a06740d756d8e8landley		return -1;
10105257cf54a5810105bc4a75703a06740d756d8e8landley	}
10115257cf54a5810105bc4a75703a06740d756d8e8landley	printf("[%dgt%d?]", t1, t2);
10125257cf54a5810105bc4a75703a06740d756d8e8landley	return 0;
10135257cf54a5810105bc4a75703a06740d756d8e8landley#endif
10145257cf54a5810105bc4a75703a06740d756d8e8landley}
10155257cf54a5810105bc4a75703a06740d756d8e8landley
10165257cf54a5810105bc4a75703a06740d756d8e8landleyvoid expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
10175257cf54a5810105bc4a75703a06740d756d8e8landley{
10185257cf54a5810105bc4a75703a06740d756d8e8landley	if (!e) {
10195257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, NULL, "y");
10205257cf54a5810105bc4a75703a06740d756d8e8landley		return;
10215257cf54a5810105bc4a75703a06740d756d8e8landley	}
10225257cf54a5810105bc4a75703a06740d756d8e8landley
10235257cf54a5810105bc4a75703a06740d756d8e8landley	if (expr_compare_type(prevtoken, e->type) > 0)
10245257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, NULL, "(");
10255257cf54a5810105bc4a75703a06740d756d8e8landley	switch (e->type) {
10265257cf54a5810105bc4a75703a06740d756d8e8landley	case E_SYMBOL:
10275257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->left.sym->name)
10285257cf54a5810105bc4a75703a06740d756d8e8landley			fn(data, e->left.sym, e->left.sym->name);
10295257cf54a5810105bc4a75703a06740d756d8e8landley		else
10305257cf54a5810105bc4a75703a06740d756d8e8landley			fn(data, NULL, "<choice>");
10315257cf54a5810105bc4a75703a06740d756d8e8landley		break;
10325257cf54a5810105bc4a75703a06740d756d8e8landley	case E_NOT:
10335257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, NULL, "!");
10345257cf54a5810105bc4a75703a06740d756d8e8landley		expr_print(e->left.expr, fn, data, E_NOT);
10355257cf54a5810105bc4a75703a06740d756d8e8landley		break;
10365257cf54a5810105bc4a75703a06740d756d8e8landley	case E_EQUAL:
10375257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, e->left.sym, e->left.sym->name);
10385257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, NULL, "=");
10395257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, e->right.sym, e->right.sym->name);
10405257cf54a5810105bc4a75703a06740d756d8e8landley		break;
10415257cf54a5810105bc4a75703a06740d756d8e8landley	case E_UNEQUAL:
10425257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, e->left.sym, e->left.sym->name);
10435257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, NULL, "!=");
10445257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, e->right.sym, e->right.sym->name);
10455257cf54a5810105bc4a75703a06740d756d8e8landley		break;
10465257cf54a5810105bc4a75703a06740d756d8e8landley	case E_OR:
10475257cf54a5810105bc4a75703a06740d756d8e8landley		expr_print(e->left.expr, fn, data, E_OR);
10485257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, NULL, " || ");
10495257cf54a5810105bc4a75703a06740d756d8e8landley		expr_print(e->right.expr, fn, data, E_OR);
10505257cf54a5810105bc4a75703a06740d756d8e8landley		break;
10515257cf54a5810105bc4a75703a06740d756d8e8landley	case E_AND:
10525257cf54a5810105bc4a75703a06740d756d8e8landley		expr_print(e->left.expr, fn, data, E_AND);
10535257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, NULL, " && ");
10545257cf54a5810105bc4a75703a06740d756d8e8landley		expr_print(e->right.expr, fn, data, E_AND);
10555257cf54a5810105bc4a75703a06740d756d8e8landley		break;
10565257cf54a5810105bc4a75703a06740d756d8e8landley	case E_CHOICE:
10575257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, e->right.sym, e->right.sym->name);
10585257cf54a5810105bc4a75703a06740d756d8e8landley		if (e->left.expr) {
10595257cf54a5810105bc4a75703a06740d756d8e8landley			fn(data, NULL, " ^ ");
10605257cf54a5810105bc4a75703a06740d756d8e8landley			expr_print(e->left.expr, fn, data, E_CHOICE);
10615257cf54a5810105bc4a75703a06740d756d8e8landley		}
10625257cf54a5810105bc4a75703a06740d756d8e8landley		break;
10635257cf54a5810105bc4a75703a06740d756d8e8landley	case E_RANGE:
10645257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, NULL, "[");
10655257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, e->left.sym, e->left.sym->name);
10665257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, NULL, " ");
10675257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, e->right.sym, e->right.sym->name);
10685257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, NULL, "]");
10695257cf54a5810105bc4a75703a06740d756d8e8landley		break;
10705257cf54a5810105bc4a75703a06740d756d8e8landley	default:
10715257cf54a5810105bc4a75703a06740d756d8e8landley	  {
10725257cf54a5810105bc4a75703a06740d756d8e8landley		char buf[32];
10735257cf54a5810105bc4a75703a06740d756d8e8landley		sprintf(buf, "<unknown type %d>", e->type);
10745257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, NULL, buf);
10755257cf54a5810105bc4a75703a06740d756d8e8landley		break;
10765257cf54a5810105bc4a75703a06740d756d8e8landley	  }
10775257cf54a5810105bc4a75703a06740d756d8e8landley	}
10785257cf54a5810105bc4a75703a06740d756d8e8landley	if (expr_compare_type(prevtoken, e->type) > 0)
10795257cf54a5810105bc4a75703a06740d756d8e8landley		fn(data, NULL, ")");
10805257cf54a5810105bc4a75703a06740d756d8e8landley}
10815257cf54a5810105bc4a75703a06740d756d8e8landley
10825257cf54a5810105bc4a75703a06740d756d8e8landleystatic void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
10835257cf54a5810105bc4a75703a06740d756d8e8landley{
10845257cf54a5810105bc4a75703a06740d756d8e8landley	fwrite(str, strlen(str), 1, data);
10855257cf54a5810105bc4a75703a06740d756d8e8landley}
10865257cf54a5810105bc4a75703a06740d756d8e8landley
10875257cf54a5810105bc4a75703a06740d756d8e8landleyvoid expr_fprint(struct expr *e, FILE *out)
10885257cf54a5810105bc4a75703a06740d756d8e8landley{
10895257cf54a5810105bc4a75703a06740d756d8e8landley	expr_print(e, expr_print_file_helper, out, E_NONE);
10905257cf54a5810105bc4a75703a06740d756d8e8landley}
10915257cf54a5810105bc4a75703a06740d756d8e8landley
10925257cf54a5810105bc4a75703a06740d756d8e8landleystatic void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
10935257cf54a5810105bc4a75703a06740d756d8e8landley{
10945257cf54a5810105bc4a75703a06740d756d8e8landley	str_append((struct gstr*)data, str);
10955257cf54a5810105bc4a75703a06740d756d8e8landley}
10965257cf54a5810105bc4a75703a06740d756d8e8landley
10975257cf54a5810105bc4a75703a06740d756d8e8landleyvoid expr_gstr_print(struct expr *e, struct gstr *gs)
10985257cf54a5810105bc4a75703a06740d756d8e8landley{
10995257cf54a5810105bc4a75703a06740d756d8e8landley	expr_print(e, expr_print_gstr_helper, gs, E_NONE);
11005257cf54a5810105bc4a75703a06740d756d8e8landley}
1101