| 742 | /* ── Expression tree helpers ────────────────────────────────────── */ |
| 743 | |
| 744 | static void expr_free(cbm_expr_t *e) { |
| 745 | enum { EXPR_FREE_STACK = 128 }; |
| 746 | cbm_expr_t *stack[EXPR_FREE_STACK]; |
| 747 | int top = 0; |
| 748 | if (e) { |
| 749 | stack[top++] = e; |
| 750 | } |
| 751 | while (top > 0) { |
| 752 | cbm_expr_t *cur = stack[--top]; |
| 753 | if (cur->type == EXPR_CONDITION) { |
| 754 | safe_str_free(&cur->cond.variable); |
| 755 | safe_str_free(&cur->cond.property); |
| 756 | safe_str_free(&cur->cond.op); |
| 757 | safe_str_free(&cur->cond.value); |
| 758 | for (int i = 0; i < cur->cond.in_value_count; i++) { |
| 759 | safe_str_free(&cur->cond.in_values[i]); |
| 760 | } |
| 761 | free(cur->cond.in_values); |
| 762 | } |
| 763 | if (cur->right) { |
| 764 | if (top < EXPR_FREE_STACK) { |
| 765 | stack[top++] = cur->right; |
| 766 | } else { |
| 767 | expr_free(cur->right); /* recurse when stack overflows */ |
| 768 | } |
| 769 | } |
| 770 | if (cur->left) { |
| 771 | if (top < EXPR_FREE_STACK) { |
| 772 | stack[top++] = cur->left; |
| 773 | } else { |
| 774 | expr_free(cur->left); /* recurse when stack overflows */ |
| 775 | } |
| 776 | } |
| 777 | free(cur); |
| 778 | } |
| 779 | } |
| 780 | |
| 781 | static cbm_expr_t *expr_leaf(cbm_condition_t c) { |
| 782 | cbm_expr_t *e = calloc(CBM_ALLOC_ONE, sizeof(cbm_expr_t)); |
no test coverage detected