aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/config/menu.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2020-04-12 00:09:52 +0200
committerJo-Philipp Wich <jo@mein.io>2020-04-12 00:10:47 +0200
commit7b1d809a8d8620032553845cf4a8819a19508687 (patch)
treee9c221f4cee621bbbfa2d02ac2870b0d3caaa4a4 /scripts/config/menu.c
parent6c16d64b2a0bb063a89225dcaabd50c00bce7aa2 (diff)
downloadupstream-7b1d809a8d8620032553845cf4a8819a19508687.tar.gz
upstream-7b1d809a8d8620032553845cf4a8819a19508687.tar.bz2
upstream-7b1d809a8d8620032553845cf4a8819a19508687.zip
Revert "build: scripts/config - update to kconfig-v5.6"
This reverts commit dcf3e63a35d05e7e5103819c0f17195bfafe9baa. The kconfig update requires further testing and refinement until it can remain in tree. Main problems are: - Recursive deps are now fatal instead of a warning - Previously legal syntax now leads to hard failures - It fails all package builds since multiple days The updated kconfig implementation needs to cope with the current status quo in the various package feeds before we can reconsider it for master. It is not desirable that single broken packages can hard-fail the entire build pipeline. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'scripts/config/menu.c')
-rw-r--r--scripts/config/menu.c451
1 files changed, 125 insertions, 326 deletions
diff --git a/scripts/config/menu.c b/scripts/config/menu.c
index 1df87dd3a5..3d89dc178d 100644
--- a/scripts/config/menu.c
+++ b/scripts/config/menu.c
@@ -1,6 +1,6 @@
-// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
*/
#include <ctype.h>
@@ -62,8 +62,13 @@ void menu_add_entry(struct symbol *sym)
menu_add_symbol(P_SYMBOL, sym, NULL);
}
+void menu_end_entry(void)
+{
+}
+
struct menu *menu_add_menu(void)
{
+ menu_end_entry();
last_entry_ptr = &current_entry->list;
return current_menu = current_entry;
}
@@ -74,23 +79,19 @@ void menu_end_menu(void)
current_menu = current_menu->parent;
}
-/*
- * Rewrites 'm' to 'm' && MODULES, so that it evaluates to 'n' when running
- * without modules
- */
-static struct expr *rewrite_m(struct expr *e)
+static struct expr *menu_check_dep(struct expr *e)
{
if (!e)
return e;
switch (e->type) {
case E_NOT:
- e->left.expr = rewrite_m(e->left.expr);
+ e->left.expr = menu_check_dep(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->left.expr = menu_check_dep(e->left.expr);
+ e->right.expr = menu_check_dep(e->right.expr);
break;
case E_SYMBOL:
/* change 'm' into 'm' && MODULES */
@@ -105,7 +106,7 @@ static struct expr *rewrite_m(struct expr *e)
void menu_add_dep(struct expr *dep)
{
- current_entry->dep = expr_alloc_and(current_entry->dep, dep);
+ current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
}
void menu_set_type(int type)
@@ -124,76 +125,61 @@ void menu_set_type(int type)
sym_type_name(sym->type), sym_type_name(type));
}
-struct property *menu_add_prop(enum prop_type type, struct expr *expr,
- struct expr *dep)
+struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep)
{
- struct property *prop;
+ struct property *prop = prop_alloc(type, current_entry->sym);
- prop = xmalloc(sizeof(*prop));
- memset(prop, 0, sizeof(*prop));
- prop->type = type;
- prop->file = current_file;
- prop->lineno = zconf_lineno();
prop->menu = current_entry;
prop->expr = expr;
- prop->visible.expr = dep;
-
- /* append property to the prop list of symbol */
- if (current_entry->sym) {
- struct property **propp;
-
- for (propp = &current_entry->sym->prop;
- *propp;
- propp = &(*propp)->next)
- ;
- *propp = prop;
- }
-
- return prop;
-}
-
-struct property *menu_add_prompt(enum prop_type type, char *prompt,
- struct expr *dep)
-{
- struct property *prop = menu_add_prop(type, NULL, dep);
+ prop->visible.expr = menu_check_dep(dep);
- if (isspace(*prompt)) {
- prop_warn(prop, "leading whitespace ignored");
- while (isspace(*prompt))
- prompt++;
- }
- if (current_entry->prompt)
- prop_warn(prop, "prompt redefined");
+ if (prompt) {
+ if (isspace(*prompt)) {
+ prop_warn(prop, "leading whitespace ignored");
+ while (isspace(*prompt))
+ prompt++;
+ }
+ if (current_entry->prompt && current_entry != &rootmenu)
+ prop_warn(prop, "prompt redefined");
- /* Apply all upper menus' visibilities to actual prompts. */
- if (type == P_PROMPT) {
- struct menu *menu = current_entry;
+ /* Apply all upper menus' visibilities to actual prompts. */
+ if(type == P_PROMPT) {
+ struct menu *menu = current_entry;
- while ((menu = menu->parent) != NULL) {
- struct expr *dup_expr;
+ 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);
+ 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);
+ prop->visible.expr
+ = expr_alloc_and(prop->visible.expr,
+ dup_expr);
+ }
}
- }
- current_entry->prompt = prop;
+ current_entry->prompt = prop;
+ }
prop->text = prompt;
return prop;
}
+struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
+{
+ return menu_add_prop(type, prompt, NULL, dep);
+}
+
void menu_add_visibility(struct expr *expr)
{
current_entry->visibility = expr_alloc_and(current_entry->visibility,
@@ -202,34 +188,39 @@ void menu_add_visibility(struct expr *expr)
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
{
- menu_add_prop(type, expr, dep);
+ menu_add_prop(type, NULL, expr, dep);
}
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
{
- menu_add_prop(type, expr_alloc_symbol(sym), dep);
+ menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
}
-void menu_add_option_modules(void)
+void menu_add_option(int token, char *arg)
{
- if (modules_sym)
- zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'",
- current_entry->sym->name, modules_sym->name);
- modules_sym = current_entry->sym;
-}
-
-void menu_add_option_defconfig_list(void)
-{
- if (!sym_defconfig_list)
- sym_defconfig_list = current_entry->sym;
- else if (sym_defconfig_list != current_entry->sym)
- zconf_error("trying to redefine defconfig symbol");
- sym_defconfig_list->flags |= SYMBOL_NO_WRITE;
-}
-
-void menu_add_option_allnoconfig_y(void)
-{
- current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
+ switch (token) {
+ case T_OPT_MODULES:
+ if (modules_sym)
+ zconf_error("symbol '%s' redefines option 'modules'"
+ " already defined by symbol '%s'",
+ current_entry->sym->name,
+ modules_sym->name
+ );
+ modules_sym = current_entry->sym;
+ break;
+ case T_OPT_DEFCONFIG_LIST:
+ if (!sym_defconfig_list)
+ sym_defconfig_list = current_entry->sym;
+ else if (sym_defconfig_list != current_entry->sym)
+ zconf_error("trying to redefine defconfig symbol");
+ break;
+ case T_OPT_ENV:
+ prop_add_env(arg);
+ break;
+ case T_OPT_ALLNOCONFIG_Y:
+ current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
+ break;
+ }
}
static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
@@ -242,8 +233,6 @@ static void sym_check_prop(struct symbol *sym)
{
struct property *prop;
struct symbol *sym2;
- char *use;
-
for (prop = sym->prop; prop; prop = prop->next) {
switch (prop->type) {
case P_DEFAULT:
@@ -261,32 +250,20 @@ static void sym_check_prop(struct symbol *sym)
"'%s': number is invalid",
sym->name);
}
- if (sym_is_choice(sym)) {
- struct property *choice_prop =
- sym_get_choice_prop(sym2);
-
- if (!choice_prop ||
- prop_get_symbol(choice_prop) != sym)
- prop_warn(prop,
- "choice default symbol '%s' is not contained in the choice",
- sym2->name);
- }
break;
case P_SELECT:
- case P_IMPLY:
- use = prop->type == P_SELECT ? "select" : "imply";
sym2 = prop_get_symbol(prop);
if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
prop_warn(prop,
- "config symbol '%s' uses %s, but is "
- "not bool or tristate", sym->name, use);
+ "config symbol '%s' uses select, but is "
+ "not boolean or tristate", sym->name);
else if (sym2->type != S_UNKNOWN &&
sym2->type != S_BOOLEAN &&
sym2->type != S_TRISTATE)
prop_warn(prop,
- "'%s' has wrong type. '%s' only "
- "accept arguments of bool and "
- "tristate type", sym2->name, use);
+ "'%s' has wrong type. 'select' only "
+ "accept arguments of boolean and "
+ "tristate type", sym2->name);
break;
case P_RANGE:
if (sym->type != S_INT && sym->type != S_HEX)
@@ -311,11 +288,6 @@ 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 */
@@ -333,167 +305,65 @@ void menu_finalize(struct menu *parent)
if (menu->sym && menu->sym->type == S_UNKNOWN)
menu_set_type(sym->type);
}
-
- /*
- * 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' */
+ } else if (parent->prompt)
+ parentdep = parent->prompt->visible.expr;
+ 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 = rewrite_m(menu->dep);
- basedep = expr_transform(basedep);
+ 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 = rewrite_m(prop->visible.expr);
- dep = expr_transform(dep);
+ 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,
expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(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)));
}
}
}
-
- if (sym && sym_is_choice(sym))
- expr_free(parentdep);
-
- /*
- * Recursively process children in the same fashion before
- * moving on
- */
for (menu = parent->list; menu; menu = menu->next)
menu_finalize(menu);
} else if (sym) {
- /*
- * Automatic submenu creation. If sym is a symbol and A, B, C,
- * ... are consecutive items (symbols, menus, ifs, etc.) that
- * all depend on sym, then the following menu structure is
- * created:
- *
- * sym
- * +-A
- * +-B
- * +-C
- * ...
- *
- * This also works recursively, giving the following structure
- * if A is a symbol and B depends on A:
- *
- * sym
- * +-A
- * | +-B
- * +-C
- * ...
- */
-
basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
basedep = expr_eliminate_dups(expr_transform(basedep));
-
- /* Examine consecutive elements after sym */
last_menu = NULL;
for (menu = parent->next; menu; menu = menu->next) {
dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
if (!expr_contains_symbol(dep, sym))
- /* No dependency, quit */
break;
if (expr_depends_symbol(dep, sym))
- /* Absolute dependency, put in submenu */
goto next;
-
- /*
- * Also consider it a dependency on sym if our
- * dependencies contain sym and are a "superset" of
- * sym's dependencies, e.g. '(sym || Q) && R' when sym
- * depends on R.
- *
- * Note that 'R' might be from an enclosing menu or if,
- * making this a more common case than it might seem.
- */
dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
dep = expr_eliminate_dups(expr_transform(dep));
dep2 = expr_copy(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);
menu->parent = parent;
last_menu = menu;
}
- expr_free(basedep);
if (last_menu) {
parent->list = parent->next;
parent->next = last_menu->next;
@@ -542,35 +412,6 @@ void menu_finalize(struct menu *parent)
*ep = expr_alloc_one(E_LIST, NULL);
(*ep)->right.sym = menu->sym;
}
-
- /*
- * This code serves two purposes:
- *
- * (1) Flattening 'if' blocks, which do not specify a submenu
- * and only add dependencies.
- *
- * (Automatic submenu creation might still create a submenu
- * from an 'if' before this code runs.)
- *
- * (2) "Undoing" any automatic submenus created earlier below
- * promptless symbols.
- *
- * Before:
- *
- * A
- * if ... (or promptless symbol)
- * +-B
- * +-C
- * D
- *
- * After:
- *
- * A
- * if ... (or promptless symbol)
- * B
- * C
- * D
- */
if (menu->list && (!menu->prompt || !menu->prompt->text)) {
for (last_menu = menu->list; ; last_menu = last_menu->next) {
last_menu->parent = parent;
@@ -595,15 +436,6 @@ void menu_finalize(struct menu *parent)
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,
@@ -711,21 +543,6 @@ const char *menu_get_help(struct menu *menu)
return "";
}
-static void get_def_str(struct gstr *r, struct menu *menu)
-{
- str_printf(r, "Defined at %s:%d\n",
- menu->file->name, menu->lineno);
-}
-
-static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix)
-{
- if (!expr_is_yes(expr)) {
- str_append(r, prefix);
- expr_gstr_print(expr, r);
- str_append(r, "\n");
- }
-}
-
static void get_prompt_str(struct gstr *r, struct property *prop,
struct list_head *head)
{
@@ -733,20 +550,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
struct menu *submenu[8], *menu, *location = NULL;
struct jump_key *jump = NULL;
- str_printf(r, " Prompt: %s\n", prop->text);
-
- get_dep_str(r, prop->menu->dep, " Depends on: ");
- /*
- * Most prompts in Linux have visibility that exactly matches their
- * dependencies. For these, we print only the dependencies to improve
- * readability. However, prompts with inline "if" expressions and
- * prompts with a parent that has a "visible if" expression have
- * differing dependencies and visibility. In these rare cases, we
- * print both.
- */
- if (!expr_eq(prop->menu->dep, prop->visible.expr))
- get_dep_str(r, prop->visible.expr, " Visible if: ");
-
+ str_printf(r, _("Prompt: %s\n"), _(prop->text));
menu = prop->menu->parent;
for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
bool accessible = menu_is_visible(menu);
@@ -779,16 +583,16 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
}
if (i > 0) {
- str_printf(r, " Location:\n");
+ str_printf(r, _(" Location:\n"));
for (j = 4; --i >= 0; j += 2) {
menu = submenu[i];
if (jump && menu == location)
jump->offset = strlen(r->s);
str_printf(r, "%*c-> %s", j, ' ',
- menu_get_prompt(menu));
+ _(menu_get_prompt(menu)));
if (menu->sym) {
str_printf(r, " (%s [=%s])", menu->sym->name ?
- menu->sym->name : "<choice>",
+ menu->sym->name : _("<choice>"),
sym_get_string_value(menu->sym));
}
str_append(r, "\n");
@@ -796,22 +600,16 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
}
}
-static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
- enum prop_type tok, const char *prefix)
+/*
+ * get property of type P_SYMBOL
+ */
+static struct property *get_symbol_prop(struct symbol *sym)
{
- bool hit = false;
- struct property *prop;
+ struct property *prop = NULL;
- for_all_properties(sym, prop, tok) {
- if (!hit) {
- str_append(r, prefix);
- hit = true;
- } else
- str_printf(r, " && ");
- expr_gstr_print(prop->expr, r);
- }
- if (hit)
- str_append(r, "\n");
+ for_all_properties(sym, prop, P_SYMBOL)
+ break;
+ return prop;
}
/*
@@ -820,6 +618,7 @@ static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
static void get_symbol_str(struct gstr *r, struct symbol *sym,
struct list_head *head)
{
+ bool hit;
struct property *prop;
if (sym && sym->name) {
@@ -835,36 +634,36 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
}
}
}
-
- /* Print the definitions with prompts before the ones without */
- for_all_properties(sym, prop, P_SYMBOL) {
- if (prop->menu->prompt) {
- get_def_str(r, prop->menu);
- get_prompt_str(r, prop->menu->prompt, head);
+ for_all_prompts(sym, prop)
+ get_prompt_str(r, prop, head);
+
+ prop = get_symbol_prop(sym);
+ if (prop) {
+ str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name,
+ prop->menu->lineno);
+ if (!expr_is_yes(prop->visible.expr)) {
+ str_append(r, _(" Depends on: "));
+ expr_gstr_print(prop->visible.expr, r);
+ str_append(r, "\n");
}
}
- for_all_properties(sym, prop, P_SYMBOL) {
- if (!prop->menu->prompt) {
- get_def_str(r, prop->menu);
- get_dep_str(r, prop->menu->dep, " Depends on: ");
- }
+ hit = false;
+ for_all_properties(sym, prop, P_SELECT) {
+ if (!hit) {
+ str_append(r, " Selects: ");
+ hit = true;
+ } else
+ str_printf(r, " && ");
+ expr_gstr_print(prop->expr, r);
}
-
- get_symbol_props_str(r, sym, P_SELECT, "Selects: ");
+ if (hit)
+ str_append(r, "\n");
if (sym->rev_dep.expr) {
- expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, "Selected by [y]:\n");
- expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, "Selected by [m]:\n");
- expr_gstr_print_revdep(sym->rev_dep.expr, r, no, "Selected by [n]:\n");
- }
-
- get_symbol_props_str(r, sym, P_IMPLY, "Implies: ");
- if (sym->implied.expr) {
- expr_gstr_print_revdep(sym->implied.expr, r, yes, "Implied by [y]:\n");
- expr_gstr_print_revdep(sym->implied.expr, r, mod, "Implied by [m]:\n");
- expr_gstr_print_revdep(sym->implied.expr, r, no, "Implied by [n]:\n");
+ str_append(r, _(" Selected by: "));
+ expr_gstr_print(sym->rev_dep.expr, r);
+ str_append(r, "\n");
}
-
str_append(r, "\n\n");
}
@@ -877,7 +676,7 @@ struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
get_symbol_str(&res, sym, head);
if (!i)
- str_append(&res, "No matches found.\n");
+ str_append(&res, _("No matches found.\n"));
return res;
}
@@ -892,7 +691,7 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
help_text = menu_get_help(menu);
}
- str_printf(help, "%s\n", help_text);
+ str_printf(help, "%s\n", _(help_text));
if (sym)
get_symbol_str(help, sym, NULL);
}