summaryrefslogtreecommitdiff
path: root/scripts/kconfig/menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/kconfig/menu.c')
-rw-r--r--scripts/kconfig/menu.c183
1 files changed, 48 insertions, 135 deletions
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 3b822cd110f4..6587ac86d0d5 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -8,16 +8,38 @@
#include <stdlib.h>
#include <string.h>
+#include <list.h>
+#include <xalloc.h>
#include "lkc.h"
#include "internal.h"
-#include "list.h"
static const char nohelp_text[] = "There is no help available for this option.";
struct menu rootmenu;
static struct menu **last_entry_ptr;
-void menu_warn(struct menu *menu, const char *fmt, ...)
+/**
+ * menu_next - return the next menu entry with depth-first traversal
+ * @menu: pointer to the current menu
+ * @root: root of the sub-tree to traverse. If NULL is given, the traveral
+ * continues until it reaches the end of the entire menu tree.
+ * return: the menu to visit next, or NULL when it reaches the end.
+ */
+struct menu *menu_next(struct menu *menu, struct menu *root)
+{
+ if (menu->list)
+ return menu->list;
+
+ while (menu != root && !menu->next)
+ menu = menu->parent;
+
+ if (menu == root)
+ return NULL;
+
+ return menu->next;
+}
+
+void menu_warn(const struct menu *menu, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
@@ -27,7 +49,7 @@ void menu_warn(struct menu *menu, const char *fmt, ...)
va_end(ap);
}
-static void prop_warn(struct property *prop, const char *fmt, ...)
+static void prop_warn(const struct property *prop, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
@@ -57,10 +79,8 @@ void menu_add_entry(struct symbol *sym)
*last_entry_ptr = menu;
last_entry_ptr = &menu->next;
current_entry = menu;
- if (sym) {
- menu_add_symbol(P_SYMBOL, sym, NULL);
+ if (sym)
list_add_tail(&menu->link, &sym->menus);
- }
}
struct menu *menu_add_menu(void)
@@ -87,12 +107,13 @@ static struct expr *rewrite_m(struct expr *e)
switch (e->type) {
case E_NOT:
- e->left.expr = rewrite_m(e->left.expr);
+ e = expr_alloc_one(E_NOT, rewrite_m(e->left.expr));
break;
case E_OR:
case E_AND:
- e->left.expr = rewrite_m(e->left.expr);
- e->right.expr = rewrite_m(e->right.expr);
+ e = expr_alloc_two(e->type,
+ rewrite_m(e->left.expr),
+ rewrite_m(e->right.expr));
break;
case E_SYMBOL:
/* change 'm' into 'm' && MODULES */
@@ -154,7 +175,7 @@ static struct property *menu_add_prop(enum prop_type type, struct expr *expr,
return prop;
}
-struct property *menu_add_prompt(enum prop_type type, char *prompt,
+struct property *menu_add_prompt(enum prop_type type, const char *prompt,
struct expr *dep)
{
struct property *prop = menu_add_prop(type, NULL, dep);
@@ -172,21 +193,11 @@ struct property *menu_add_prompt(enum prop_type type, char *prompt,
struct menu *menu = current_entry;
while ((menu = menu->parent) != NULL) {
- struct expr *dup_expr;
if (!menu->visibility)
continue;
- /*
- * Do not add a reference to the menu's visibility
- * expression but use a copy of it. Otherwise the
- * expression reduction functions will modify
- * expressions that have multiple references which
- * can cause unwanted side effects.
- */
- dup_expr = expr_copy(menu->visibility);
-
prop->visible.expr = expr_alloc_and(prop->visible.expr,
- dup_expr);
+ menu->visibility);
}
}
@@ -242,11 +253,9 @@ static void sym_check_prop(struct symbol *sym)
sym->name);
}
if (sym_is_choice(sym)) {
- struct property *choice_prop =
- sym_get_choice_prop(sym2);
+ struct menu *choice = sym_get_choice_menu(sym2);
- if (!choice_prop ||
- prop_get_symbol(choice_prop) != sym)
+ if (!choice || choice->sym != sym)
prop_warn(prop,
"choice default symbol '%s' is not contained in the choice",
sym2->name);
@@ -287,7 +296,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
struct menu *menu, *last_menu;
struct symbol *sym;
struct property *prop;
- struct expr *parentdep, *basedep, *dep, *dep2, **ep;
+ struct expr *basedep, *dep, *dep2;
sym = parent->sym;
if (parent->list) {
@@ -296,35 +305,6 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
* and propagate parent dependencies before moving on.
*/
- bool is_choice = false;
-
- if (sym && sym_is_choice(sym))
- is_choice = true;
-
- if (is_choice) {
- if (sym->type == S_UNKNOWN) {
- /* find the first choice value to find out choice type */
- current_entry = parent;
- for (menu = parent->list; menu; menu = menu->next) {
- if (menu->sym && menu->sym->type != S_UNKNOWN) {
- menu_set_type(menu->sym->type);
- break;
- }
- }
- }
-
- /*
- * Use the choice itself as the parent dependency of
- * the contained items. This turns the mode of the
- * choice into an upper bound on the visibility of the
- * choice value symbols.
- */
- parentdep = expr_alloc_symbol(sym);
- } else {
- /* Menu node for 'menu', 'if' */
- parentdep = parent->dep;
- }
-
/* For each child menu node... */
for (menu = parent->list; menu; menu = menu->next) {
/*
@@ -333,7 +313,7 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
*/
basedep = rewrite_m(menu->dep);
basedep = expr_transform(basedep);
- basedep = expr_alloc_and(expr_copy(parentdep), basedep);
+ basedep = expr_alloc_and(parent->dep, basedep);
basedep = expr_eliminate_dups(basedep);
menu->dep = basedep;
@@ -377,10 +357,8 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
*/
dep = rewrite_m(prop->visible.expr);
dep = expr_transform(dep);
- dep = expr_alloc_and(expr_copy(basedep), dep);
+ dep = expr_alloc_and(basedep, dep);
dep = expr_eliminate_dups(dep);
- if (menu->sym && menu->sym->type != S_TRISTATE)
- dep = expr_trans_bool(dep);
prop->visible.expr = dep;
/*
@@ -390,24 +368,21 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
if (prop->type == P_SELECT) {
struct symbol *es = prop_get_symbol(prop);
es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
- expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
+ expr_alloc_and(expr_alloc_symbol(menu->sym), dep));
} else if (prop->type == P_IMPLY) {
struct symbol *es = prop_get_symbol(prop);
es->implied.expr = expr_alloc_or(es->implied.expr,
- expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
+ expr_alloc_and(expr_alloc_symbol(menu->sym), dep));
}
}
}
- if (is_choice)
- expr_free(parentdep);
-
/*
* Recursively process children in the same fashion before
* moving on
*/
for (menu = parent->list; menu; menu = menu->next)
- _menu_finalize(menu, is_choice);
+ _menu_finalize(menu, sym && sym_is_choice(sym));
} else if (!inside_choice && sym) {
/*
* Automatic submenu creation. If sym is a symbol and A, B, C,
@@ -457,22 +432,18 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
*/
dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
dep = expr_eliminate_dups(expr_transform(dep));
- dep2 = expr_copy(basedep);
+ dep2 = basedep;
expr_eliminate_eq(&dep, &dep2);
- expr_free(dep);
if (!expr_is_yes(dep2)) {
/* Not superset, quit */
- expr_free(dep2);
break;
}
/* Superset, put in submenu */
- expr_free(dep2);
next:
_menu_finalize(menu, false);
menu->parent = parent;
last_menu = menu;
}
- expr_free(basedep);
if (last_menu) {
parent->list = parent->next;
parent->next = last_menu->next;
@@ -482,46 +453,6 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep);
}
for (menu = parent->list; menu; menu = menu->next) {
- if (sym && sym_is_choice(sym) &&
- menu->sym && !sym_is_choice_value(menu->sym)) {
- current_entry = menu;
- menu->sym->flags |= SYMBOL_CHOICEVAL;
- if (!menu->prompt)
- menu_warn(menu, "choice value must have a prompt");
- for (prop = menu->sym->prop; prop; prop = prop->next) {
- if (prop->type == P_DEFAULT)
- prop_warn(prop, "defaults for choice "
- "values not supported");
- if (prop->menu == menu)
- continue;
- if (prop->type == P_PROMPT &&
- prop->menu->parent->sym != sym)
- prop_warn(prop, "choice value used outside its choice group");
- }
- /* Non-tristate choice values of tristate choices must
- * depend on the choice being set to Y. The choice
- * values' dependencies were propagated to their
- * properties above, so the change here must be re-
- * propagated.
- */
- if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
- basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
- menu->dep = expr_alloc_and(basedep, menu->dep);
- for (prop = menu->sym->prop; prop; prop = prop->next) {
- if (prop->menu != menu)
- continue;
- prop->visible.expr = expr_alloc_and(expr_copy(basedep),
- prop->visible.expr);
- }
- }
- menu_add_symbol(P_CHOICE, sym, NULL);
- prop = sym_get_choice_prop(sym);
- for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
- ;
- *ep = expr_alloc_one(E_LIST, NULL);
- (*ep)->right.sym = menu->sym;
- }
-
/*
* This code serves two purposes:
*
@@ -570,21 +501,6 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
sym_check_prop(sym);
sym->flags |= SYMBOL_WARNED;
}
-
- /*
- * For non-optional choices, add a reverse dependency (corresponding to
- * a select) of '<visibility> && m'. This prevents the user from
- * setting the choice mode to 'n' when the choice is visible.
- *
- * This would also work for non-choice symbols, but only non-optional
- * choices clear SYMBOL_OPTIONAL as of writing. Choices are implemented
- * as a type of symbol.
- */
- if (sym && !sym_is_optional(sym) && parent->prompt) {
- sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
- expr_alloc_and(parent->prompt->visible.expr,
- expr_alloc_symbol(&symbol_mod)));
- }
}
void menu_finalize(void)
@@ -592,7 +508,7 @@ void menu_finalize(void)
_menu_finalize(&rootmenu, false);
}
-bool menu_has_prompt(struct menu *menu)
+bool menu_has_prompt(const struct menu *menu)
{
if (!menu->prompt)
return false;
@@ -642,18 +558,14 @@ bool menu_is_visible(struct menu *menu)
if (!sym || sym_get_tristate_value(menu->sym) == no)
return false;
- for (child = menu->list; child; child = child->next) {
- if (menu_is_visible(child)) {
- if (sym)
- sym->flags |= SYMBOL_DEF_USER;
+ for (child = menu->list; child; child = child->next)
+ if (menu_is_visible(child))
return true;
- }
- }
return false;
}
-const char *menu_get_prompt(struct menu *menu)
+const char *menu_get_prompt(const struct menu *menu)
{
if (menu->prompt)
return menu->prompt->text;
@@ -674,13 +586,14 @@ struct menu *menu_get_parent_menu(struct menu *menu)
return menu;
}
-static void get_def_str(struct gstr *r, struct menu *menu)
+static void get_def_str(struct gstr *r, const struct menu *menu)
{
str_printf(r, "Defined at %s:%d\n",
menu->filename, menu->lineno);
}
-static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix)
+static void get_dep_str(struct gstr *r, const struct expr *expr,
+ const char *prefix)
{
if (!expr_is_yes(expr)) {
str_append(r, prefix);