^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "lkc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define DEBUG_EXPR 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static struct expr *expr_eliminate_yn(struct expr *e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct expr *expr_alloc_symbol(struct symbol *sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct expr *e = xcalloc(1, sizeof(*e));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) e->type = E_SYMBOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) e->left.sym = sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct expr *e = xcalloc(1, sizeof(*e));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) e->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) e->left.expr = ce;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct expr *e = xcalloc(1, sizeof(*e));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) e->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) e->left.expr = e1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) e->right.expr = e2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct expr *e = xcalloc(1, sizeof(*e));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) e->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) e->left.sym = s1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) e->right.sym = s2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (!e1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return e2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (!e1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return e2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct expr *expr_copy(const struct expr *org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct expr *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (!org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) e = xmalloc(sizeof(*org));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) memcpy(e, org, sizeof(*org));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) switch (org->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) case E_SYMBOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) e->left = org->left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) case E_NOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) e->left.expr = expr_copy(org->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) case E_EQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) case E_GEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) case E_GTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) case E_LEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) case E_LTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) case E_UNEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) e->left.sym = org->left.sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) e->right.sym = org->right.sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) case E_LIST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) e->left.expr = expr_copy(org->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) e->right.expr = expr_copy(org->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) fprintf(stderr, "can't copy type %d\n", e->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) free(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) e = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) void expr_free(struct expr *e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (!e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) switch (e->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) case E_SYMBOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) case E_NOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) expr_free(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) case E_EQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) case E_GEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) case E_GTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) case E_LEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) case E_LTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) case E_UNEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) expr_free(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) expr_free(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) fprintf(stderr, "how to free type %d?\n", e->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) free(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static int trans_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define e1 (*ep1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define e2 (*ep2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * expr_eliminate_eq() helper.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * against all other leaves. Two equal leaves are both replaced with either 'y'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * or 'n' as appropriate for 'type', to be eliminated later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* Recurse down to leaves */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (e1->type == type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) __expr_eliminate_eq(type, &e1->left.expr, &e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) __expr_eliminate_eq(type, &e1->right.expr, &e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (e2->type == type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) __expr_eliminate_eq(type, &e1, &e2->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) __expr_eliminate_eq(type, &e1, &e2->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* e1 and e2 are leaves. Compare them. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) e1->left.sym == e2->left.sym &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (!expr_eq(e1, e2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /* e1 and e2 are equal leaves. Prepare them for elimination. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) trans_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) expr_free(e1); expr_free(e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) e1 = expr_alloc_symbol(&symbol_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) e2 = expr_alloc_symbol(&symbol_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) e1 = expr_alloc_symbol(&symbol_yes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) e2 = expr_alloc_symbol(&symbol_yes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * Rewrites the expressions 'ep1' and 'ep2' to remove operands common to both.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * Example reductions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * ep1: A && B -> ep1: y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * ep2: A && B && C -> ep2: C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * ep1: A || B -> ep1: n
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * ep2: A || B || C -> ep2: C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * ep1: A && (B && FOO) -> ep1: FOO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * ep2: (BAR && B) && A -> ep2: BAR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * ep1: A && (B || C) -> ep1: y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * ep2: (C || B) && A -> ep2: y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * Comparisons are done between all operands at the same "level" of && or ||.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * For example, in the expression 'e1 && (e2 || e3) && (e4 || e5)', the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * following operands will be compared:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * - 'e1', 'e2 || e3', and 'e4 || e5', against each other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * - e2 against e3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * - e4 against e5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * Parentheses are irrelevant within a single level. 'e1 && (e2 && e3)' and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * '(e1 && e2) && e3' are both a single level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * See __expr_eliminate_eq() as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (!e1 || !e2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) switch (e1->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) __expr_eliminate_eq(e1->type, ep1, ep2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (e1->type != e2->type) switch (e2->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) __expr_eliminate_eq(e2->type, ep1, ep2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) e1 = expr_eliminate_yn(e1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) e2 = expr_eliminate_yn(e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) #undef e1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #undef e2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * Returns true if 'e1' and 'e2' are equal, after minor simplification. Two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * &&/|| expressions are considered equal if every operand in one expression
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * equals some operand in the other (operands do not need to appear in the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * order), recursively.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) int expr_eq(struct expr *e1, struct expr *e2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) int res, old_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * A NULL expr is taken to be yes, but there's also a different way to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * represent yes. expr_is_yes() checks for either representation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (!e1 || !e2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return expr_is_yes(e1) && expr_is_yes(e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (e1->type != e2->type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) switch (e1->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) case E_EQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) case E_GEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) case E_GTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) case E_LEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) case E_LTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) case E_UNEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) case E_SYMBOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return e1->left.sym == e2->left.sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) case E_NOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return expr_eq(e1->left.expr, e2->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) e1 = expr_copy(e1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) e2 = expr_copy(e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) old_count = trans_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) expr_eliminate_eq(&e1, &e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) e1->left.sym == e2->left.sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) expr_free(e1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) expr_free(e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) trans_count = old_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) case E_LIST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) case E_RANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) case E_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /* panic */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (DEBUG_EXPR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) expr_fprint(e1, stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) printf(" = ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) expr_fprint(e2, stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) printf(" ?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * Recursively performs the following simplifications in-place (as well as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * corresponding simplifications with swapped operands):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * expr && n -> n
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * expr && y -> expr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * expr || n -> expr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * expr || y -> y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * Returns the optimized expression.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static struct expr *expr_eliminate_yn(struct expr *e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct expr *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (e) switch (e->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) e->left.expr = expr_eliminate_yn(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) e->right.expr = expr_eliminate_yn(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (e->left.expr->type == E_SYMBOL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (e->left.expr->left.sym == &symbol_no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) expr_free(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) expr_free(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) e->type = E_SYMBOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) e->left.sym = &symbol_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) e->right.expr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) } else if (e->left.expr->left.sym == &symbol_yes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) free(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) tmp = e->right.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) *e = *(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) free(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (e->right.expr->type == E_SYMBOL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (e->right.expr->left.sym == &symbol_no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) expr_free(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) expr_free(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) e->type = E_SYMBOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) e->left.sym = &symbol_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) e->right.expr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) } else if (e->right.expr->left.sym == &symbol_yes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) free(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) tmp = e->left.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) *e = *(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) free(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) e->left.expr = expr_eliminate_yn(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) e->right.expr = expr_eliminate_yn(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (e->left.expr->type == E_SYMBOL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (e->left.expr->left.sym == &symbol_no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) free(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) tmp = e->right.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) *e = *(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) free(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) } else if (e->left.expr->left.sym == &symbol_yes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) expr_free(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) expr_free(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) e->type = E_SYMBOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) e->left.sym = &symbol_yes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) e->right.expr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (e->right.expr->type == E_SYMBOL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (e->right.expr->left.sym == &symbol_no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) free(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) tmp = e->left.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) *e = *(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) free(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) } else if (e->right.expr->left.sym == &symbol_yes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) expr_free(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) expr_free(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) e->type = E_SYMBOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) e->left.sym = &symbol_yes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) e->right.expr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * bool FOO!=n => FOO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct expr *expr_trans_bool(struct expr *e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (!e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) switch (e->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) case E_NOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) e->left.expr = expr_trans_bool(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) e->right.expr = expr_trans_bool(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) case E_UNEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) // FOO!=n -> FOO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (e->left.sym->type == S_TRISTATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (e->right.sym == &symbol_no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) e->type = E_SYMBOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) e->right.sym = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * e1 || e2 -> ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) struct expr *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) struct symbol *sym1, *sym2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (expr_eq(e1, e2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return expr_copy(e1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (e1->type == E_NOT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) tmp = e1->left.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) sym1 = tmp->left.sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) sym1 = e1->left.sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (e2->type == E_NOT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (e2->left.expr->type != E_SYMBOL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) sym2 = e2->left.expr->left.sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) sym2 = e2->left.sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (sym1 != sym2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (sym1->type == S_TRISTATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) // (a='y') || (a='m') -> (a!='n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) // (a='y') || (a='n') -> (a!='m')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) // (a='m') || (a='n') -> (a!='y')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (sym1->type == S_BOOLEAN && sym1 == sym2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return expr_alloc_symbol(&symbol_yes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (DEBUG_EXPR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) printf("optimize (");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) expr_fprint(e1, stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) printf(") || (");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) expr_fprint(e2, stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) printf(")?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct expr *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct symbol *sym1, *sym2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (expr_eq(e1, e2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return expr_copy(e1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (e1->type == E_NOT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) tmp = e1->left.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) sym1 = tmp->left.sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) sym1 = e1->left.sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (e2->type == E_NOT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (e2->left.expr->type != E_SYMBOL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) sym2 = e2->left.expr->left.sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) sym2 = e2->left.sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (sym1 != sym2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) // (a) && (a='y') -> (a='y')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) // (a) && (a!='n') -> (a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return expr_alloc_symbol(sym1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) // (a) && (a!='m') -> (a='y')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (sym1->type == S_TRISTATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) sym2 = e1->right.sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) : expr_alloc_symbol(&symbol_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) sym2 = e2->right.sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) : expr_alloc_symbol(&symbol_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) // (a!='y') && (a!='n') -> (a='m')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) // (a!='y') && (a!='m') -> (a='n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) // (a!='m') && (a!='n') -> (a='m')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (DEBUG_EXPR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) printf("optimize (");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) expr_fprint(e1, stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) printf(") && (");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) expr_fprint(e2, stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) printf(")?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) * expr_eliminate_dups() helper.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) * against all other leaves to look for simplifications.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) #define e1 (*ep1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) #define e2 (*ep2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct expr *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) /* Recurse down to leaves */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (e1->type == type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) expr_eliminate_dups1(type, &e1->left.expr, &e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) expr_eliminate_dups1(type, &e1->right.expr, &e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (e2->type == type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) expr_eliminate_dups1(type, &e1, &e2->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) expr_eliminate_dups1(type, &e1, &e2->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /* e1 and e2 are leaves. Compare and process them. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (e1 == e2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) switch (e1->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) case E_OR: case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) expr_eliminate_dups1(e1->type, &e1, &e1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) tmp = expr_join_or(e1, e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) expr_free(e1); expr_free(e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) e1 = expr_alloc_symbol(&symbol_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) e2 = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) trans_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) tmp = expr_join_and(e1, e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) expr_free(e1); expr_free(e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) e1 = expr_alloc_symbol(&symbol_yes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) e2 = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) trans_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) #undef e1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) #undef e2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) * Rewrites 'e' in-place to remove ("join") duplicate and other redundant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) * operands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * Example simplifications:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) * A || B || A -> A || B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * A && B && A=y -> A=y && B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) * Returns the deduplicated expression.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) struct expr *expr_eliminate_dups(struct expr *e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) int oldcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (!e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) oldcount = trans_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) trans_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) switch (e->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) case E_OR: case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) expr_eliminate_dups1(e->type, &e, &e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (!trans_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) /* No simplifications done in this pass. We're done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) e = expr_eliminate_yn(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) trans_count = oldcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * Performs various simplifications involving logical operators and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * comparisons.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * Allocates and returns a new expression.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct expr *expr_transform(struct expr *e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) struct expr *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (!e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) switch (e->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) case E_EQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) case E_GEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) case E_GTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) case E_LEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) case E_LTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) case E_UNEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) case E_SYMBOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) case E_LIST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) e->left.expr = expr_transform(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) e->right.expr = expr_transform(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) switch (e->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) case E_EQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (e->left.sym->type != S_BOOLEAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (e->right.sym == &symbol_no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) e->type = E_NOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) e->left.expr = expr_alloc_symbol(e->left.sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) e->right.sym = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (e->right.sym == &symbol_mod) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) e->type = E_SYMBOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) e->left.sym = &symbol_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) e->right.sym = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (e->right.sym == &symbol_yes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) e->type = E_SYMBOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) e->right.sym = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) case E_UNEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (e->left.sym->type != S_BOOLEAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (e->right.sym == &symbol_no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) e->type = E_SYMBOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) e->right.sym = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (e->right.sym == &symbol_mod) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) e->type = E_SYMBOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) e->left.sym = &symbol_yes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) e->right.sym = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (e->right.sym == &symbol_yes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) e->type = E_NOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) e->left.expr = expr_alloc_symbol(e->left.sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) e->right.sym = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) case E_NOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) switch (e->left.expr->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) case E_NOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) // !!a -> a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) tmp = e->left.expr->left.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) free(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) free(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) e = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) e = expr_transform(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) case E_EQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) case E_UNEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) // !a='x' -> a!='x'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) tmp = e->left.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) free(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) e = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) case E_LEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) case E_GEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) // !a<='x' -> a>'x'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) tmp = e->left.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) free(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) e = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) e->type = e->type == E_LEQ ? E_GTH : E_LTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) case E_LTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) case E_GTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) // !a<'x' -> a>='x'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) tmp = e->left.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) free(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) e = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) e->type = e->type == E_LTH ? E_GEQ : E_LEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) // !(a || b) -> !a && !b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) tmp = e->left.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) e->type = E_AND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) tmp->type = E_NOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) tmp->right.expr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) e = expr_transform(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) // !(a && b) -> !a || !b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) tmp = e->left.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) e->type = E_OR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) tmp->type = E_NOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) tmp->right.expr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) e = expr_transform(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) case E_SYMBOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (e->left.expr->left.sym == &symbol_yes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) // !'y' -> 'n'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) tmp = e->left.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) free(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) e = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) e->type = E_SYMBOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) e->left.sym = &symbol_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (e->left.expr->left.sym == &symbol_mod) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) // !'m' -> 'm'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) tmp = e->left.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) free(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) e = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) e->type = E_SYMBOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) e->left.sym = &symbol_mod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (e->left.expr->left.sym == &symbol_no) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) // !'n' -> 'y'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) tmp = e->left.expr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) free(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) e = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) e->type = E_SYMBOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) e->left.sym = &symbol_yes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) int expr_contains_symbol(struct expr *dep, struct symbol *sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (!dep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) switch (dep->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return expr_contains_symbol(dep->left.expr, sym) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) expr_contains_symbol(dep->right.expr, sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) case E_SYMBOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return dep->left.sym == sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) case E_EQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) case E_GEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) case E_GTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) case E_LEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) case E_LTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) case E_UNEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return dep->left.sym == sym ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) dep->right.sym == sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) case E_NOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) return expr_contains_symbol(dep->left.expr, sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (!dep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) switch (dep->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return expr_depends_symbol(dep->left.expr, sym) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) expr_depends_symbol(dep->right.expr, sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) case E_SYMBOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return dep->left.sym == sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) case E_EQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (dep->left.sym == sym) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) case E_UNEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) if (dep->left.sym == sym) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (dep->right.sym == &symbol_no)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) * Inserts explicit comparisons of type 'type' to symbol 'sym' into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * expression 'e'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) * Examples transformations for type == E_UNEQUAL, sym == &symbol_no:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * A -> A!=n
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) * !A -> A=n
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) * A && B -> !(A=n || B=n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) * A || B -> !(A=n && B=n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) * A && (B || C) -> !(A=n || (B=n && C=n))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) * Allocates and returns a new expression.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) struct expr *e1, *e2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (!e) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) e = expr_alloc_symbol(sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (type == E_UNEQUAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) e = expr_alloc_one(E_NOT, e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) switch (e->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (sym == &symbol_yes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) e = expr_alloc_two(E_AND, e1, e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (sym == &symbol_no)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) e = expr_alloc_two(E_OR, e1, e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (type == E_UNEQUAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) e = expr_alloc_one(E_NOT, e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if (sym == &symbol_yes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) e = expr_alloc_two(E_OR, e1, e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (sym == &symbol_no)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) e = expr_alloc_two(E_AND, e1, e2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (type == E_UNEQUAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) e = expr_alloc_one(E_NOT, e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) case E_NOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) case E_UNEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) case E_LTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) case E_LEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) case E_GTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) case E_GEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) case E_EQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (type == E_EQUAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) if (sym == &symbol_yes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) return expr_copy(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (sym == &symbol_mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) return expr_alloc_symbol(&symbol_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (sym == &symbol_no)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return expr_alloc_one(E_NOT, expr_copy(e));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (sym == &symbol_yes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) return expr_alloc_one(E_NOT, expr_copy(e));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (sym == &symbol_mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) return expr_alloc_symbol(&symbol_yes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (sym == &symbol_no)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) return expr_copy(e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) case E_SYMBOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return expr_alloc_comp(type, e->left.sym, sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) case E_LIST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) case E_RANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) case E_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) /* panic */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) enum string_value_kind {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) k_string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) k_signed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) k_unsigned,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) union string_value {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) unsigned long long u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) signed long long s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) static enum string_value_kind expr_parse_string(const char *str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) enum symbol_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) union string_value *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) char *tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) enum string_value_kind kind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) case S_BOOLEAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) case S_TRISTATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) val->s = !strcmp(str, "n") ? 0 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) !strcmp(str, "m") ? 1 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) !strcmp(str, "y") ? 2 : -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) return k_signed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) case S_INT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) val->s = strtoll(str, &tail, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) kind = k_signed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) case S_HEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) val->u = strtoull(str, &tail, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) kind = k_unsigned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) val->s = strtoll(str, &tail, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) kind = k_signed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) return !errno && !*tail && tail > str && isxdigit(tail[-1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) ? kind : k_string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) tristate expr_calc_value(struct expr *e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) tristate val1, val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) const char *str1, *str2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) enum string_value_kind k1 = k_string, k2 = k_string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) union string_value lval = {}, rval = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (!e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return yes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) switch (e->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) case E_SYMBOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) sym_calc_value(e->left.sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return e->left.sym->curr.tri;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) val1 = expr_calc_value(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) val2 = expr_calc_value(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) return EXPR_AND(val1, val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) val1 = expr_calc_value(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) val2 = expr_calc_value(e->right.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return EXPR_OR(val1, val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) case E_NOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) val1 = expr_calc_value(e->left.expr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return EXPR_NOT(val1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) case E_EQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) case E_GEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) case E_GTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) case E_LEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) case E_LTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) case E_UNEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) printf("expr_calc_value: %d?\n", e->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) return no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) sym_calc_value(e->left.sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) sym_calc_value(e->right.sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) str1 = sym_get_string_value(e->left.sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) str2 = sym_get_string_value(e->right.sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) if (e->left.sym->type != S_STRING || e->right.sym->type != S_STRING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) k1 = expr_parse_string(str1, e->left.sym->type, &lval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) k2 = expr_parse_string(str2, e->right.sym->type, &rval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (k1 == k_string || k2 == k_string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) res = strcmp(str1, str2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) else if (k1 == k_unsigned || k2 == k_unsigned)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) res = (lval.u > rval.u) - (lval.u < rval.u);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) else /* if (k1 == k_signed && k2 == k_signed) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) res = (lval.s > rval.s) - (lval.s < rval.s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) switch(e->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) case E_EQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) return res ? no : yes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) case E_GEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) return res >= 0 ? yes : no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) case E_GTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) return res > 0 ? yes : no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) case E_LEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) return res <= 0 ? yes : no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) case E_LTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return res < 0 ? yes : no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) case E_UNEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) return res ? yes : no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) printf("expr_calc_value: relation %d?\n", e->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) return no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) static int expr_compare_type(enum expr_type t1, enum expr_type t2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) if (t1 == t2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) switch (t1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) case E_LEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) case E_LTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) case E_GEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) case E_GTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (t2 == E_EQUAL || t2 == E_UNEQUAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) case E_EQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) case E_UNEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) if (t2 == E_NOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) case E_NOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (t2 == E_AND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) if (t2 == E_OR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (t2 == E_LIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) case E_LIST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (t2 == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) printf("[%dgt%d?]", t1, t2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) void expr_print(struct expr *e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) void (*fn)(void *, struct symbol *, const char *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) void *data, int prevtoken)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (!e) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) fn(data, NULL, "y");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (expr_compare_type(prevtoken, e->type) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) fn(data, NULL, "(");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) switch (e->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) case E_SYMBOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (e->left.sym->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) fn(data, e->left.sym, e->left.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) fn(data, NULL, "<choice>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) case E_NOT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) fn(data, NULL, "!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) expr_print(e->left.expr, fn, data, E_NOT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) case E_EQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (e->left.sym->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) fn(data, e->left.sym, e->left.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) fn(data, NULL, "<choice>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) fn(data, NULL, "=");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) fn(data, e->right.sym, e->right.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) case E_LEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) case E_LTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) if (e->left.sym->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) fn(data, e->left.sym, e->left.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) fn(data, NULL, "<choice>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) fn(data, NULL, e->type == E_LEQ ? "<=" : "<");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) fn(data, e->right.sym, e->right.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) case E_GEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) case E_GTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) if (e->left.sym->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) fn(data, e->left.sym, e->left.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) fn(data, NULL, "<choice>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) fn(data, NULL, e->type == E_GEQ ? ">=" : ">");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) fn(data, e->right.sym, e->right.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) case E_UNEQUAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) if (e->left.sym->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) fn(data, e->left.sym, e->left.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) fn(data, NULL, "<choice>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) fn(data, NULL, "!=");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) fn(data, e->right.sym, e->right.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) case E_OR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) expr_print(e->left.expr, fn, data, E_OR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) fn(data, NULL, " || ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) expr_print(e->right.expr, fn, data, E_OR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) case E_AND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) expr_print(e->left.expr, fn, data, E_AND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) fn(data, NULL, " && ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) expr_print(e->right.expr, fn, data, E_AND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) case E_LIST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) fn(data, e->right.sym, e->right.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (e->left.expr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) fn(data, NULL, " ^ ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) expr_print(e->left.expr, fn, data, E_LIST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) case E_RANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) fn(data, NULL, "[");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) fn(data, e->left.sym, e->left.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) fn(data, NULL, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) fn(data, e->right.sym, e->right.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) fn(data, NULL, "]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) char buf[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) sprintf(buf, "<unknown type %d>", e->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) fn(data, NULL, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (expr_compare_type(prevtoken, e->type) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) fn(data, NULL, ")");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) xfwrite(str, strlen(str), 1, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) void expr_fprint(struct expr *e, FILE *out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) expr_print(e, expr_print_file_helper, out, E_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) struct gstr *gs = (struct gstr*)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) const char *sym_str = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) if (sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) sym_str = sym_get_string_value(sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if (gs->max_width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) unsigned extra_length = strlen(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) const char *last_cr = strrchr(gs->s, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) unsigned last_line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) if (sym_str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) extra_length += 4 + strlen(sym_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) if (!last_cr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) last_cr = gs->s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) last_line_length = strlen(gs->s) - (last_cr - gs->s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) if ((last_line_length + extra_length) > gs->max_width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) str_append(gs, "\\\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) str_append(gs, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if (sym && sym->type != S_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) str_printf(gs, " [=%s]", sym_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) void expr_gstr_print(struct expr *e, struct gstr *gs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) expr_print(e, expr_print_gstr_helper, gs, E_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) * Transform the top level "||" tokens into newlines and prepend each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) * line with a minus. This makes expressions much easier to read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) * Suitable for reverse dependency expressions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) static void expr_print_revdep(struct expr *e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) void (*fn)(void *, struct symbol *, const char *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) void *data, tristate pr_type, const char **title)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (e->type == E_OR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) expr_print_revdep(e->left.expr, fn, data, pr_type, title);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) expr_print_revdep(e->right.expr, fn, data, pr_type, title);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) } else if (expr_calc_value(e) == pr_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (*title) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) fn(data, NULL, *title);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) *title = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) fn(data, NULL, " - ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) expr_print(e, fn, data, E_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) fn(data, NULL, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) tristate pr_type, const char *title)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) expr_print_revdep(e, expr_print_gstr_helper, gs, pr_type, &title);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) }