1 // SPDX-License-Identifier: GPL-2.0
16 static struct expr *expr_eliminate_yn(struct expr *e);
18 struct expr *expr_alloc_symbol(struct symbol *sym)
20 struct expr *e = xcalloc(1, sizeof(*e));
26 struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
28 struct expr *e = xcalloc(1, sizeof(*e));
34 struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
36 struct expr *e = xcalloc(1, sizeof(*e));
43 struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
45 struct expr *e = xcalloc(1, sizeof(*e));
52 struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
56 return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
59 struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
63 return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
66 struct expr *expr_copy(const struct expr *org)
73 e = xmalloc(sizeof(*org));
74 memcpy(e, org, sizeof(*org));
80 e->left.expr = expr_copy(org->left.expr);
88 e->left.sym = org->left.sym;
89 e->right.sym = org->right.sym;
93 e->left.expr = expr_copy(org->left.expr);
94 e->right.expr = expr_copy(org->right.expr);
97 fprintf(stderr, "can't copy type %d\n", e->type);
106 void expr_free(struct expr *e)
115 expr_free(e->left.expr);
126 expr_free(e->left.expr);
127 expr_free(e->right.expr);
130 fprintf(stderr, "how to free type %d?\n", e->type);
136 static int trans_count;
139 * expr_eliminate_eq() helper.
141 * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
142 * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
143 * against all other leaves. Two equal leaves are both replaced with either 'y'
144 * or 'n' as appropriate for 'type', to be eliminated later.
146 static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
148 /* Recurse down to leaves */
150 if ((*ep1)->type == type) {
151 __expr_eliminate_eq(type, &(*ep1)->left.expr, ep2);
152 __expr_eliminate_eq(type, &(*ep1)->right.expr, ep2);
155 if ((*ep2)->type == type) {
156 __expr_eliminate_eq(type, ep1, &(*ep2)->left.expr);
157 __expr_eliminate_eq(type, ep1, &(*ep2)->right.expr);
161 /* *ep1 and *ep2 are leaves. Compare them. */
163 if ((*ep1)->type == E_SYMBOL && (*ep2)->type == E_SYMBOL &&
164 (*ep1)->left.sym == (*ep2)->left.sym &&
165 ((*ep1)->left.sym == &symbol_yes || (*ep1)->left.sym == &symbol_no))
167 if (!expr_eq(*ep1, *ep2))
170 /* *ep1 and *ep2 are equal leaves. Prepare them for elimination. */
173 expr_free(*ep1); expr_free(*ep2);
176 *ep1 = expr_alloc_symbol(&symbol_no);
177 *ep2 = expr_alloc_symbol(&symbol_no);
180 *ep1 = expr_alloc_symbol(&symbol_yes);
181 *ep2 = expr_alloc_symbol(&symbol_yes);
189 * Rewrites the expressions 'ep1' and 'ep2' to remove operands common to both.
190 * Example reductions:
192 * ep1: A && B -> ep1: y
193 * ep2: A && B && C -> ep2: C
195 * ep1: A || B -> ep1: n
196 * ep2: A || B || C -> ep2: C
198 * ep1: A && (B && FOO) -> ep1: FOO
199 * ep2: (BAR && B) && A -> ep2: BAR
201 * ep1: A && (B || C) -> ep1: y
202 * ep2: (C || B) && A -> ep2: y
204 * Comparisons are done between all operands at the same "level" of && or ||.
205 * For example, in the expression 'e1 && (e2 || e3) && (e4 || e5)', the
206 * following operands will be compared:
208 * - 'e1', 'e2 || e3', and 'e4 || e5', against each other
212 * Parentheses are irrelevant within a single level. 'e1 && (e2 && e3)' and
213 * '(e1 && e2) && e3' are both a single level.
215 * See __expr_eliminate_eq() as well.
217 void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
221 switch ((*ep1)->type) {
224 __expr_eliminate_eq((*ep1)->type, ep1, ep2);
228 if ((*ep1)->type != (*ep2)->type) switch ((*ep2)->type) {
231 __expr_eliminate_eq((*ep2)->type, ep1, ep2);
235 *ep1 = expr_eliminate_yn(*ep1);
236 *ep2 = expr_eliminate_yn(*ep2);
240 * Returns true if 'e1' and 'e2' are equal, after minor simplification. Two
241 * &&/|| expressions are considered equal if every operand in one expression
242 * equals some operand in the other (operands do not need to appear in the same
243 * order), recursively.
245 int expr_eq(struct expr *e1, struct expr *e2)
250 * A NULL expr is taken to be yes, but there's also a different way to
251 * represent yes. expr_is_yes() checks for either representation.
254 return expr_is_yes(e1) && expr_is_yes(e2);
256 if (e1->type != e2->type)
265 return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
267 return e1->left.sym == e2->left.sym;
269 return expr_eq(e1->left.expr, e2->left.expr);
274 old_count = trans_count;
275 expr_eliminate_eq(&e1, &e2);
276 res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
277 e1->left.sym == e2->left.sym);
280 trans_count = old_count;
288 expr_fprint(e1, stdout);
290 expr_fprint(e2, stdout);
298 * Recursively performs the following simplifications in-place (as well as the
299 * corresponding simplifications with swapped operands):
306 * Returns the optimized expression.
308 static struct expr *expr_eliminate_yn(struct expr *e)
312 if (e) switch (e->type) {
314 e->left.expr = expr_eliminate_yn(e->left.expr);
315 e->right.expr = expr_eliminate_yn(e->right.expr);
316 if (e->left.expr->type == E_SYMBOL) {
317 if (e->left.expr->left.sym == &symbol_no) {
318 expr_free(e->left.expr);
319 expr_free(e->right.expr);
321 e->left.sym = &symbol_no;
322 e->right.expr = NULL;
324 } else if (e->left.expr->left.sym == &symbol_yes) {
327 *e = *(e->right.expr);
332 if (e->right.expr->type == E_SYMBOL) {
333 if (e->right.expr->left.sym == &symbol_no) {
334 expr_free(e->left.expr);
335 expr_free(e->right.expr);
337 e->left.sym = &symbol_no;
338 e->right.expr = NULL;
340 } else if (e->right.expr->left.sym == &symbol_yes) {
343 *e = *(e->left.expr);
350 e->left.expr = expr_eliminate_yn(e->left.expr);
351 e->right.expr = expr_eliminate_yn(e->right.expr);
352 if (e->left.expr->type == E_SYMBOL) {
353 if (e->left.expr->left.sym == &symbol_no) {
356 *e = *(e->right.expr);
359 } else if (e->left.expr->left.sym == &symbol_yes) {
360 expr_free(e->left.expr);
361 expr_free(e->right.expr);
363 e->left.sym = &symbol_yes;
364 e->right.expr = NULL;
368 if (e->right.expr->type == E_SYMBOL) {
369 if (e->right.expr->left.sym == &symbol_no) {
372 *e = *(e->left.expr);
375 } else if (e->right.expr->left.sym == &symbol_yes) {
376 expr_free(e->left.expr);
377 expr_free(e->right.expr);
379 e->left.sym = &symbol_yes;
380 e->right.expr = NULL;
394 static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
397 struct symbol *sym1, *sym2;
400 return expr_copy(e1);
401 if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
403 if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
405 if (e1->type == E_NOT) {
407 if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
409 sym1 = tmp->left.sym;
412 if (e2->type == E_NOT) {
413 if (e2->left.expr->type != E_SYMBOL)
415 sym2 = e2->left.expr->left.sym;
420 if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
422 if (sym1->type == S_TRISTATE) {
423 if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
424 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
425 (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
426 // (a='y') || (a='m') -> (a!='n')
427 return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
429 if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
430 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
431 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
432 // (a='y') || (a='n') -> (a!='m')
433 return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
435 if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
436 ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
437 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
438 // (a='m') || (a='n') -> (a!='y')
439 return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
442 if (sym1->type == S_BOOLEAN) {
443 if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
444 (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
445 return expr_alloc_symbol(&symbol_yes);
449 printf("optimize (");
450 expr_fprint(e1, stdout);
452 expr_fprint(e2, stdout);
458 static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
461 struct symbol *sym1, *sym2;
464 return expr_copy(e1);
465 if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
467 if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
469 if (e1->type == E_NOT) {
471 if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
473 sym1 = tmp->left.sym;
476 if (e2->type == E_NOT) {
477 if (e2->left.expr->type != E_SYMBOL)
479 sym2 = e2->left.expr->left.sym;
484 if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
487 if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
488 (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
489 // (a) && (a='y') -> (a='y')
490 return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
492 if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
493 (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
494 // (a) && (a!='n') -> (a)
495 return expr_alloc_symbol(sym1);
497 if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
498 (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
499 // (a) && (a!='m') -> (a='y')
500 return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
502 if (sym1->type == S_TRISTATE) {
503 if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
504 // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
505 sym2 = e1->right.sym;
506 if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
507 return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
508 : expr_alloc_symbol(&symbol_no);
510 if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
511 // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
512 sym2 = e2->right.sym;
513 if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
514 return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
515 : expr_alloc_symbol(&symbol_no);
517 if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
518 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
519 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
520 // (a!='y') && (a!='n') -> (a='m')
521 return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
523 if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
524 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
525 (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
526 // (a!='y') && (a!='m') -> (a='n')
527 return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
529 if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
530 ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
531 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
532 // (a!='m') && (a!='n') -> (a='m')
533 return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
535 if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
536 (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
537 (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
538 (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
543 printf("optimize (");
544 expr_fprint(e1, stdout);
546 expr_fprint(e2, stdout);
553 * expr_eliminate_dups() helper.
555 * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
556 * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
557 * against all other leaves to look for simplifications.
559 static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
563 /* Recurse down to leaves */
565 if ((*ep1)->type == type) {
566 expr_eliminate_dups1(type, &(*ep1)->left.expr, ep2);
567 expr_eliminate_dups1(type, &(*ep1)->right.expr, ep2);
570 if ((*ep2)->type == type) {
571 expr_eliminate_dups1(type, ep1, &(*ep2)->left.expr);
572 expr_eliminate_dups1(type, ep1, &(*ep2)->right.expr);
576 /* *ep1 and *ep2 are leaves. Compare and process them. */
581 switch ((*ep1)->type) {
582 case E_OR: case E_AND:
583 expr_eliminate_dups1((*ep1)->type, ep1, ep1);
590 tmp = expr_join_or(*ep1, *ep2);
592 expr_free(*ep1); expr_free(*ep2);
593 *ep1 = expr_alloc_symbol(&symbol_no);
599 tmp = expr_join_and(*ep1, *ep2);
601 expr_free(*ep1); expr_free(*ep2);
602 *ep1 = expr_alloc_symbol(&symbol_yes);
613 * Rewrites 'e' in-place to remove ("join") duplicate and other redundant
616 * Example simplifications:
618 * A || B || A -> A || B
619 * A && B && A=y -> A=y && B
621 * Returns the deduplicated expression.
623 struct expr *expr_eliminate_dups(struct expr *e)
629 oldcount = trans_count;
633 case E_OR: case E_AND:
634 expr_eliminate_dups1(e->type, &e, &e);
638 e = expr_eliminate_yn(e);
639 } while (trans_count); /* repeat until we get no more simplifications */
640 trans_count = oldcount;
645 * Performs various simplifications involving logical operators and
648 * Allocates and returns a new expression.
650 struct expr *expr_transform(struct expr *e)
666 e->left.expr = expr_transform(e->left.expr);
667 e->right.expr = expr_transform(e->right.expr);
672 if (e->left.sym->type != S_BOOLEAN)
674 if (e->right.sym == &symbol_no) {
676 e->left.expr = expr_alloc_symbol(e->left.sym);
680 if (e->right.sym == &symbol_mod) {
681 printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
683 e->left.sym = &symbol_no;
687 if (e->right.sym == &symbol_yes) {
694 if (e->left.sym->type != S_BOOLEAN)
696 if (e->right.sym == &symbol_no) {
701 if (e->right.sym == &symbol_mod) {
702 printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
704 e->left.sym = &symbol_yes;
708 if (e->right.sym == &symbol_yes) {
710 e->left.expr = expr_alloc_symbol(e->left.sym);
716 switch (e->left.expr->type) {
719 tmp = e->left.expr->left.expr;
723 e = expr_transform(e);
731 e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
739 e->type = e->type == E_LEQ ? E_GTH : E_LTH;
747 e->type = e->type == E_LTH ? E_GEQ : E_LEQ;
750 // !(a || b) -> !a && !b
753 e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
755 tmp->right.expr = NULL;
756 e = expr_transform(e);
759 // !(a && b) -> !a || !b
762 e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
764 tmp->right.expr = NULL;
765 e = expr_transform(e);
768 if (e->left.expr->left.sym == &symbol_yes) {
774 e->left.sym = &symbol_no;
777 if (e->left.expr->left.sym == &symbol_mod) {
783 e->left.sym = &symbol_mod;
786 if (e->left.expr->left.sym == &symbol_no) {
792 e->left.sym = &symbol_yes;
806 int expr_contains_symbol(struct expr *dep, struct symbol *sym)
814 return expr_contains_symbol(dep->left.expr, sym) ||
815 expr_contains_symbol(dep->right.expr, sym);
817 return dep->left.sym == sym;
824 return dep->left.sym == sym ||
825 dep->right.sym == sym;
827 return expr_contains_symbol(dep->left.expr, sym);
834 bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
841 return expr_depends_symbol(dep->left.expr, sym) ||
842 expr_depends_symbol(dep->right.expr, sym);
844 return dep->left.sym == sym;
846 if (dep->left.sym == sym) {
847 if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
852 if (dep->left.sym == sym) {
853 if (dep->right.sym == &symbol_no)
864 * Inserts explicit comparisons of type 'type' to symbol 'sym' into the
867 * Examples transformations for type == E_UNEQUAL, sym == &symbol_no:
871 * A && B -> !(A=n || B=n)
872 * A || B -> !(A=n && B=n)
873 * A && (B || C) -> !(A=n || (B=n && C=n))
875 * Allocates and returns a new expression.
877 struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
879 struct expr *e1, *e2;
882 e = expr_alloc_symbol(sym);
883 if (type == E_UNEQUAL)
884 e = expr_alloc_one(E_NOT, e);
889 e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
890 e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
891 if (sym == &symbol_yes)
892 e = expr_alloc_two(E_AND, e1, e2);
893 if (sym == &symbol_no)
894 e = expr_alloc_two(E_OR, e1, e2);
895 if (type == E_UNEQUAL)
896 e = expr_alloc_one(E_NOT, e);
899 e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
900 e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
901 if (sym == &symbol_yes)
902 e = expr_alloc_two(E_OR, e1, e2);
903 if (sym == &symbol_no)
904 e = expr_alloc_two(E_AND, e1, e2);
905 if (type == E_UNEQUAL)
906 e = expr_alloc_one(E_NOT, e);
909 return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
916 if (type == E_EQUAL) {
917 if (sym == &symbol_yes)
919 if (sym == &symbol_mod)
920 return expr_alloc_symbol(&symbol_no);
921 if (sym == &symbol_no)
922 return expr_alloc_one(E_NOT, expr_copy(e));
924 if (sym == &symbol_yes)
925 return expr_alloc_one(E_NOT, expr_copy(e));
926 if (sym == &symbol_mod)
927 return expr_alloc_symbol(&symbol_yes);
928 if (sym == &symbol_no)
933 return expr_alloc_comp(type, e->left.sym, sym);
941 enum string_value_kind {
948 unsigned long long u;
952 static enum string_value_kind expr_parse_string(const char *str,
953 enum symbol_type type,
954 union string_value *val)
957 enum string_value_kind kind;
963 val->s = !strcmp(str, "n") ? 0 :
964 !strcmp(str, "m") ? 1 :
965 !strcmp(str, "y") ? 2 : -1;
968 val->s = strtoll(str, &tail, 10);
972 val->u = strtoull(str, &tail, 16);
976 val->s = strtoll(str, &tail, 0);
980 return !errno && !*tail && tail > str && isxdigit(tail[-1])
984 tristate expr_calc_value(struct expr *e)
987 const char *str1, *str2;
988 enum string_value_kind k1 = k_string, k2 = k_string;
989 union string_value lval = {}, rval = {};
997 sym_calc_value(e->left.sym);
998 return e->left.sym->curr.tri;
1000 val1 = expr_calc_value(e->left.expr);
1001 val2 = expr_calc_value(e->right.expr);
1002 return EXPR_AND(val1, val2);
1004 val1 = expr_calc_value(e->left.expr);
1005 val2 = expr_calc_value(e->right.expr);
1006 return EXPR_OR(val1, val2);
1008 val1 = expr_calc_value(e->left.expr);
1009 return EXPR_NOT(val1);
1018 printf("expr_calc_value: %d?\n", e->type);
1022 sym_calc_value(e->left.sym);
1023 sym_calc_value(e->right.sym);
1024 str1 = sym_get_string_value(e->left.sym);
1025 str2 = sym_get_string_value(e->right.sym);
1027 if (e->left.sym->type != S_STRING || e->right.sym->type != S_STRING) {
1028 k1 = expr_parse_string(str1, e->left.sym->type, &lval);
1029 k2 = expr_parse_string(str2, e->right.sym->type, &rval);
1032 if (k1 == k_string || k2 == k_string)
1033 res = strcmp(str1, str2);
1034 else if (k1 == k_unsigned || k2 == k_unsigned)
1035 res = (lval.u > rval.u) - (lval.u < rval.u);
1036 else /* if (k1 == k_signed && k2 == k_signed) */
1037 res = (lval.s > rval.s) - (lval.s < rval.s);
1041 return res ? no : yes;
1043 return res >= 0 ? yes : no;
1045 return res > 0 ? yes : no;
1047 return res <= 0 ? yes : no;
1049 return res < 0 ? yes : no;
1051 return res ? yes : no;
1053 printf("expr_calc_value: relation %d?\n", e->type);
1058 static int expr_compare_type(enum expr_type t1, enum expr_type t2)
1067 if (t2 == E_EQUAL || t2 == E_UNEQUAL)
1089 void expr_print(const struct expr *e,
1090 void (*fn)(void *, struct symbol *, const char *),
1091 void *data, int prevtoken)
1094 fn(data, NULL, "y");
1098 if (expr_compare_type(prevtoken, e->type) > 0)
1099 fn(data, NULL, "(");
1102 if (e->left.sym->name)
1103 fn(data, e->left.sym, e->left.sym->name);
1105 fn(data, NULL, "<choice>");
1108 fn(data, NULL, "!");
1109 expr_print(e->left.expr, fn, data, E_NOT);
1112 if (e->left.sym->name)
1113 fn(data, e->left.sym, e->left.sym->name);
1115 fn(data, NULL, "<choice>");
1116 fn(data, NULL, "=");
1117 fn(data, e->right.sym, e->right.sym->name);
1121 if (e->left.sym->name)
1122 fn(data, e->left.sym, e->left.sym->name);
1124 fn(data, NULL, "<choice>");
1125 fn(data, NULL, e->type == E_LEQ ? "<=" : "<");
1126 fn(data, e->right.sym, e->right.sym->name);
1130 if (e->left.sym->name)
1131 fn(data, e->left.sym, e->left.sym->name);
1133 fn(data, NULL, "<choice>");
1134 fn(data, NULL, e->type == E_GEQ ? ">=" : ">");
1135 fn(data, e->right.sym, e->right.sym->name);
1138 if (e->left.sym->name)
1139 fn(data, e->left.sym, e->left.sym->name);
1141 fn(data, NULL, "<choice>");
1142 fn(data, NULL, "!=");
1143 fn(data, e->right.sym, e->right.sym->name);
1146 expr_print(e->left.expr, fn, data, E_OR);
1147 fn(data, NULL, " || ");
1148 expr_print(e->right.expr, fn, data, E_OR);
1151 expr_print(e->left.expr, fn, data, E_AND);
1152 fn(data, NULL, " && ");
1153 expr_print(e->right.expr, fn, data, E_AND);
1156 fn(data, NULL, "[");
1157 fn(data, e->left.sym, e->left.sym->name);
1158 fn(data, NULL, " ");
1159 fn(data, e->right.sym, e->right.sym->name);
1160 fn(data, NULL, "]");
1165 sprintf(buf, "<unknown type %d>", e->type);
1166 fn(data, NULL, buf);
1170 if (expr_compare_type(prevtoken, e->type) > 0)
1171 fn(data, NULL, ")");
1174 static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
1176 xfwrite(str, strlen(str), 1, data);
1179 void expr_fprint(struct expr *e, FILE *out)
1181 expr_print(e, expr_print_file_helper, out, E_NONE);
1184 static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
1186 struct gstr *gs = (struct gstr*)data;
1187 const char *sym_str = NULL;
1190 sym_str = sym_get_string_value(sym);
1192 if (gs->max_width) {
1193 unsigned extra_length = strlen(str);
1194 const char *last_cr = strrchr(gs->s, '\n');
1195 unsigned last_line_length;
1198 extra_length += 4 + strlen(sym_str);
1203 last_line_length = strlen(gs->s) - (last_cr - gs->s);
1205 if ((last_line_length + extra_length) > gs->max_width)
1206 str_append(gs, "\\\n");
1209 str_append(gs, str);
1210 if (sym && sym->type != S_UNKNOWN)
1211 str_printf(gs, " [=%s]", sym_str);
1214 void expr_gstr_print(const struct expr *e, struct gstr *gs)
1216 expr_print(e, expr_print_gstr_helper, gs, E_NONE);
1220 * Transform the top level "||" tokens into newlines and prepend each
1221 * line with a minus. This makes expressions much easier to read.
1222 * Suitable for reverse dependency expressions.
1224 static void expr_print_revdep(struct expr *e,
1225 void (*fn)(void *, struct symbol *, const char *),
1226 void *data, tristate pr_type, const char **title)
1228 if (e->type == E_OR) {
1229 expr_print_revdep(e->left.expr, fn, data, pr_type, title);
1230 expr_print_revdep(e->right.expr, fn, data, pr_type, title);
1231 } else if (expr_calc_value(e) == pr_type) {
1233 fn(data, NULL, *title);
1237 fn(data, NULL, " - ");
1238 expr_print(e, fn, data, E_NONE);
1239 fn(data, NULL, "\n");
1243 void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
1244 tristate pr_type, const char *title)
1246 expr_print_revdep(e, expr_print_gstr_helper, gs, pr_type, &title);