From 4d11907abfeb7a1de0080a8c7a7e67ce4fa231db Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Thu, 5 Oct 2017 14:01:14 +0200 Subject: [PATCH] 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 Signed-off-by: Masahiro Yamada Signed-off-by: Christian Lamparter --- config/menu.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/config/menu.c b/config/menu.c index 912c776..c8cec26 100644 --- a/config/menu.c +++ b/config/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) { -- 2.31.1