History

kconfig: fix submenu rendering of negative dependencies

The Kconfig frontend should render options that depend on a previous option in the submenu of that previous option. But currently, this breaks for negative dependencies. For example, option FOO may be rendered in the submenu of option BAR, despite FOO actually depending on !BAR. Let's fix this ironic rendering by modifying Kconfig to explicitly check negative dependencies. I've only tested locally on x86, but as far as I can tell, this only changes how 2 options are rendered in the menu: 1. NTFS3_FS, no longer in the NTFS_FS submenu, and 2. MTD_BLOCK_RO, no longer in the MTD_BLOCK submenu.

Julian Braha committed 3 months ago

Commit 35e4b601 parent 14b8b4b3 files · +44 −0Browse files

Unified · Split

3 files
  1. scripts/kconfig/expr.c +33 −0
  2. scripts/kconfig/expr.h +1 −0
  3. scripts/kconfig/menu.c +10 −0
scripts/kconfig/expr.c+33−0
@@ -738,6 +738,39 @@ bool expr_contains_symbol(struct expr *dep, struct symbol *sym) · 737 unmodified lines
738738 return false;
739739 }
740740
741+/*
742+ * Check if the expression references 'sym' in a way that is satisfiable
743+ * with 'sym' disabled, e.g.'sym!=y'.
744+ *
745+ * Expects that expr_transform() was already called on 'expr'.
746+ */
747+bool expr_contains_symbol_negated(struct expr *dep, struct symbol *sym)
748+{
749+ if (!dep)
750+ return false;
751+
752+ switch (dep->type) {
753+ case E_AND:
754+ case E_OR:
755+ return expr_contains_symbol_negated(dep->left.expr, sym) ||
756+ expr_contains_symbol_negated(dep->right.expr, sym);
757+ case E_NOT:
758+ return dep->left.expr->type == E_SYMBOL &&
759+ dep->left.expr->left.sym == sym;
760+ case E_EQUAL:
761+ /* sym=n */
762+ return dep->left.sym == sym && dep->right.sym == &symbol_no;
763+ case E_UNEQUAL:
764+ /* sym!=y, sym!=m */
765+ return dep->left.sym == sym &&
766+ (dep->right.sym == &symbol_yes ||
767+ dep->right.sym == &symbol_mod);
768+ default:
769+ break;
770+ }
771+ return false;
772+}
773+
741774 bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
742775 {
743776 if (!dep)
scripts/kconfig/expr.h+1−0
@@ -307,6 +307,7 @@ tristate expr_calc_value(struct expr *e); · 306 unmodified lines
307307 struct expr *expr_eliminate_dups(struct expr *e);
308308 struct expr *expr_transform(struct expr *e);
309309 bool expr_contains_symbol(struct expr *dep, struct symbol *sym);
310+bool expr_contains_symbol_negated(struct expr *dep, struct symbol *sym);
310311 bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
311312 struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
312313
scripts/kconfig/menu.c+10−0
@@ -428,9 +428,19 @@ static void _menu_finalize(struct menu *parent, bool inside_choice) · 427 unmodified lines
428428 if (!expr_contains_symbol(dep, sym))
429429 /* No dependency, quit */
430430 break;
431+ /*
432+ * Note that it's actually possible to depend on both
433+ * 'SYM!=y' and 'SYM=y', so we need to first check if
434+ * it's a positive dependency before checking if it's
435+ * a negative dependency. See example:
436+ * 'SFC && MTD && !(SFC=y && MTD=m)'
437+ */
431438 if (expr_depends_symbol(dep, sym))
432439 /* Absolute dependency, put in submenu */
433440 goto next;
441+ if (expr_contains_symbol_negated(dep, sym))
442+ /* Negative dependency, quit */
443+ break;
434444
435445 /*
436446 * Also consider it a dependency on sym if our