diff options
Diffstat (limited to 'scripts/kconfig/expr.c')
-rw-r--r-- | scripts/kconfig/expr.c | 288 |
1 files changed, 163 insertions, 125 deletions
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c index d6626521f9b9..667d1aa23711 100644 --- a/scripts/kconfig/expr.c +++ b/scripts/kconfig/expr.c | |||
@@ -11,6 +11,9 @@ | |||
11 | 11 | ||
12 | #define DEBUG_EXPR 0 | 12 | #define DEBUG_EXPR 0 |
13 | 13 | ||
14 | static int expr_eq(struct expr *e1, struct expr *e2); | ||
15 | static struct expr *expr_eliminate_yn(struct expr *e); | ||
16 | |||
14 | struct expr *expr_alloc_symbol(struct symbol *sym) | 17 | struct expr *expr_alloc_symbol(struct symbol *sym) |
15 | { | 18 | { |
16 | struct expr *e = xcalloc(1, sizeof(*e)); | 19 | struct expr *e = xcalloc(1, sizeof(*e)); |
@@ -76,6 +79,10 @@ struct expr *expr_copy(const struct expr *org) | |||
76 | e->left.expr = expr_copy(org->left.expr); | 79 | e->left.expr = expr_copy(org->left.expr); |
77 | break; | 80 | break; |
78 | case E_EQUAL: | 81 | case E_EQUAL: |
82 | case E_GEQ: | ||
83 | case E_GTH: | ||
84 | case E_LEQ: | ||
85 | case E_LTH: | ||
79 | case E_UNEQUAL: | 86 | case E_UNEQUAL: |
80 | e->left.sym = org->left.sym; | 87 | e->left.sym = org->left.sym; |
81 | e->right.sym = org->right.sym; | 88 | e->right.sym = org->right.sym; |
@@ -108,6 +115,10 @@ void expr_free(struct expr *e) | |||
108 | expr_free(e->left.expr); | 115 | expr_free(e->left.expr); |
109 | return; | 116 | return; |
110 | case E_EQUAL: | 117 | case E_EQUAL: |
118 | case E_GEQ: | ||
119 | case E_GTH: | ||
120 | case E_LEQ: | ||
121 | case E_LTH: | ||
111 | case E_UNEQUAL: | 122 | case E_UNEQUAL: |
112 | break; | 123 | break; |
113 | case E_OR: | 124 | case E_OR: |
@@ -186,7 +197,7 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) | |||
186 | #undef e1 | 197 | #undef e1 |
187 | #undef e2 | 198 | #undef e2 |
188 | 199 | ||
189 | int expr_eq(struct expr *e1, struct expr *e2) | 200 | static int expr_eq(struct expr *e1, struct expr *e2) |
190 | { | 201 | { |
191 | int res, old_count; | 202 | int res, old_count; |
192 | 203 | ||
@@ -194,6 +205,10 @@ int expr_eq(struct expr *e1, struct expr *e2) | |||
194 | return 0; | 205 | return 0; |
195 | switch (e1->type) { | 206 | switch (e1->type) { |
196 | case E_EQUAL: | 207 | case E_EQUAL: |
208 | case E_GEQ: | ||
209 | case E_GTH: | ||
210 | case E_LEQ: | ||
211 | case E_LTH: | ||
197 | case E_UNEQUAL: | 212 | case E_UNEQUAL: |
198 | return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; | 213 | return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; |
199 | case E_SYMBOL: | 214 | case E_SYMBOL: |
@@ -228,7 +243,7 @@ int expr_eq(struct expr *e1, struct expr *e2) | |||
228 | return 0; | 243 | return 0; |
229 | } | 244 | } |
230 | 245 | ||
231 | struct expr *expr_eliminate_yn(struct expr *e) | 246 | static struct expr *expr_eliminate_yn(struct expr *e) |
232 | { | 247 | { |
233 | struct expr *tmp; | 248 | struct expr *tmp; |
234 | 249 | ||
@@ -553,62 +568,6 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct | |||
553 | #undef e2 | 568 | #undef e2 |
554 | } | 569 | } |
555 | 570 | ||
556 | static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2) | ||
557 | { | ||
558 | #define e1 (*ep1) | ||
559 | #define e2 (*ep2) | ||
560 | struct expr *tmp, *tmp1, *tmp2; | ||
561 | |||
562 | if (e1->type == type) { | ||
563 | expr_eliminate_dups2(type, &e1->left.expr, &e2); | ||
564 | expr_eliminate_dups2(type, &e1->right.expr, &e2); | ||
565 | return; | ||
566 | } | ||
567 | if (e2->type == type) { | ||
568 | expr_eliminate_dups2(type, &e1, &e2->left.expr); | ||
569 | expr_eliminate_dups2(type, &e1, &e2->right.expr); | ||
570 | } | ||
571 | if (e1 == e2) | ||
572 | return; | ||
573 | |||
574 | switch (e1->type) { | ||
575 | case E_OR: | ||
576 | expr_eliminate_dups2(e1->type, &e1, &e1); | ||
577 | // (FOO || BAR) && (!FOO && !BAR) -> n | ||
578 | tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); | ||
579 | tmp2 = expr_copy(e2); | ||
580 | tmp = expr_extract_eq_and(&tmp1, &tmp2); | ||
581 | if (expr_is_yes(tmp1)) { | ||
582 | expr_free(e1); | ||
583 | e1 = expr_alloc_symbol(&symbol_no); | ||
584 | trans_count++; | ||
585 | } | ||
586 | expr_free(tmp2); | ||
587 | expr_free(tmp1); | ||
588 | expr_free(tmp); | ||
589 | break; | ||
590 | case E_AND: | ||
591 | expr_eliminate_dups2(e1->type, &e1, &e1); | ||
592 | // (FOO && BAR) || (!FOO || !BAR) -> y | ||
593 | tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); | ||
594 | tmp2 = expr_copy(e2); | ||
595 | tmp = expr_extract_eq_or(&tmp1, &tmp2); | ||
596 | if (expr_is_no(tmp1)) { | ||
597 | expr_free(e1); | ||
598 | e1 = expr_alloc_symbol(&symbol_yes); | ||
599 | trans_count++; | ||
600 | } | ||
601 | expr_free(tmp2); | ||
602 | expr_free(tmp1); | ||
603 | expr_free(tmp); | ||
604 | break; | ||
605 | default: | ||
606 | ; | ||
607 | } | ||
608 | #undef e1 | ||
609 | #undef e2 | ||
610 | } | ||
611 | |||
612 | struct expr *expr_eliminate_dups(struct expr *e) | 571 | struct expr *expr_eliminate_dups(struct expr *e) |
613 | { | 572 | { |
614 | int oldcount; | 573 | int oldcount; |
@@ -621,7 +580,6 @@ struct expr *expr_eliminate_dups(struct expr *e) | |||
621 | switch (e->type) { | 580 | switch (e->type) { |
622 | case E_OR: case E_AND: | 581 | case E_OR: case E_AND: |
623 | expr_eliminate_dups1(e->type, &e, &e); | 582 | expr_eliminate_dups1(e->type, &e, &e); |
624 | expr_eliminate_dups2(e->type, &e, &e); | ||
625 | default: | 583 | default: |
626 | ; | 584 | ; |
627 | } | 585 | } |
@@ -641,6 +599,10 @@ struct expr *expr_transform(struct expr *e) | |||
641 | return NULL; | 599 | return NULL; |
642 | switch (e->type) { | 600 | switch (e->type) { |
643 | case E_EQUAL: | 601 | case E_EQUAL: |
602 | case E_GEQ: | ||
603 | case E_GTH: | ||
604 | case E_LEQ: | ||
605 | case E_LTH: | ||
644 | case E_UNEQUAL: | 606 | case E_UNEQUAL: |
645 | case E_SYMBOL: | 607 | case E_SYMBOL: |
646 | case E_LIST: | 608 | case E_LIST: |
@@ -713,6 +675,22 @@ struct expr *expr_transform(struct expr *e) | |||
713 | e = tmp; | 675 | e = tmp; |
714 | e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL; | 676 | e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL; |
715 | break; | 677 | break; |
678 | case E_LEQ: | ||
679 | case E_GEQ: | ||
680 | // !a<='x' -> a>'x' | ||
681 | tmp = e->left.expr; | ||
682 | free(e); | ||
683 | e = tmp; | ||
684 | e->type = e->type == E_LEQ ? E_GTH : E_LTH; | ||
685 | break; | ||
686 | case E_LTH: | ||
687 | case E_GTH: | ||
688 | // !a<'x' -> a>='x' | ||
689 | tmp = e->left.expr; | ||
690 | free(e); | ||
691 | e = tmp; | ||
692 | e->type = e->type == E_LTH ? E_GEQ : E_LEQ; | ||
693 | break; | ||
716 | case E_OR: | 694 | case E_OR: |
717 | // !(a || b) -> !a && !b | 695 | // !(a || b) -> !a && !b |
718 | tmp = e->left.expr; | 696 | tmp = e->left.expr; |
@@ -783,6 +761,10 @@ int expr_contains_symbol(struct expr *dep, struct symbol *sym) | |||
783 | case E_SYMBOL: | 761 | case E_SYMBOL: |
784 | return dep->left.sym == sym; | 762 | return dep->left.sym == sym; |
785 | case E_EQUAL: | 763 | case E_EQUAL: |
764 | case E_GEQ: | ||
765 | case E_GTH: | ||
766 | case E_LEQ: | ||
767 | case E_LTH: | ||
786 | case E_UNEQUAL: | 768 | case E_UNEQUAL: |
787 | return dep->left.sym == sym || | 769 | return dep->left.sym == sym || |
788 | dep->right.sym == sym; | 770 | dep->right.sym == sym; |
@@ -823,57 +805,6 @@ bool expr_depends_symbol(struct expr *dep, struct symbol *sym) | |||
823 | return false; | 805 | return false; |
824 | } | 806 | } |
825 | 807 | ||
826 | struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2) | ||
827 | { | ||
828 | struct expr *tmp = NULL; | ||
829 | expr_extract_eq(E_AND, &tmp, ep1, ep2); | ||
830 | if (tmp) { | ||
831 | *ep1 = expr_eliminate_yn(*ep1); | ||
832 | *ep2 = expr_eliminate_yn(*ep2); | ||
833 | } | ||
834 | return tmp; | ||
835 | } | ||
836 | |||
837 | struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2) | ||
838 | { | ||
839 | struct expr *tmp = NULL; | ||
840 | expr_extract_eq(E_OR, &tmp, ep1, ep2); | ||
841 | if (tmp) { | ||
842 | *ep1 = expr_eliminate_yn(*ep1); | ||
843 | *ep2 = expr_eliminate_yn(*ep2); | ||
844 | } | ||
845 | return tmp; | ||
846 | } | ||
847 | |||
848 | void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2) | ||
849 | { | ||
850 | #define e1 (*ep1) | ||
851 | #define e2 (*ep2) | ||
852 | if (e1->type == type) { | ||
853 | expr_extract_eq(type, ep, &e1->left.expr, &e2); | ||
854 | expr_extract_eq(type, ep, &e1->right.expr, &e2); | ||
855 | return; | ||
856 | } | ||
857 | if (e2->type == type) { | ||
858 | expr_extract_eq(type, ep, ep1, &e2->left.expr); | ||
859 | expr_extract_eq(type, ep, ep1, &e2->right.expr); | ||
860 | return; | ||
861 | } | ||
862 | if (expr_eq(e1, e2)) { | ||
863 | *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1; | ||
864 | expr_free(e2); | ||
865 | if (type == E_AND) { | ||
866 | e1 = expr_alloc_symbol(&symbol_yes); | ||
867 | e2 = expr_alloc_symbol(&symbol_yes); | ||
868 | } else if (type == E_OR) { | ||
869 | e1 = expr_alloc_symbol(&symbol_no); | ||
870 | e2 = expr_alloc_symbol(&symbol_no); | ||
871 | } | ||
872 | } | ||
873 | #undef e1 | ||
874 | #undef e2 | ||
875 | } | ||
876 | |||
877 | struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) | 808 | struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) |
878 | { | 809 | { |
879 | struct expr *e1, *e2; | 810 | struct expr *e1, *e2; |
@@ -908,6 +839,10 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb | |||
908 | case E_NOT: | 839 | case E_NOT: |
909 | return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym); | 840 | return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym); |
910 | case E_UNEQUAL: | 841 | case E_UNEQUAL: |
842 | case E_LTH: | ||
843 | case E_LEQ: | ||
844 | case E_GTH: | ||
845 | case E_GEQ: | ||
911 | case E_EQUAL: | 846 | case E_EQUAL: |
912 | if (type == E_EQUAL) { | 847 | if (type == E_EQUAL) { |
913 | if (sym == &symbol_yes) | 848 | if (sym == &symbol_yes) |
@@ -935,10 +870,57 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb | |||
935 | return NULL; | 870 | return NULL; |
936 | } | 871 | } |
937 | 872 | ||
873 | enum string_value_kind { | ||
874 | k_string, | ||
875 | k_signed, | ||
876 | k_unsigned, | ||
877 | k_invalid | ||
878 | }; | ||
879 | |||
880 | union string_value { | ||
881 | unsigned long long u; | ||
882 | signed long long s; | ||
883 | }; | ||
884 | |||
885 | static enum string_value_kind expr_parse_string(const char *str, | ||
886 | enum symbol_type type, | ||
887 | union string_value *val) | ||
888 | { | ||
889 | char *tail; | ||
890 | enum string_value_kind kind; | ||
891 | |||
892 | errno = 0; | ||
893 | switch (type) { | ||
894 | case S_BOOLEAN: | ||
895 | case S_TRISTATE: | ||
896 | return k_string; | ||
897 | case S_INT: | ||
898 | val->s = strtoll(str, &tail, 10); | ||
899 | kind = k_signed; | ||
900 | break; | ||
901 | case S_HEX: | ||
902 | val->u = strtoull(str, &tail, 16); | ||
903 | kind = k_unsigned; | ||
904 | break; | ||
905 | case S_STRING: | ||
906 | case S_UNKNOWN: | ||
907 | val->s = strtoll(str, &tail, 0); | ||
908 | kind = k_signed; | ||
909 | break; | ||
910 | default: | ||
911 | return k_invalid; | ||
912 | } | ||
913 | return !errno && !*tail && tail > str && isxdigit(tail[-1]) | ||
914 | ? kind : k_string; | ||
915 | } | ||
916 | |||
938 | tristate expr_calc_value(struct expr *e) | 917 | tristate expr_calc_value(struct expr *e) |
939 | { | 918 | { |
940 | tristate val1, val2; | 919 | tristate val1, val2; |
941 | const char *str1, *str2; | 920 | const char *str1, *str2; |
921 | enum string_value_kind k1 = k_string, k2 = k_string; | ||
922 | union string_value lval = {}, rval = {}; | ||
923 | int res; | ||
942 | 924 | ||
943 | if (!e) | 925 | if (!e) |
944 | return yes; | 926 | return yes; |
@@ -959,31 +941,70 @@ tristate expr_calc_value(struct expr *e) | |||
959 | val1 = expr_calc_value(e->left.expr); | 941 | val1 = expr_calc_value(e->left.expr); |
960 | return EXPR_NOT(val1); | 942 | return EXPR_NOT(val1); |
961 | case E_EQUAL: | 943 | case E_EQUAL: |
962 | sym_calc_value(e->left.sym); | 944 | case E_GEQ: |
963 | sym_calc_value(e->right.sym); | 945 | case E_GTH: |
964 | str1 = sym_get_string_value(e->left.sym); | 946 | case E_LEQ: |
965 | str2 = sym_get_string_value(e->right.sym); | 947 | case E_LTH: |
966 | return !strcmp(str1, str2) ? yes : no; | ||
967 | case E_UNEQUAL: | 948 | case E_UNEQUAL: |
968 | sym_calc_value(e->left.sym); | 949 | break; |
969 | sym_calc_value(e->right.sym); | ||
970 | str1 = sym_get_string_value(e->left.sym); | ||
971 | str2 = sym_get_string_value(e->right.sym); | ||
972 | return !strcmp(str1, str2) ? no : yes; | ||
973 | default: | 950 | default: |
974 | printf("expr_calc_value: %d?\n", e->type); | 951 | printf("expr_calc_value: %d?\n", e->type); |
975 | return no; | 952 | return no; |
976 | } | 953 | } |
954 | |||
955 | sym_calc_value(e->left.sym); | ||
956 | sym_calc_value(e->right.sym); | ||
957 | str1 = sym_get_string_value(e->left.sym); | ||
958 | str2 = sym_get_string_value(e->right.sym); | ||
959 | |||
960 | if (e->left.sym->type != S_STRING || e->right.sym->type != S_STRING) { | ||
961 | k1 = expr_parse_string(str1, e->left.sym->type, &lval); | ||
962 | k2 = expr_parse_string(str2, e->right.sym->type, &rval); | ||
963 | } | ||
964 | |||
965 | if (k1 == k_string || k2 == k_string) | ||
966 | res = strcmp(str1, str2); | ||
967 | else if (k1 == k_invalid || k2 == k_invalid) { | ||
968 | if (e->type != E_EQUAL && e->type != E_UNEQUAL) { | ||
969 | printf("Cannot compare \"%s\" and \"%s\"\n", str1, str2); | ||
970 | return no; | ||
971 | } | ||
972 | res = strcmp(str1, str2); | ||
973 | } else if (k1 == k_unsigned || k2 == k_unsigned) | ||
974 | res = (lval.u > rval.u) - (lval.u < rval.u); | ||
975 | else /* if (k1 == k_signed && k2 == k_signed) */ | ||
976 | res = (lval.s > rval.s) - (lval.s < rval.s); | ||
977 | |||
978 | switch(e->type) { | ||
979 | case E_EQUAL: | ||
980 | return res ? no : yes; | ||
981 | case E_GEQ: | ||
982 | return res >= 0 ? yes : no; | ||
983 | case E_GTH: | ||
984 | return res > 0 ? yes : no; | ||
985 | case E_LEQ: | ||
986 | return res <= 0 ? yes : no; | ||
987 | case E_LTH: | ||
988 | return res < 0 ? yes : no; | ||
989 | case E_UNEQUAL: | ||
990 | return res ? yes : no; | ||
991 | default: | ||
992 | printf("expr_calc_value: relation %d?\n", e->type); | ||
993 | return no; | ||
994 | } | ||
977 | } | 995 | } |
978 | 996 | ||
979 | int expr_compare_type(enum expr_type t1, enum expr_type t2) | 997 | static int expr_compare_type(enum expr_type t1, enum expr_type t2) |
980 | { | 998 | { |
981 | #if 0 | ||
982 | return 1; | ||
983 | #else | ||
984 | if (t1 == t2) | 999 | if (t1 == t2) |
985 | return 0; | 1000 | return 0; |
986 | switch (t1) { | 1001 | switch (t1) { |
1002 | case E_LEQ: | ||
1003 | case E_LTH: | ||
1004 | case E_GEQ: | ||
1005 | case E_GTH: | ||
1006 | if (t2 == E_EQUAL || t2 == E_UNEQUAL) | ||
1007 | return 1; | ||
987 | case E_EQUAL: | 1008 | case E_EQUAL: |
988 | case E_UNEQUAL: | 1009 | case E_UNEQUAL: |
989 | if (t2 == E_NOT) | 1010 | if (t2 == E_NOT) |
@@ -1005,7 +1026,6 @@ int expr_compare_type(enum expr_type t1, enum expr_type t2) | |||
1005 | } | 1026 | } |
1006 | printf("[%dgt%d?]", t1, t2); | 1027 | printf("[%dgt%d?]", t1, t2); |
1007 | return 0; | 1028 | return 0; |
1008 | #endif | ||
1009 | } | 1029 | } |
1010 | 1030 | ||
1011 | static inline struct expr * | 1031 | static inline struct expr * |
@@ -1078,6 +1098,24 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char * | |||
1078 | fn(data, NULL, "="); | 1098 | fn(data, NULL, "="); |
1079 | fn(data, e->right.sym, e->right.sym->name); | 1099 | fn(data, e->right.sym, e->right.sym->name); |
1080 | break; | 1100 | break; |
1101 | case E_LEQ: | ||
1102 | case E_LTH: | ||
1103 | if (e->left.sym->name) | ||
1104 | fn(data, e->left.sym, e->left.sym->name); | ||
1105 | else | ||
1106 | fn(data, NULL, "<choice>"); | ||
1107 | fn(data, NULL, e->type == E_LEQ ? "<=" : "<"); | ||
1108 | fn(data, e->right.sym, e->right.sym->name); | ||
1109 | break; | ||
1110 | case E_GEQ: | ||
1111 | case E_GTH: | ||
1112 | if (e->left.sym->name) | ||
1113 | fn(data, e->left.sym, e->left.sym->name); | ||
1114 | else | ||
1115 | fn(data, NULL, "<choice>"); | ||
1116 | fn(data, NULL, e->type == E_LEQ ? ">=" : ">"); | ||
1117 | fn(data, e->right.sym, e->right.sym->name); | ||
1118 | break; | ||
1081 | case E_UNEQUAL: | 1119 | case E_UNEQUAL: |
1082 | if (e->left.sym->name) | 1120 | if (e->left.sym->name) |
1083 | fn(data, e->left.sym, e->left.sym->name); | 1121 | fn(data, e->left.sym, e->left.sym->name); |