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