summaryrefslogtreecommitdiff
path: root/scripts/kconfig/menu.c
diff options
context:
space:
mode:
authorUlf Magnusson <ulfalizer@gmail.com>2017-10-05 14:01:14 +0200
committerMasahiro Yamada <yamada.masahiro@socionext.com>2017-12-15 08:21:31 +0900
commitfa8cedaef814ceced8b55e0d2bbd404ccbc2b786 (patch)
tree9ddbdb601050597defb84ab28dd38a4af1bb0356 /scripts/kconfig/menu.c
parent9a826842ff2fbd200561d3c1e81ca34eab6bfbbb (diff)
kconfig: Clarify expression rewriting
menu_finalize() is one of the more opaque parts of Kconfig, and I need to make some changes to it to fix an issue related to modules. Add some comments related to expression rewriting and dependency propagation as a review aid. They will also help other people trying to understand the code. Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Diffstat (limited to 'scripts/kconfig/menu.c')
-rw-r--r--scripts/kconfig/menu.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 912c77645583..c8cec26c2535 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -306,6 +306,11 @@ void menu_finalize(struct menu *parent)
sym = parent->sym;
if (parent->list) {
+ /*
+ * This menu node has children. We (recursively) process them
+ * and propagate parent dependencies before moving on.
+ */
+
if (sym && sym_is_choice(sym)) {
if (sym->type == S_UNKNOWN) {
/* find the first choice value to find out choice type */
@@ -329,24 +334,66 @@ void menu_finalize(struct menu *parent)
else
parentdep = parent->dep;
+ /* For each child menu node... */
for (menu = parent->list; menu; menu = menu->next) {
+ /*
+ * Propagate parent dependencies to the child menu
+ * node, also rewriting and simplifying expressions
+ */
basedep = expr_transform(menu->dep);
basedep = expr_alloc_and(expr_copy(parentdep), basedep);
basedep = expr_eliminate_dups(basedep);
menu->dep = basedep;
+
if (menu->sym)
+ /*
+ * Note: For symbols, all prompts are included
+ * too in the symbol's own property list
+ */
prop = menu->sym->prop;
else
+ /*
+ * For non-symbol menu nodes, we just need to
+ * handle the prompt
+ */
prop = menu->prompt;
+
+ /* For each property... */
for (; prop; prop = prop->next) {
if (prop->menu != menu)
+ /*
+ * Two possibilities:
+ *
+ * 1. The property lacks dependencies
+ * and so isn't location-specific,
+ * e.g. an 'option'
+ *
+ * 2. The property belongs to a symbol
+ * defined in multiple locations and
+ * is from some other location. It
+ * will be handled there in that
+ * case.
+ *
+ * Skip the property.
+ */
continue;
+
+ /*
+ * Propagate parent dependencies to the
+ * property's condition, rewriting and
+ * simplifying expressions at the same time
+ */
dep = expr_transform(prop->visible.expr);
dep = expr_alloc_and(expr_copy(basedep), dep);
dep = expr_eliminate_dups(dep);
if (menu->sym && menu->sym->type != S_TRISTATE)
dep = expr_trans_bool(dep);
prop->visible.expr = dep;
+
+ /*
+ * Handle selects and implies, which modify the
+ * dependencies of the selected/implied symbol
+ */
if (prop->type == P_SELECT) {
struct symbol *es = prop_get_symbol(prop);
es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
@@ -358,6 +405,11 @@ void menu_finalize(struct menu *parent)
}
}
}
+
+ /*
+ * Recursively process children in the same fashion before
+ * moving on
+ */
for (menu = parent->list; menu; menu = menu->next)
menu_finalize(menu);
} else if (sym) {