1 // SPDX-License-Identifier: GPL-2.0
16 static int expr_eq(struct expr *e1, struct expr *e2);
17 static struct expr *expr_eliminate_yn(struct expr *e);
19 struct expr *expr_alloc_symbol(struct symbol *sym)
21 struct expr *e = xcalloc(1, sizeof(*e));
27 struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
29 struct expr *e = xcalloc(1, sizeof(*e));
35 struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
37 struct expr *e = xcalloc(1, sizeof(*e));
44 struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
46 struct expr *e = xcalloc(1, sizeof(*e));
53 struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
57 return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
60 struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
64 return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
67 struct expr *expr_copy(const struct expr *org)
74 e = xmalloc(sizeof(*org));
75 memcpy(e, org, sizeof(*org));
81 e->left.expr = expr_copy(org->left.expr);
89 e->left.sym = org->left.sym;
90 e->right.sym = org->right.sym;
95 e->left.expr = expr_copy(org->left.expr);
96 e->right.expr = expr_copy(org->right.expr);
99 fprintf(stderr, "can't copy type %d\n", e->type);
108 void expr_free(struct expr *e)
117 expr_free(e->left.expr);
128 expr_free(e->left.expr);
129 expr_free(e->right.expr);
132 fprintf(stderr, "how to free type %d?\n", e->type);
138 static int trans_count;
144 * expr_eliminate_eq() helper.
146 * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
147 * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
148 * against all other leaves. Two equal leaves are both replaced with either 'y'
149 * or 'n' as appropriate for 'type', to be eliminated later.
151 static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
153 /* Recurse down to leaves */
155 if (e1->type == type) {
156 __expr_eliminate_eq(type, &e1->left.expr, &e2);
157 __expr_eliminate_eq(type, &e1->right.expr, &e2);
160 if (e2->type == type) {
161 __expr_eliminate_eq(type, &e1, &e2->left.expr);
162 __expr_eliminate_eq(type, &e1, &e2->right.expr);
166 /* e1 and e2 are leaves. Compare them. */
168 if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
169 e1->left.sym == e2->left.sym &&
170 (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
172 if (!expr_eq(e1, e2))
175 /* e1 and e2 are equal leaves. Prepare them for elimination. */
178 expr_free(e1); expr_free(e2);
181 e1 = expr_alloc_symbol(&symbol_no);
182 e2 = expr_alloc_symbol(&symbol_no);
185 e1 = expr_alloc_symbol(&symbol_yes);
186 e2 = expr_alloc_symbol(&symbol_yes);
194 * Rewrites the expressions 'ep1' and 'ep2' to remove operands common to both.
195 * Example reductions:
197 * ep1: A && B -> ep1: y
198 * ep2: A && B && C -> ep2: C
200 * ep1: A || B -> ep1: n
201 * ep2: A || B || C -> ep2: C
203 * ep1: A && (B && FOO) -> ep1: FOO
204 * ep2: (BAR && B) && A -> ep2: BAR
206 * ep1: A && (B || C) -> ep1: y
207 * ep2: (C || B) && A -> ep2: y
209 * Comparisons are done between all operands at the same "level" of && or ||.
210 * For example, in the expression 'e1 && (e2 || e3) && (e4 || e5)', the
211 * following operands will be compared:
213 * - 'e1', 'e2 || e3', and 'e4 || e5', against each other
217 * Parentheses are irrelevant within a single level. 'e1 && (e2 && e3)' and
218 * '(e1 && e2) && e3' are both a single level.
220 * See __expr_eliminate_eq() as well.
222 void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
229 __expr_eliminate_eq(e1->type, ep1, ep2);
233 if (e1->type != e2->type) switch (e2->type) {
236 __expr_eliminate_eq(e2->type, ep1, ep2);
240 e1 = expr_eliminate_yn(e1);
241 e2 = expr_eliminate_yn(e2);
248 * Returns true if 'e1' and 'e2' are equal, after minor simplification. Two
249 * &&/|| expressions are considered equal if every operand in one expression
250 * equals some operand in the other (operands do not need to appear in the same
251 * order), recursively.
253 static int expr_eq(struct expr *e1, struct expr *e2)
257 if (e1->type != e2->type)
266 return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
268 return e1->left.sym == e2->left.sym;
270 return expr_eq(e1->left.expr, e2->left.expr);
275 old_count = trans_count;
276 expr_eliminate_eq(&e1, &e2);
277 res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
278 e1->left.sym == e2->left.sym);
281 trans_count = old_count;
290 expr_fprint(e1, stdout);
292 expr_fprint(e2, stdout);
300 * Recursively performs the following simplifications in-place (as well as the
301 * corresponding simplifications with swapped operands):
308 * Returns the optimized expression.
310 static struct expr *expr_eliminate_yn(struct expr *e)
314 if (e) switch (e->type) {
316 e->left.expr = expr_eliminate_yn(e->left.expr);
317 e->right.expr = expr_eliminate_yn(e->right.expr);
318 if (e->left.expr->type == E_SYMBOL) {
319 if (e->left.expr->left.sym == &symbol_no) {
320 expr_free(e->left.expr);
321 expr_free(e->right.expr);
323 e->left.sym = &symbol_no;
324 e->right.expr = NULL;
326 } else if (e->left.expr->left.sym == &symbol_yes) {
329 *e = *(e->right.expr);
334 if (e->right.expr->type == E_SYMBOL) {
335 if (e->right.expr->left.sym == &symbol_no) {
336 expr_free(e->left.expr);
337 expr_free(e->right.expr);
339 e->left.sym = &symbol_no;
340 e->right.expr = NULL;
342 } else if (e->right.expr->left.sym == &symbol_yes) {
345 *e = *(e->left.expr);
352 e->left.expr = expr_eliminate_yn(e->left.expr);
353 e->right.expr = expr_eliminate_yn(e->right.expr);
354 if (e->left.expr->type == E_SYMBOL) {
355 if (e->left.expr->left.sym == &symbol_no) {
358 *e = *(e->right.expr);
361 } else if (e->left.expr->left.sym == &symbol_yes) {
362 expr_free(e->left.expr);
363 expr_free(e->right.expr);
365 e->left.sym = &symbol_yes;
366 e->right.expr = NULL;
370 if (e->right.expr->type == E_SYMBOL) {
371 if (e->right.expr->left.sym == &symbol_no) {
374 *e = *(e->left.expr);
377 } else if (e->right.expr->left.sym == &symbol_yes) {
378 expr_free(e->left.expr);
379 expr_free(e->right.expr);
381 e->left.sym = &symbol_yes;
382 e->right.expr = NULL;
396 struct expr *expr_trans_bool(struct expr *e)
404 e->left.expr = expr_trans_bool(e->left.expr);
405 e->right.expr = expr_trans_bool(e->right.expr);
409 if (e->left.sym->type == S_TRISTATE) {
410 if (e->right.sym == &symbol_no) {
425 static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
428 struct symbol *sym1, *sym2;
431 return expr_copy(e1);
432 if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
434 if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
436 if (e1->type == E_NOT) {
438 if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
440 sym1 = tmp->left.sym;
443 if (e2->type == E_NOT) {
444 if (e2->left.expr->type != E_SYMBOL)
446 sym2 = e2->left.expr->left.sym;
451 if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
453 if (sym1->type == S_TRISTATE) {
454 if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
455 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
456 (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
457 // (a='y') || (a='m') -> (a!='n')
458 return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
460 if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
461 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
462 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
463 // (a='y') || (a='n') -> (a!='m')
464 return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
466 if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
467 ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
468 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
469 // (a='m') || (a='n') -> (a!='y')
470 return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
473 if (sym1->type == S_BOOLEAN && sym1 == sym2) {
474 if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
475 (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
476 return expr_alloc_symbol(&symbol_yes);
480 printf("optimize (");
481 expr_fprint(e1, stdout);
483 expr_fprint(e2, stdout);
489 static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
492 struct symbol *sym1, *sym2;
495 return expr_copy(e1);
496 if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
498 if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
500 if (e1->type == E_NOT) {
502 if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
504 sym1 = tmp->left.sym;
507 if (e2->type == E_NOT) {
508 if (e2->left.expr->type != E_SYMBOL)
510 sym2 = e2->left.expr->left.sym;
515 if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
518 if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
519 (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
520 // (a) && (a='y') -> (a='y')
521 return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
523 if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
524 (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
525 // (a) && (a!='n') -> (a)
526 return expr_alloc_symbol(sym1);
528 if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
529 (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
530 // (a) && (a!='m') -> (a='y')
531 return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
533 if (sym1->type == S_TRISTATE) {
534 if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
535 // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
536 sym2 = e1->right.sym;
537 if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
538 return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
539 : expr_alloc_symbol(&symbol_no);
541 if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
542 // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
543 sym2 = e2->right.sym;
544 if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
545 return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
546 : expr_alloc_symbol(&symbol_no);
548 if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
549 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
550 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
551 // (a!='y') && (a!='n') -> (a='m')
552 return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
554 if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
555 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
556 (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
557 // (a!='y') && (a!='m') -> (a='n')
558 return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
560 if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
561 ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
562 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
563 // (a!='m') && (a!='n') -> (a='m')
564 return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
566 if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
567 (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
568 (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
569 (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
574 printf("optimize (");
575 expr_fprint(e1, stdout);
577 expr_fprint(e2, stdout);
584 * expr_eliminate_dups() helper.
586 * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
587 * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
588 * against all other leaves to look for simplifications.
590 static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
596 /* Recurse down to leaves */
598 if (e1->type == type) {
599 expr_eliminate_dups1(type, &e1->left.expr, &e2);
600 expr_eliminate_dups1(type, &e1->right.expr, &e2);
603 if (e2->type == type) {
604 expr_eliminate_dups1(type, &e1, &e2->left.expr);
605 expr_eliminate_dups1(type, &e1, &e2->right.expr);
609 /* e1 and e2 are leaves. Compare and process them. */
615 case E_OR: case E_AND:
616 expr_eliminate_dups1(e1->type, &e1, &e1);
623 tmp = expr_join_or(e1, e2);
625 expr_free(e1); expr_free(e2);
626 e1 = expr_alloc_symbol(&symbol_no);
632 tmp = expr_join_and(e1, e2);
634 expr_free(e1); expr_free(e2);
635 e1 = expr_alloc_symbol(&symbol_yes);
648 * Rewrites 'e' in-place to remove ("join") duplicate and other redundant
651 * Example simplifications:
653 * A || B || A -> A || B
654 * A && B && A=y -> A=y && B
656 * Returns the deduplicated expression.
658 struct expr *expr_eliminate_dups(struct expr *e)
664 oldcount = trans_count;
668 case E_OR: case E_AND:
669 expr_eliminate_dups1(e->type, &e, &e);
674 /* No simplifications done in this pass. We're done */
676 e = expr_eliminate_yn(e);
678 trans_count = oldcount;
683 * Performs various simplifications involving logical operators and
686 * Allocates and returns a new expression.
688 struct expr *expr_transform(struct expr *e)
705 e->left.expr = expr_transform(e->left.expr);
706 e->right.expr = expr_transform(e->right.expr);
711 if (e->left.sym->type != S_BOOLEAN)
713 if (e->right.sym == &symbol_no) {
715 e->left.expr = expr_alloc_symbol(e->left.sym);
719 if (e->right.sym == &symbol_mod) {
720 printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
722 e->left.sym = &symbol_no;
726 if (e->right.sym == &symbol_yes) {
733 if (e->left.sym->type != S_BOOLEAN)
735 if (e->right.sym == &symbol_no) {
740 if (e->right.sym == &symbol_mod) {
741 printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
743 e->left.sym = &symbol_yes;
747 if (e->right.sym == &symbol_yes) {
749 e->left.expr = expr_alloc_symbol(e->left.sym);
755 switch (e->left.expr->type) {
758 tmp = e->left.expr->left.expr;
762 e = expr_transform(e);
770 e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
778 e->type = e->type == E_LEQ ? E_GTH : E_LTH;
786 e->type = e->type == E_LTH ? E_GEQ : E_LEQ;
789 // !(a || b) -> !a && !b
792 e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
794 tmp->right.expr = NULL;
795 e = expr_transform(e);
798 // !(a && b) -> !a || !b
801 e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
803 tmp->right.expr = NULL;
804 e = expr_transform(e);
807 if (e->left.expr->left.sym == &symbol_yes) {
813 e->left.sym = &symbol_no;
816 if (e->left.expr->left.sym == &symbol_mod) {
822 e->left.sym = &symbol_mod;
825 if (e->left.expr->left.sym == &symbol_no) {
831 e->left.sym = &symbol_yes;
845 int expr_contains_symbol(struct expr *dep, struct symbol *sym)
853 return expr_contains_symbol(dep->left.expr, sym) ||
854 expr_contains_symbol(dep->right.expr, sym);
856 return dep->left.sym == sym;
863 return dep->left.sym == sym ||
864 dep->right.sym == sym;
866 return expr_contains_symbol(dep->left.expr, sym);
873 bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
880 return expr_depends_symbol(dep->left.expr, sym) ||
881 expr_depends_symbol(dep->right.expr, sym);
883 return dep->left.sym == sym;
885 if (dep->left.sym == sym) {
886 if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
891 if (dep->left.sym == sym) {
892 if (dep->right.sym == &symbol_no)
903 * Inserts explicit comparisons of type 'type' to symbol 'sym' into the
906 * Examples transformations for type == E_UNEQUAL, sym == &symbol_no:
910 * A && B -> !(A=n || B=n)
911 * A || B -> !(A=n && B=n)
912 * A && (B || C) -> !(A=n || (B=n && C=n))
914 * Allocates and returns a new expression.
916 struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
918 struct expr *e1, *e2;
921 e = expr_alloc_symbol(sym);
922 if (type == E_UNEQUAL)
923 e = expr_alloc_one(E_NOT, e);
928 e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
929 e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
930 if (sym == &symbol_yes)
931 e = expr_alloc_two(E_AND, e1, e2);
932 if (sym == &symbol_no)
933 e = expr_alloc_two(E_OR, e1, e2);
934 if (type == E_UNEQUAL)
935 e = expr_alloc_one(E_NOT, e);
938 e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
939 e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
940 if (sym == &symbol_yes)
941 e = expr_alloc_two(E_OR, e1, e2);
942 if (sym == &symbol_no)
943 e = expr_alloc_two(E_AND, e1, e2);
944 if (type == E_UNEQUAL)
945 e = expr_alloc_one(E_NOT, e);
948 return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
955 if (type == E_EQUAL) {
956 if (sym == &symbol_yes)
958 if (sym == &symbol_mod)
959 return expr_alloc_symbol(&symbol_no);
960 if (sym == &symbol_no)
961 return expr_alloc_one(E_NOT, expr_copy(e));
963 if (sym == &symbol_yes)
964 return expr_alloc_one(E_NOT, expr_copy(e));
965 if (sym == &symbol_mod)
966 return expr_alloc_symbol(&symbol_yes);
967 if (sym == &symbol_no)
972 return expr_alloc_comp(type, e->left.sym, sym);
981 enum string_value_kind {
988 unsigned long long u;
992 static enum string_value_kind expr_parse_string(const char *str,
993 enum symbol_type type,
994 union string_value *val)
997 enum string_value_kind kind;
1003 val->s = !strcmp(str, "n") ? 0 :
1004 !strcmp(str, "m") ? 1 :
1005 !strcmp(str, "y") ? 2 : -1;
1008 val->s = strtoll(str, &tail, 10);
1012 val->u = strtoull(str, &tail, 16);
1016 val->s = strtoll(str, &tail, 0);
1020 return !errno && !*tail && tail > str && isxdigit(tail[-1])
1024 tristate expr_calc_value(struct expr *e)
1026 tristate val1, val2;
1027 const char *str1, *str2;
1028 enum string_value_kind k1 = k_string, k2 = k_string;
1029 union string_value lval = {}, rval = {};
1037 sym_calc_value(e->left.sym);
1038 return e->left.sym->curr.tri;
1040 val1 = expr_calc_value(e->left.expr);
1041 val2 = expr_calc_value(e->right.expr);
1042 return EXPR_AND(val1, val2);
1044 val1 = expr_calc_value(e->left.expr);
1045 val2 = expr_calc_value(e->right.expr);
1046 return EXPR_OR(val1, val2);
1048 val1 = expr_calc_value(e->left.expr);
1049 return EXPR_NOT(val1);
1058 printf("expr_calc_value: %d?\n", e->type);
1062 sym_calc_value(e->left.sym);
1063 sym_calc_value(e->right.sym);
1064 str1 = sym_get_string_value(e->left.sym);
1065 str2 = sym_get_string_value(e->right.sym);
1067 if (e->left.sym->type != S_STRING || e->right.sym->type != S_STRING) {
1068 k1 = expr_parse_string(str1, e->left.sym->type, &lval);
1069 k2 = expr_parse_string(str2, e->right.sym->type, &rval);
1072 if (k1 == k_string || k2 == k_string)
1073 res = strcmp(str1, str2);
1074 else if (k1 == k_unsigned || k2 == k_unsigned)
1075 res = (lval.u > rval.u) - (lval.u < rval.u);
1076 else /* if (k1 == k_signed && k2 == k_signed) */
1077 res = (lval.s > rval.s) - (lval.s < rval.s);
1081 return res ? no : yes;
1083 return res >= 0 ? yes : no;
1085 return res > 0 ? yes : no;
1087 return res <= 0 ? yes : no;
1089 return res < 0 ? yes : no;
1091 return res ? yes : no;
1093 printf("expr_calc_value: relation %d?\n", e->type);
1098 static int expr_compare_type(enum expr_type t1, enum expr_type t2)
1107 if (t2 == E_EQUAL || t2 == E_UNEQUAL)
1128 printf("[%dgt%d?]", t1, t2);
1132 void expr_print(struct expr *e,
1133 void (*fn)(void *, struct symbol *, const char *),
1134 void *data, int prevtoken)
1137 fn(data, NULL, "y");
1141 if (expr_compare_type(prevtoken, e->type) > 0)
1142 fn(data, NULL, "(");
1145 if (e->left.sym->name)
1146 fn(data, e->left.sym, e->left.sym->name);
1148 fn(data, NULL, "<choice>");
1151 fn(data, NULL, "!");
1152 expr_print(e->left.expr, fn, data, E_NOT);
1155 if (e->left.sym->name)
1156 fn(data, e->left.sym, e->left.sym->name);
1158 fn(data, NULL, "<choice>");
1159 fn(data, NULL, "=");
1160 fn(data, e->right.sym, e->right.sym->name);
1164 if (e->left.sym->name)
1165 fn(data, e->left.sym, e->left.sym->name);
1167 fn(data, NULL, "<choice>");
1168 fn(data, NULL, e->type == E_LEQ ? "<=" : "<");
1169 fn(data, e->right.sym, e->right.sym->name);
1173 if (e->left.sym->name)
1174 fn(data, e->left.sym, e->left.sym->name);
1176 fn(data, NULL, "<choice>");
1177 fn(data, NULL, e->type == E_GEQ ? ">=" : ">");
1178 fn(data, e->right.sym, e->right.sym->name);
1181 if (e->left.sym->name)
1182 fn(data, e->left.sym, e->left.sym->name);
1184 fn(data, NULL, "<choice>");
1185 fn(data, NULL, "!=");
1186 fn(data, e->right.sym, e->right.sym->name);
1189 expr_print(e->left.expr, fn, data, E_OR);
1190 fn(data, NULL, " || ");
1191 expr_print(e->right.expr, fn, data, E_OR);
1194 expr_print(e->left.expr, fn, data, E_AND);
1195 fn(data, NULL, " && ");
1196 expr_print(e->right.expr, fn, data, E_AND);
1199 fn(data, e->right.sym, e->right.sym->name);
1201 fn(data, NULL, " ^ ");
1202 expr_print(e->left.expr, fn, data, E_LIST);
1206 fn(data, NULL, "[");
1207 fn(data, e->left.sym, e->left.sym->name);
1208 fn(data, NULL, " ");
1209 fn(data, e->right.sym, e->right.sym->name);
1210 fn(data, NULL, "]");
1215 sprintf(buf, "<unknown type %d>", e->type);
1216 fn(data, NULL, buf);
1220 if (expr_compare_type(prevtoken, e->type) > 0)
1221 fn(data, NULL, ")");
1224 static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
1226 xfwrite(str, strlen(str), 1, data);
1229 void expr_fprint(struct expr *e, FILE *out)
1231 expr_print(e, expr_print_file_helper, out, E_NONE);
1234 static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
1236 struct gstr *gs = (struct gstr*)data;
1237 const char *sym_str = NULL;
1240 sym_str = sym_get_string_value(sym);
1242 if (gs->max_width) {
1243 unsigned extra_length = strlen(str);
1244 const char *last_cr = strrchr(gs->s, '\n');
1245 unsigned last_line_length;
1248 extra_length += 4 + strlen(sym_str);
1253 last_line_length = strlen(gs->s) - (last_cr - gs->s);
1255 if ((last_line_length + extra_length) > gs->max_width)
1256 str_append(gs, "\\\n");
1259 str_append(gs, str);
1260 if (sym && sym->type != S_UNKNOWN)
1261 str_printf(gs, " [=%s]", sym_str);
1264 void expr_gstr_print(struct expr *e, struct gstr *gs)
1266 expr_print(e, expr_print_gstr_helper, gs, E_NONE);
1270 * Transform the top level "||" tokens into newlines and prepend each
1271 * line with a minus. This makes expressions much easier to read.
1272 * Suitable for reverse dependency expressions.
1274 static void expr_print_revdep(struct expr *e,
1275 void (*fn)(void *, struct symbol *, const char *),
1276 void *data, tristate pr_type, const char **title)
1278 if (e->type == E_OR) {
1279 expr_print_revdep(e->left.expr, fn, data, pr_type, title);
1280 expr_print_revdep(e->right.expr, fn, data, pr_type, title);
1281 } else if (expr_calc_value(e) == pr_type) {
1283 fn(data, NULL, *title);
1287 fn(data, NULL, " - ");
1288 expr_print(e, fn, data, E_NONE);
1289 fn(data, NULL, "\n");
1293 void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
1294 tristate pr_type, const char *title)
1296 expr_print_revdep(e, expr_print_gstr_helper, gs, pr_type, &title);