tristate expr_calc_value(struct expr *e) { tristate val1, val2; const char *str1, *str2; if (!e) return yes; switch (e->type) { case E_SYMBOL: sym_calc_value(e->left.sym); return e->left.sym->curr.tri; case E_AND: val1 = expr_calc_value(e->left.expr); val2 = expr_calc_value(e->right.expr); return EXPR_AND(val1, val2); case E_OR: val1 = expr_calc_value(e->left.expr); val2 = expr_calc_value(e->right.expr); return EXPR_OR(val1, val2); case E_NOT: val1 = expr_calc_value(e->left.expr); return EXPR_NOT(val1); case E_EQUAL: sym_calc_value(e->left.sym); sym_calc_value(e->right.sym); str1 = sym_get_string_value(e->left.sym); str2 = sym_get_string_value(e->right.sym); return !strcmp(str1, str2) ? yes : no; case E_UNEQUAL: sym_calc_value(e->left.sym); sym_calc_value(e->right.sym); str1 = sym_get_string_value(e->left.sym); str2 = sym_get_string_value(e->right.sym); return !strcmp(str1, str2) ? no : yes; default: printf("expr_calc_value: %d?\n", e->type); return no; } }
tristate expr_calc_value(struct expr *e) { tristate val1, val2; const char *str1, *str2; enum string_value_kind k1 = k_string, k2 = k_string; union string_value lval = {}, rval = {}; int res; if (!e) return yes; switch (e->type) { case E_SYMBOL: sym_calc_value(e->left.sym); return e->left.sym->curr.tri; case E_AND: val1 = expr_calc_value(e->left.expr); val2 = expr_calc_value(e->right.expr); return EXPR_AND(val1, val2); case E_OR: val1 = expr_calc_value(e->left.expr); val2 = expr_calc_value(e->right.expr); return EXPR_OR(val1, val2); case E_NOT: val1 = expr_calc_value(e->left.expr); return EXPR_NOT(val1); case E_EQUAL: case E_GEQ: case E_GTH: case E_LEQ: case E_LTH: case E_UNEQUAL: break; default: printf("expr_calc_value: %d?\n", e->type); return no; } sym_calc_value(e->left.sym); sym_calc_value(e->right.sym); str1 = sym_get_string_value(e->left.sym); str2 = sym_get_string_value(e->right.sym); if (e->left.sym->type != S_STRING || e->right.sym->type != S_STRING) { k1 = expr_parse_string(str1, e->left.sym->type, &lval); k2 = expr_parse_string(str2, e->right.sym->type, &rval); } if (k1 == k_string || k2 == k_string) res = strcmp(str1, str2); else if (k1 == k_invalid || k2 == k_invalid) { if (e->type != E_EQUAL && e->type != E_UNEQUAL) { printf("Cannot compare \"%s\" and \"%s\"\n", str1, str2); return no; } res = strcmp(str1, str2); } else if (k1 == k_unsigned || k2 == k_unsigned) res = (lval.u > rval.u) - (lval.u < rval.u); else /* if (k1 == k_signed && k2 == k_signed) */ res = (lval.s > rval.s) - (lval.s < rval.s); switch(e->type) { case E_EQUAL: return res ? no : yes; case E_GEQ: return res >= 0 ? yes : no; case E_GTH: return res > 0 ? yes : no; case E_LEQ: return res <= 0 ? yes : no; case E_LTH: return res < 0 ? yes : no; case E_UNEQUAL: return res ? yes : no; default: printf("expr_calc_value: relation %d?\n", e->type); return no; } }