* Returns true if 'e1' and 'e2' are equal, after minor simplification. Two * &&/|| expressions are considered equal if every operand in one expression * equals some operand in the other (operands do not need to appear in the same * order), recursively. */
| 250 | * order), recursively. |
| 251 | */ |
| 252 | int expr_eq(struct expr *e1, struct expr *e2) |
| 253 | { |
| 254 | int res, old_count; |
| 255 | |
| 256 | /* |
| 257 | * A NULL expr is taken to be yes, but there's also a different way to |
| 258 | * represent yes. expr_is_yes() checks for either representation. |
| 259 | */ |
| 260 | if (!e1 || !e2) |
| 261 | return expr_is_yes(e1) && expr_is_yes(e2); |
| 262 | |
| 263 | if (e1->type != e2->type) |
| 264 | return 0; |
| 265 | switch (e1->type) { |
| 266 | case E_EQUAL: |
| 267 | case E_GEQ: |
| 268 | case E_GTH: |
| 269 | case E_LEQ: |
| 270 | case E_LTH: |
| 271 | case E_UNEQUAL: |
| 272 | return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; |
| 273 | case E_SYMBOL: |
| 274 | return e1->left.sym == e2->left.sym; |
| 275 | case E_NOT: |
| 276 | return expr_eq(e1->left.expr, e2->left.expr); |
| 277 | case E_AND: |
| 278 | case E_OR: |
| 279 | e1 = expr_copy(e1); |
| 280 | e2 = expr_copy(e2); |
| 281 | old_count = trans_count; |
| 282 | expr_eliminate_eq(&e1, &e2); |
| 283 | res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL && |
| 284 | e1->left.sym == e2->left.sym); |
| 285 | expr_free(e1); |
| 286 | expr_free(e2); |
| 287 | trans_count = old_count; |
| 288 | return res; |
| 289 | case E_LIST: |
| 290 | case E_RANGE: |
| 291 | case E_NONE: |
| 292 | /* panic */; |
| 293 | } |
| 294 | |
| 295 | if (DEBUG_EXPR) { |
| 296 | expr_fprint(e1, stdout); |
| 297 | printf(" = "); |
| 298 | expr_fprint(e2, stdout); |
| 299 | printf(" ?\n"); |
| 300 | } |
| 301 | |
| 302 | return 0; |
| 303 | } |
| 304 | |
| 305 | /* |
| 306 | * Recursively performs the following simplifications in-place (as well as the |
no test coverage detected