linux-next/scripts/kconfig/menu.c

770 lines
18 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
*/
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <list.h>
#include <xalloc.h>
#include "lkc.h"
#include "internal.h"
static const char nohelp_text[] = "There is no help available for this option.";
struct menu rootmenu;
static struct menu **last_entry_ptr;
/**
* 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);
fprintf(stderr, "%s:%d:warning: ", menu->filename, menu->lineno);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
static void prop_warn(const struct property *prop, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "%s:%d:warning: ", prop->filename, prop->lineno);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
void _menu_init(void)
{
current_entry = current_menu = &rootmenu;
last_entry_ptr = &rootmenu.list;
}
void menu_add_entry(struct symbol *sym)
{
struct menu *menu;
menu = xmalloc(sizeof(*menu));
memset(menu, 0, sizeof(*menu));
menu->sym = sym;
menu->parent = current_menu;
menu->filename = cur_filename;
menu->lineno = cur_lineno;
*last_entry_ptr = menu;
last_entry_ptr = &menu->next;
current_entry = menu;
if (sym)
list_add_tail(&menu->link, &sym->menus);
}
struct menu *menu_add_menu(void)
{
last_entry_ptr = &current_entry->list;
current_menu = current_entry;
return current_menu;
}
void menu_end_menu(void)
{
last_entry_ptr = &current_menu->next;
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)
{
if (!e)
return e;
switch (e->type) {
case E_NOT:
kconfig: use hash table to reuse expressions Currently, every expression in Kconfig files produces a new abstract syntax tree (AST), even if it is identical to a previously encountered one. Consider the following code: config FOO bool "FOO" depends on (A || B) && C config BAR bool "BAR" depends on (A || B) && C config BAZ bool "BAZ" depends on A || B The "depends on" lines are similar, but currently a separate AST is allocated for each one. The current data structure looks like this: FOO->dep ==> AND BAR->dep ==> AND BAZ->dep ==> OR / \ / \ / \ OR C OR C A B / \ / \ A B A B This is redundant; FOO->dep and BAR->dep have identical ASTs but different memory instances. We can optimize this; FOO->dep and BAR->dep can share the same AST, and BAZ->dep can reference its sub tree. The optimized data structure looks like this: FOO->dep, BAR->dep ==> AND / \ BAZ->dep ==> OR C / \ A B This commit introduces a hash table to keep track of allocated expressions. If an identical expression is found, it is reused. This does not necessarily result in memory savings, as menu_finalize() transforms expressions without freeing up stale ones. This will be addressed later. One optimization that can be easily implemented is caching the expression's value. Once FOO's dependency, (A || B) && C, is calculated, it can be cached, eliminating the need to recalculate it for BAR. This commit also reverts commit e983b7b17ad1 ("kconfig/menu.c: fix multiple references to expressions in menu_add_prop()"). Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-09-08 12:43:20 +00:00
e = expr_alloc_one(E_NOT, rewrite_m(e->left.expr));
break;
case E_OR:
case E_AND:
kconfig: use hash table to reuse expressions Currently, every expression in Kconfig files produces a new abstract syntax tree (AST), even if it is identical to a previously encountered one. Consider the following code: config FOO bool "FOO" depends on (A || B) && C config BAR bool "BAR" depends on (A || B) && C config BAZ bool "BAZ" depends on A || B The "depends on" lines are similar, but currently a separate AST is allocated for each one. The current data structure looks like this: FOO->dep ==> AND BAR->dep ==> AND BAZ->dep ==> OR / \ / \ / \ OR C OR C A B / \ / \ A B A B This is redundant; FOO->dep and BAR->dep have identical ASTs but different memory instances. We can optimize this; FOO->dep and BAR->dep can share the same AST, and BAZ->dep can reference its sub tree. The optimized data structure looks like this: FOO->dep, BAR->dep ==> AND / \ BAZ->dep ==> OR C / \ A B This commit introduces a hash table to keep track of allocated expressions. If an identical expression is found, it is reused. This does not necessarily result in memory savings, as menu_finalize() transforms expressions without freeing up stale ones. This will be addressed later. One optimization that can be easily implemented is caching the expression's value. Once FOO's dependency, (A || B) && C, is calculated, it can be cached, eliminating the need to recalculate it for BAR. This commit also reverts commit e983b7b17ad1 ("kconfig/menu.c: fix multiple references to expressions in menu_add_prop()"). Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-09-08 12:43:20 +00:00
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 */
if (e->left.sym == &symbol_mod)
return expr_alloc_and(e, expr_alloc_symbol(modules_sym));
break;
default:
break;
}
return e;
}
void menu_add_dep(struct expr *dep)
{
kconfig: Clean up modules handling and fix crash Kconfig currently doesn't handle 'm' appearing in a Kconfig file before the modules symbol is defined (the symbol with 'option modules'). The problem is the following code, which runs during parsing: /* change 'm' into 'm' && MODULES */ if (e->left.sym == &symbol_mod) return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); If the modules symbol has not yet been defined, modules_sym is NULL, giving an invalid expression. Here is a test file where both BEFORE_1 and BEFORE_2 trigger a segfault. If the modules symbol is removed, all symbols trigger segfaults. config BEFORE_1 def_tristate y if m if m config BEFORE_2 def_tristate y endif config MODULES def_bool y option modules config AFTER_1 def_tristate y if m if m config AFTER_2 def_tristate y endif Fix the issue by rewriting 'm' in menu_finalize() instead. This function runs after parsing and is the proper place to do it. The following existing code in conf_parse() in zconf.y ensures that the modules symbol exists at that point: if (!modules_sym) modules_sym = sym_find( "n" ); ... menu_finalize(&rootmenu); The following tests were done to ensure no functional changes for configurations that don't reference 'm' before the modules symbol: - zconfdump(stdout) was run with ARCH=x86 and ARCH=arm before and after the change and verified to produce identical output. This function prints all symbols, choices, and menus together with their properties and their dependency expressions. A rewritten 'm' appears as 'm && MODULES'. A small annoyance is that the assert(len != 0) in xfwrite() needs to be disabled in order to use zconfdump(), because it chokes on e.g. 'default ""'. - The Kconfiglib test suite was run to indirectly verify that alldefconfig, allyesconfig, allnoconfig, and all defconfigs in the kernel still generate the same final .config. - Valgrind was used to check for memory errors and (new) memory leaks. Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-05 12:01:15 +00:00
current_entry->dep = expr_alloc_and(current_entry->dep, dep);
}
void menu_set_type(int type)
{
struct symbol *sym = current_entry->sym;
if (sym->type == type)
return;
if (sym->type == S_UNKNOWN) {
sym->type = type;
return;
}
menu_warn(current_entry,
"ignoring type redefinition of '%s' from '%s' to '%s'",
sym->name ? sym->name : "<choice>",
sym_type_name(sym->type), sym_type_name(type));
}
static struct property *menu_add_prop(enum prop_type type, struct expr *expr,
struct expr *dep)
{
struct property *prop;
prop = xmalloc(sizeof(*prop));
memset(prop, 0, sizeof(*prop));
prop->type = type;
prop->filename = cur_filename;
prop->lineno = cur_lineno;
prop->menu = current_entry;
prop->expr = expr;
kconfig: Clean up modules handling and fix crash Kconfig currently doesn't handle 'm' appearing in a Kconfig file before the modules symbol is defined (the symbol with 'option modules'). The problem is the following code, which runs during parsing: /* change 'm' into 'm' && MODULES */ if (e->left.sym == &symbol_mod) return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); If the modules symbol has not yet been defined, modules_sym is NULL, giving an invalid expression. Here is a test file where both BEFORE_1 and BEFORE_2 trigger a segfault. If the modules symbol is removed, all symbols trigger segfaults. config BEFORE_1 def_tristate y if m if m config BEFORE_2 def_tristate y endif config MODULES def_bool y option modules config AFTER_1 def_tristate y if m if m config AFTER_2 def_tristate y endif Fix the issue by rewriting 'm' in menu_finalize() instead. This function runs after parsing and is the proper place to do it. The following existing code in conf_parse() in zconf.y ensures that the modules symbol exists at that point: if (!modules_sym) modules_sym = sym_find( "n" ); ... menu_finalize(&rootmenu); The following tests were done to ensure no functional changes for configurations that don't reference 'm' before the modules symbol: - zconfdump(stdout) was run with ARCH=x86 and ARCH=arm before and after the change and verified to produce identical output. This function prints all symbols, choices, and menus together with their properties and their dependency expressions. A rewritten 'm' appears as 'm && MODULES'. A small annoyance is that the assert(len != 0) in xfwrite() needs to be disabled in order to use zconfdump(), because it chokes on e.g. 'default ""'. - The Kconfiglib test suite was run to indirectly verify that alldefconfig, allyesconfig, allnoconfig, and all defconfigs in the kernel still generate the same final .config. - Valgrind was used to check for memory errors and (new) memory leaks. Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-05 12:01:15 +00:00
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, const char *prompt,
struct expr *dep)
{
struct property *prop = menu_add_prop(type, NULL, dep);
if (isspace(*prompt)) {
prop_warn(prop, "leading whitespace ignored");
while (isspace(*prompt))
prompt++;
}
if (current_entry->prompt)
prop_warn(prop, "prompt redefined");
/* Apply all upper menus' visibilities to actual prompts. */
if (type == P_PROMPT) {
struct menu *menu = current_entry;
while ((menu = menu->parent) != NULL) {
if (!menu->visibility)
continue;
prop->visible.expr = expr_alloc_and(prop->visible.expr,
kconfig: use hash table to reuse expressions Currently, every expression in Kconfig files produces a new abstract syntax tree (AST), even if it is identical to a previously encountered one. Consider the following code: config FOO bool "FOO" depends on (A || B) && C config BAR bool "BAR" depends on (A || B) && C config BAZ bool "BAZ" depends on A || B The "depends on" lines are similar, but currently a separate AST is allocated for each one. The current data structure looks like this: FOO->dep ==> AND BAR->dep ==> AND BAZ->dep ==> OR / \ / \ / \ OR C OR C A B / \ / \ A B A B This is redundant; FOO->dep and BAR->dep have identical ASTs but different memory instances. We can optimize this; FOO->dep and BAR->dep can share the same AST, and BAZ->dep can reference its sub tree. The optimized data structure looks like this: FOO->dep, BAR->dep ==> AND / \ BAZ->dep ==> OR C / \ A B This commit introduces a hash table to keep track of allocated expressions. If an identical expression is found, it is reused. This does not necessarily result in memory savings, as menu_finalize() transforms expressions without freeing up stale ones. This will be addressed later. One optimization that can be easily implemented is caching the expression's value. Once FOO's dependency, (A || B) && C, is calculated, it can be cached, eliminating the need to recalculate it for BAR. This commit also reverts commit e983b7b17ad1 ("kconfig/menu.c: fix multiple references to expressions in menu_add_prop()"). Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-09-08 12:43:20 +00:00
menu->visibility);
}
}
current_entry->prompt = prop;
prop->text = prompt;
return prop;
}
void menu_add_visibility(struct expr *expr)
{
current_entry->visibility = expr_alloc_and(current_entry->visibility,
expr);
}
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
{
menu_add_prop(type, 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);
}
static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
{
return sym2->type == S_INT || sym2->type == S_HEX ||
(sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
}
static void sym_check_prop(struct symbol *sym)
{
struct property *prop;
struct symbol *sym2;
Kconfig: Introduce the "imply" keyword The "imply" keyword is a weak version of "select" where the target config symbol can still be turned off, avoiding those pitfalls that come with the "select" keyword. This is useful e.g. with multiple drivers that want to indicate their ability to hook into a secondary subsystem while allowing the user to configure that subsystem out without also having to unset these drivers. Currently, the same effect can almost be achieved with: config DRIVER_A tristate config DRIVER_B tristate config DRIVER_C tristate config DRIVER_D tristate [...] config SUBSYSTEM_X tristate default DRIVER_A || DRIVER_B || DRIVER_C || DRIVER_D || [...] This is unwieldy to maintain especially with a large number of drivers. Furthermore, there is no easy way to restrict the choice for SUBSYSTEM_X to y or n, excluding m, when some drivers are built-in. The "select" keyword allows for excluding m, but it excludes n as well. Hence this "imply" keyword. The above becomes: config DRIVER_A tristate imply SUBSYSTEM_X config DRIVER_B tristate imply SUBSYSTEM_X [...] config SUBSYSTEM_X tristate This is much cleaner, and way more flexible than "select". SUBSYSTEM_X can still be configured out, and it can be set as a module when none of the drivers are configured in or all of them are modular. Signed-off-by: Nicolas Pitre <nico@linaro.org> Acked-by: Richard Cochran <richardcochran@gmail.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: John Stultz <john.stultz@linaro.org> Reviewed-by: Josh Triplett <josh@joshtriplett.org> Cc: Paul Bolle <pebolle@tiscali.nl> Cc: linux-kbuild@vger.kernel.org Cc: netdev@vger.kernel.org Cc: Michal Marek <mmarek@suse.com> Cc: Edward Cree <ecree@solarflare.com> Link: http://lkml.kernel.org/r/1478841010-28605-2-git-send-email-nicolas.pitre@linaro.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2016-11-11 05:10:05 +00:00
char *use;
for (prop = sym->prop; prop; prop = prop->next) {
switch (prop->type) {
case P_DEFAULT:
if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&
prop->expr->type != E_SYMBOL)
prop_warn(prop,
"default for config symbol '%s'"
" must be a single symbol", sym->name);
if (prop->expr->type != E_SYMBOL)
break;
sym2 = prop_get_symbol(prop);
if (sym->type == S_HEX || sym->type == S_INT) {
if (!menu_validate_number(sym, sym2))
prop_warn(prop,
"'%s': number is invalid",
sym->name);
}
if (sym_is_choice(sym)) {
struct menu *choice = sym_get_choice_menu(sym2);
if (!choice || choice->sym != sym)
prop_warn(prop,
"choice default symbol '%s' is not contained in the choice",
sym2->name);
}
break;
case P_SELECT:
Kconfig: Introduce the "imply" keyword The "imply" keyword is a weak version of "select" where the target config symbol can still be turned off, avoiding those pitfalls that come with the "select" keyword. This is useful e.g. with multiple drivers that want to indicate their ability to hook into a secondary subsystem while allowing the user to configure that subsystem out without also having to unset these drivers. Currently, the same effect can almost be achieved with: config DRIVER_A tristate config DRIVER_B tristate config DRIVER_C tristate config DRIVER_D tristate [...] config SUBSYSTEM_X tristate default DRIVER_A || DRIVER_B || DRIVER_C || DRIVER_D || [...] This is unwieldy to maintain especially with a large number of drivers. Furthermore, there is no easy way to restrict the choice for SUBSYSTEM_X to y or n, excluding m, when some drivers are built-in. The "select" keyword allows for excluding m, but it excludes n as well. Hence this "imply" keyword. The above becomes: config DRIVER_A tristate imply SUBSYSTEM_X config DRIVER_B tristate imply SUBSYSTEM_X [...] config SUBSYSTEM_X tristate This is much cleaner, and way more flexible than "select". SUBSYSTEM_X can still be configured out, and it can be set as a module when none of the drivers are configured in or all of them are modular. Signed-off-by: Nicolas Pitre <nico@linaro.org> Acked-by: Richard Cochran <richardcochran@gmail.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: John Stultz <john.stultz@linaro.org> Reviewed-by: Josh Triplett <josh@joshtriplett.org> Cc: Paul Bolle <pebolle@tiscali.nl> Cc: linux-kbuild@vger.kernel.org Cc: netdev@vger.kernel.org Cc: Michal Marek <mmarek@suse.com> Cc: Edward Cree <ecree@solarflare.com> Link: http://lkml.kernel.org/r/1478841010-28605-2-git-send-email-nicolas.pitre@linaro.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2016-11-11 05:10:05 +00:00
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,
Kconfig: Introduce the "imply" keyword The "imply" keyword is a weak version of "select" where the target config symbol can still be turned off, avoiding those pitfalls that come with the "select" keyword. This is useful e.g. with multiple drivers that want to indicate their ability to hook into a secondary subsystem while allowing the user to configure that subsystem out without also having to unset these drivers. Currently, the same effect can almost be achieved with: config DRIVER_A tristate config DRIVER_B tristate config DRIVER_C tristate config DRIVER_D tristate [...] config SUBSYSTEM_X tristate default DRIVER_A || DRIVER_B || DRIVER_C || DRIVER_D || [...] This is unwieldy to maintain especially with a large number of drivers. Furthermore, there is no easy way to restrict the choice for SUBSYSTEM_X to y or n, excluding m, when some drivers are built-in. The "select" keyword allows for excluding m, but it excludes n as well. Hence this "imply" keyword. The above becomes: config DRIVER_A tristate imply SUBSYSTEM_X config DRIVER_B tristate imply SUBSYSTEM_X [...] config SUBSYSTEM_X tristate This is much cleaner, and way more flexible than "select". SUBSYSTEM_X can still be configured out, and it can be set as a module when none of the drivers are configured in or all of them are modular. Signed-off-by: Nicolas Pitre <nico@linaro.org> Acked-by: Richard Cochran <richardcochran@gmail.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: John Stultz <john.stultz@linaro.org> Reviewed-by: Josh Triplett <josh@joshtriplett.org> Cc: Paul Bolle <pebolle@tiscali.nl> Cc: linux-kbuild@vger.kernel.org Cc: netdev@vger.kernel.org Cc: Michal Marek <mmarek@suse.com> Cc: Edward Cree <ecree@solarflare.com> Link: http://lkml.kernel.org/r/1478841010-28605-2-git-send-email-nicolas.pitre@linaro.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2016-11-11 05:10:05 +00:00
"config symbol '%s' uses %s, but is "
"not bool or tristate", sym->name, use);
else if (sym2->type != S_UNKNOWN &&
sym2->type != S_BOOLEAN &&
sym2->type != S_TRISTATE)
prop_warn(prop,
Kconfig: Introduce the "imply" keyword The "imply" keyword is a weak version of "select" where the target config symbol can still be turned off, avoiding those pitfalls that come with the "select" keyword. This is useful e.g. with multiple drivers that want to indicate their ability to hook into a secondary subsystem while allowing the user to configure that subsystem out without also having to unset these drivers. Currently, the same effect can almost be achieved with: config DRIVER_A tristate config DRIVER_B tristate config DRIVER_C tristate config DRIVER_D tristate [...] config SUBSYSTEM_X tristate default DRIVER_A || DRIVER_B || DRIVER_C || DRIVER_D || [...] This is unwieldy to maintain especially with a large number of drivers. Furthermore, there is no easy way to restrict the choice for SUBSYSTEM_X to y or n, excluding m, when some drivers are built-in. The "select" keyword allows for excluding m, but it excludes n as well. Hence this "imply" keyword. The above becomes: config DRIVER_A tristate imply SUBSYSTEM_X config DRIVER_B tristate imply SUBSYSTEM_X [...] config SUBSYSTEM_X tristate This is much cleaner, and way more flexible than "select". SUBSYSTEM_X can still be configured out, and it can be set as a module when none of the drivers are configured in or all of them are modular. Signed-off-by: Nicolas Pitre <nico@linaro.org> Acked-by: Richard Cochran <richardcochran@gmail.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: John Stultz <john.stultz@linaro.org> Reviewed-by: Josh Triplett <josh@joshtriplett.org> Cc: Paul Bolle <pebolle@tiscali.nl> Cc: linux-kbuild@vger.kernel.org Cc: netdev@vger.kernel.org Cc: Michal Marek <mmarek@suse.com> Cc: Edward Cree <ecree@solarflare.com> Link: http://lkml.kernel.org/r/1478841010-28605-2-git-send-email-nicolas.pitre@linaro.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2016-11-11 05:10:05 +00:00
"'%s' has wrong type. '%s' only "
"accept arguments of bool and "
Kconfig: Introduce the "imply" keyword The "imply" keyword is a weak version of "select" where the target config symbol can still be turned off, avoiding those pitfalls that come with the "select" keyword. This is useful e.g. with multiple drivers that want to indicate their ability to hook into a secondary subsystem while allowing the user to configure that subsystem out without also having to unset these drivers. Currently, the same effect can almost be achieved with: config DRIVER_A tristate config DRIVER_B tristate config DRIVER_C tristate config DRIVER_D tristate [...] config SUBSYSTEM_X tristate default DRIVER_A || DRIVER_B || DRIVER_C || DRIVER_D || [...] This is unwieldy to maintain especially with a large number of drivers. Furthermore, there is no easy way to restrict the choice for SUBSYSTEM_X to y or n, excluding m, when some drivers are built-in. The "select" keyword allows for excluding m, but it excludes n as well. Hence this "imply" keyword. The above becomes: config DRIVER_A tristate imply SUBSYSTEM_X config DRIVER_B tristate imply SUBSYSTEM_X [...] config SUBSYSTEM_X tristate This is much cleaner, and way more flexible than "select". SUBSYSTEM_X can still be configured out, and it can be set as a module when none of the drivers are configured in or all of them are modular. Signed-off-by: Nicolas Pitre <nico@linaro.org> Acked-by: Richard Cochran <richardcochran@gmail.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: John Stultz <john.stultz@linaro.org> Reviewed-by: Josh Triplett <josh@joshtriplett.org> Cc: Paul Bolle <pebolle@tiscali.nl> Cc: linux-kbuild@vger.kernel.org Cc: netdev@vger.kernel.org Cc: Michal Marek <mmarek@suse.com> Cc: Edward Cree <ecree@solarflare.com> Link: http://lkml.kernel.org/r/1478841010-28605-2-git-send-email-nicolas.pitre@linaro.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2016-11-11 05:10:05 +00:00
"tristate type", sym2->name, use);
break;
case P_RANGE:
if (sym->type != S_INT && sym->type != S_HEX)
prop_warn(prop, "range is only allowed "
"for int or hex symbols");
if (!menu_validate_number(sym, prop->expr->left.sym) ||
!menu_validate_number(sym, prop->expr->right.sym))
prop_warn(prop, "range is invalid");
break;
default:
;
}
}
}
2024-03-23 08:51:01 +00:00
static void _menu_finalize(struct menu *parent, bool inside_choice)
{
struct menu *menu, *last_menu;
struct symbol *sym;
struct property *prop;
kconfig: fix conditional prompt behavior for choice When a prompt is followed by "if <expr>", the symbol is configurable when the if-conditional evaluates to true. A typical usage is as follows: menuconfig BLOCK bool "Enable the block layer" if EXPERT default y When EXPERT=n, the prompt is hidden, but this config entry is still active, and BLOCK is set to its default value 'y'. When EXPERT=y, the prompt is shown, making BLOCK a user-configurable option. This usage is common throughout the kernel tree, but it has never worked within a choice block. [Test Code] config EXPERT bool "Allow expert users to modify more options" choice prompt "Choose" if EXPERT config A bool "A" config B bool "B" endchoice [Result] # CONFIG_EXPERT is not set When the prompt is hidden, the choice block should produce the default without asking for the user's preference. Hence, the output should be: # CONFIG_EXPERT is not set CONFIG_A=y # CONFIG_B is not set Removing unnecessary hacks fixes the issue. This commit also changes the behavior of 'select' by choice members. [Test Code 2] config MODULES def_bool y modules config DEP def_tristate m if DEP choice prompt "choose" config A bool "A" select C endchoice config B def_bool y select D endif config C tristate config D tristate The current output is as follows: CONFIG_MODULES=y CONFIG_DEP=m CONFIG_A=y CONFIG_B=y CONFIG_C=y CONFIG_D=m With this commit, the output will be changed as follows: CONFIG_MODULES=y CONFIG_DEP=m CONFIG_A=y CONFIG_B=y CONFIG_C=m CONFIG_D=m CONFIG_C will be changed to 'm' because 'select C' will inherit the dependency on DEP, which is 'm'. This change is aligned with the behavior of 'select' outside a choice block; 'select D' depends on DEP, therefore D is selected by (B && DEP). Note: With this commit, allmodconfig will set CONFIG_USB_ROLE_SWITCH to 'm' instead of 'y'. I did not see any build regression with this change. Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-26 18:22:01 +00:00
struct expr *basedep, *dep, *dep2;
sym = parent->sym;
if (parent->list) {
/*
* This menu node has children. We (recursively) process them
* and propagate parent dependencies before moving on.
*/
/* 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
*/
kconfig: Clean up modules handling and fix crash Kconfig currently doesn't handle 'm' appearing in a Kconfig file before the modules symbol is defined (the symbol with 'option modules'). The problem is the following code, which runs during parsing: /* change 'm' into 'm' && MODULES */ if (e->left.sym == &symbol_mod) return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); If the modules symbol has not yet been defined, modules_sym is NULL, giving an invalid expression. Here is a test file where both BEFORE_1 and BEFORE_2 trigger a segfault. If the modules symbol is removed, all symbols trigger segfaults. config BEFORE_1 def_tristate y if m if m config BEFORE_2 def_tristate y endif config MODULES def_bool y option modules config AFTER_1 def_tristate y if m if m config AFTER_2 def_tristate y endif Fix the issue by rewriting 'm' in menu_finalize() instead. This function runs after parsing and is the proper place to do it. The following existing code in conf_parse() in zconf.y ensures that the modules symbol exists at that point: if (!modules_sym) modules_sym = sym_find( "n" ); ... menu_finalize(&rootmenu); The following tests were done to ensure no functional changes for configurations that don't reference 'm' before the modules symbol: - zconfdump(stdout) was run with ARCH=x86 and ARCH=arm before and after the change and verified to produce identical output. This function prints all symbols, choices, and menus together with their properties and their dependency expressions. A rewritten 'm' appears as 'm && MODULES'. A small annoyance is that the assert(len != 0) in xfwrite() needs to be disabled in order to use zconfdump(), because it chokes on e.g. 'default ""'. - The Kconfiglib test suite was run to indirectly verify that alldefconfig, allyesconfig, allnoconfig, and all defconfigs in the kernel still generate the same final .config. - Valgrind was used to check for memory errors and (new) memory leaks. Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-05 12:01:15 +00:00
basedep = rewrite_m(menu->dep);
basedep = expr_transform(basedep);
kconfig: use hash table to reuse expressions Currently, every expression in Kconfig files produces a new abstract syntax tree (AST), even if it is identical to a previously encountered one. Consider the following code: config FOO bool "FOO" depends on (A || B) && C config BAR bool "BAR" depends on (A || B) && C config BAZ bool "BAZ" depends on A || B The "depends on" lines are similar, but currently a separate AST is allocated for each one. The current data structure looks like this: FOO->dep ==> AND BAR->dep ==> AND BAZ->dep ==> OR / \ / \ / \ OR C OR C A B / \ / \ A B A B This is redundant; FOO->dep and BAR->dep have identical ASTs but different memory instances. We can optimize this; FOO->dep and BAR->dep can share the same AST, and BAZ->dep can reference its sub tree. The optimized data structure looks like this: FOO->dep, BAR->dep ==> AND / \ BAZ->dep ==> OR C / \ A B This commit introduces a hash table to keep track of allocated expressions. If an identical expression is found, it is reused. This does not necessarily result in memory savings, as menu_finalize() transforms expressions without freeing up stale ones. This will be addressed later. One optimization that can be easily implemented is caching the expression's value. Once FOO's dependency, (A || B) && C, is calculated, it can be cached, eliminating the need to recalculate it for BAR. This commit also reverts commit e983b7b17ad1 ("kconfig/menu.c: fix multiple references to expressions in menu_add_prop()"). Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-09-08 12:43:20 +00:00
basedep = expr_alloc_and(parent->dep, 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
*/
kconfig: Clean up modules handling and fix crash Kconfig currently doesn't handle 'm' appearing in a Kconfig file before the modules symbol is defined (the symbol with 'option modules'). The problem is the following code, which runs during parsing: /* change 'm' into 'm' && MODULES */ if (e->left.sym == &symbol_mod) return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); If the modules symbol has not yet been defined, modules_sym is NULL, giving an invalid expression. Here is a test file where both BEFORE_1 and BEFORE_2 trigger a segfault. If the modules symbol is removed, all symbols trigger segfaults. config BEFORE_1 def_tristate y if m if m config BEFORE_2 def_tristate y endif config MODULES def_bool y option modules config AFTER_1 def_tristate y if m if m config AFTER_2 def_tristate y endif Fix the issue by rewriting 'm' in menu_finalize() instead. This function runs after parsing and is the proper place to do it. The following existing code in conf_parse() in zconf.y ensures that the modules symbol exists at that point: if (!modules_sym) modules_sym = sym_find( "n" ); ... menu_finalize(&rootmenu); The following tests were done to ensure no functional changes for configurations that don't reference 'm' before the modules symbol: - zconfdump(stdout) was run with ARCH=x86 and ARCH=arm before and after the change and verified to produce identical output. This function prints all symbols, choices, and menus together with their properties and their dependency expressions. A rewritten 'm' appears as 'm && MODULES'. A small annoyance is that the assert(len != 0) in xfwrite() needs to be disabled in order to use zconfdump(), because it chokes on e.g. 'default ""'. - The Kconfiglib test suite was run to indirectly verify that alldefconfig, allyesconfig, allnoconfig, and all defconfigs in the kernel still generate the same final .config. - Valgrind was used to check for memory errors and (new) memory leaks. Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-05 12:01:15 +00:00
dep = rewrite_m(prop->visible.expr);
dep = expr_transform(dep);
kconfig: use hash table to reuse expressions Currently, every expression in Kconfig files produces a new abstract syntax tree (AST), even if it is identical to a previously encountered one. Consider the following code: config FOO bool "FOO" depends on (A || B) && C config BAR bool "BAR" depends on (A || B) && C config BAZ bool "BAZ" depends on A || B The "depends on" lines are similar, but currently a separate AST is allocated for each one. The current data structure looks like this: FOO->dep ==> AND BAR->dep ==> AND BAZ->dep ==> OR / \ / \ / \ OR C OR C A B / \ / \ A B A B This is redundant; FOO->dep and BAR->dep have identical ASTs but different memory instances. We can optimize this; FOO->dep and BAR->dep can share the same AST, and BAZ->dep can reference its sub tree. The optimized data structure looks like this: FOO->dep, BAR->dep ==> AND / \ BAZ->dep ==> OR C / \ A B This commit introduces a hash table to keep track of allocated expressions. If an identical expression is found, it is reused. This does not necessarily result in memory savings, as menu_finalize() transforms expressions without freeing up stale ones. This will be addressed later. One optimization that can be easily implemented is caching the expression's value. Once FOO's dependency, (A || B) && C, is calculated, it can be cached, eliminating the need to recalculate it for BAR. This commit also reverts commit e983b7b17ad1 ("kconfig/menu.c: fix multiple references to expressions in menu_add_prop()"). Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-09-08 12:43:20 +00:00
dep = expr_alloc_and(basedep, dep);
dep = expr_eliminate_dups(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,
kconfig: use hash table to reuse expressions Currently, every expression in Kconfig files produces a new abstract syntax tree (AST), even if it is identical to a previously encountered one. Consider the following code: config FOO bool "FOO" depends on (A || B) && C config BAR bool "BAR" depends on (A || B) && C config BAZ bool "BAZ" depends on A || B The "depends on" lines are similar, but currently a separate AST is allocated for each one. The current data structure looks like this: FOO->dep ==> AND BAR->dep ==> AND BAZ->dep ==> OR / \ / \ / \ OR C OR C A B / \ / \ A B A B This is redundant; FOO->dep and BAR->dep have identical ASTs but different memory instances. We can optimize this; FOO->dep and BAR->dep can share the same AST, and BAZ->dep can reference its sub tree. The optimized data structure looks like this: FOO->dep, BAR->dep ==> AND / \ BAZ->dep ==> OR C / \ A B This commit introduces a hash table to keep track of allocated expressions. If an identical expression is found, it is reused. This does not necessarily result in memory savings, as menu_finalize() transforms expressions without freeing up stale ones. This will be addressed later. One optimization that can be easily implemented is caching the expression's value. Once FOO's dependency, (A || B) && C, is calculated, it can be cached, eliminating the need to recalculate it for BAR. This commit also reverts commit e983b7b17ad1 ("kconfig/menu.c: fix multiple references to expressions in menu_add_prop()"). Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-09-08 12:43:20 +00:00
expr_alloc_and(expr_alloc_symbol(menu->sym), dep));
Kconfig: Introduce the "imply" keyword The "imply" keyword is a weak version of "select" where the target config symbol can still be turned off, avoiding those pitfalls that come with the "select" keyword. This is useful e.g. with multiple drivers that want to indicate their ability to hook into a secondary subsystem while allowing the user to configure that subsystem out without also having to unset these drivers. Currently, the same effect can almost be achieved with: config DRIVER_A tristate config DRIVER_B tristate config DRIVER_C tristate config DRIVER_D tristate [...] config SUBSYSTEM_X tristate default DRIVER_A || DRIVER_B || DRIVER_C || DRIVER_D || [...] This is unwieldy to maintain especially with a large number of drivers. Furthermore, there is no easy way to restrict the choice for SUBSYSTEM_X to y or n, excluding m, when some drivers are built-in. The "select" keyword allows for excluding m, but it excludes n as well. Hence this "imply" keyword. The above becomes: config DRIVER_A tristate imply SUBSYSTEM_X config DRIVER_B tristate imply SUBSYSTEM_X [...] config SUBSYSTEM_X tristate This is much cleaner, and way more flexible than "select". SUBSYSTEM_X can still be configured out, and it can be set as a module when none of the drivers are configured in or all of them are modular. Signed-off-by: Nicolas Pitre <nico@linaro.org> Acked-by: Richard Cochran <richardcochran@gmail.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: John Stultz <john.stultz@linaro.org> Reviewed-by: Josh Triplett <josh@joshtriplett.org> Cc: Paul Bolle <pebolle@tiscali.nl> Cc: linux-kbuild@vger.kernel.org Cc: netdev@vger.kernel.org Cc: Michal Marek <mmarek@suse.com> Cc: Edward Cree <ecree@solarflare.com> Link: http://lkml.kernel.org/r/1478841010-28605-2-git-send-email-nicolas.pitre@linaro.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2016-11-11 05:10:05 +00:00
} else if (prop->type == P_IMPLY) {
struct symbol *es = prop_get_symbol(prop);
es->implied.expr = expr_alloc_or(es->implied.expr,
kconfig: use hash table to reuse expressions Currently, every expression in Kconfig files produces a new abstract syntax tree (AST), even if it is identical to a previously encountered one. Consider the following code: config FOO bool "FOO" depends on (A || B) && C config BAR bool "BAR" depends on (A || B) && C config BAZ bool "BAZ" depends on A || B The "depends on" lines are similar, but currently a separate AST is allocated for each one. The current data structure looks like this: FOO->dep ==> AND BAR->dep ==> AND BAZ->dep ==> OR / \ / \ / \ OR C OR C A B / \ / \ A B A B This is redundant; FOO->dep and BAR->dep have identical ASTs but different memory instances. We can optimize this; FOO->dep and BAR->dep can share the same AST, and BAZ->dep can reference its sub tree. The optimized data structure looks like this: FOO->dep, BAR->dep ==> AND / \ BAZ->dep ==> OR C / \ A B This commit introduces a hash table to keep track of allocated expressions. If an identical expression is found, it is reused. This does not necessarily result in memory savings, as menu_finalize() transforms expressions without freeing up stale ones. This will be addressed later. One optimization that can be easily implemented is caching the expression's value. Once FOO's dependency, (A || B) && C, is calculated, it can be cached, eliminating the need to recalculate it for BAR. This commit also reverts commit e983b7b17ad1 ("kconfig/menu.c: fix multiple references to expressions in menu_add_prop()"). Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-09-08 12:43:20 +00:00
expr_alloc_and(expr_alloc_symbol(menu->sym), dep));
}
}
}
/*
* Recursively process children in the same fashion before
* moving on
*/
for (menu = parent->list; menu; menu = menu->next)
kconfig: fix conditional prompt behavior for choice When a prompt is followed by "if <expr>", the symbol is configurable when the if-conditional evaluates to true. A typical usage is as follows: menuconfig BLOCK bool "Enable the block layer" if EXPERT default y When EXPERT=n, the prompt is hidden, but this config entry is still active, and BLOCK is set to its default value 'y'. When EXPERT=y, the prompt is shown, making BLOCK a user-configurable option. This usage is common throughout the kernel tree, but it has never worked within a choice block. [Test Code] config EXPERT bool "Allow expert users to modify more options" choice prompt "Choose" if EXPERT config A bool "A" config B bool "B" endchoice [Result] # CONFIG_EXPERT is not set When the prompt is hidden, the choice block should produce the default without asking for the user's preference. Hence, the output should be: # CONFIG_EXPERT is not set CONFIG_A=y # CONFIG_B is not set Removing unnecessary hacks fixes the issue. This commit also changes the behavior of 'select' by choice members. [Test Code 2] config MODULES def_bool y modules config DEP def_tristate m if DEP choice prompt "choose" config A bool "A" select C endchoice config B def_bool y select D endif config C tristate config D tristate The current output is as follows: CONFIG_MODULES=y CONFIG_DEP=m CONFIG_A=y CONFIG_B=y CONFIG_C=y CONFIG_D=m With this commit, the output will be changed as follows: CONFIG_MODULES=y CONFIG_DEP=m CONFIG_A=y CONFIG_B=y CONFIG_C=m CONFIG_D=m CONFIG_C will be changed to 'm' because 'select C' will inherit the dependency on DEP, which is 'm'. This change is aligned with the behavior of 'select' outside a choice block; 'select D' depends on DEP, therefore D is selected by (B && DEP). Note: With this commit, allmodconfig will set CONFIG_USB_ROLE_SWITCH to 'm' instead of 'y'. I did not see any build regression with this change. Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-26 18:22:01 +00:00
_menu_finalize(menu, sym && sym_is_choice(sym));
2024-03-23 08:51:01 +00:00
} else if (!inside_choice && 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));
kconfig: use hash table to reuse expressions Currently, every expression in Kconfig files produces a new abstract syntax tree (AST), even if it is identical to a previously encountered one. Consider the following code: config FOO bool "FOO" depends on (A || B) && C config BAR bool "BAR" depends on (A || B) && C config BAZ bool "BAZ" depends on A || B The "depends on" lines are similar, but currently a separate AST is allocated for each one. The current data structure looks like this: FOO->dep ==> AND BAR->dep ==> AND BAZ->dep ==> OR / \ / \ / \ OR C OR C A B / \ / \ A B A B This is redundant; FOO->dep and BAR->dep have identical ASTs but different memory instances. We can optimize this; FOO->dep and BAR->dep can share the same AST, and BAZ->dep can reference its sub tree. The optimized data structure looks like this: FOO->dep, BAR->dep ==> AND / \ BAZ->dep ==> OR C / \ A B This commit introduces a hash table to keep track of allocated expressions. If an identical expression is found, it is reused. This does not necessarily result in memory savings, as menu_finalize() transforms expressions without freeing up stale ones. This will be addressed later. One optimization that can be easily implemented is caching the expression's value. Once FOO's dependency, (A || B) && C, is calculated, it can be cached, eliminating the need to recalculate it for BAR. This commit also reverts commit e983b7b17ad1 ("kconfig/menu.c: fix multiple references to expressions in menu_add_prop()"). Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-09-08 12:43:20 +00:00
dep2 = basedep;
expr_eliminate_eq(&dep, &dep2);
if (!expr_is_yes(dep2)) {
/* Not superset, quit */
break;
}
/* Superset, put in submenu */
next:
2024-03-23 08:51:01 +00:00
_menu_finalize(menu, false);
menu->parent = parent;
last_menu = menu;
}
if (last_menu) {
parent->list = parent->next;
parent->next = last_menu->next;
last_menu->next = NULL;
}
sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep);
}
for (menu = parent->list; menu; menu = menu->next) {
/*
* 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;
if (!last_menu->next)
break;
}
last_menu->next = menu->next;
menu->next = menu->list;
menu->list = NULL;
}
}
if (sym && !(sym->flags & SYMBOL_WARNED)) {
if (sym->type == S_UNKNOWN)
menu_warn(parent, "config symbol defined without type");
/* Check properties connected to this symbol */
sym_check_prop(sym);
sym->flags |= SYMBOL_WARNED;
}
}
2024-03-23 08:51:01 +00:00
void menu_finalize(void)
{
_menu_finalize(&rootmenu, false);
}
bool menu_has_prompt(const struct menu *menu)
{
if (!menu->prompt)
return false;
return true;
}
/*
* Determine if a menu is empty.
* A menu is considered empty if it contains no or only
* invisible entries.
*/
bool menu_is_empty(struct menu *menu)
{
struct menu *child;
for (child = menu->list; child; child = child->next) {
if (menu_is_visible(child))
return(false);
}
return(true);
}
bool menu_is_visible(struct menu *menu)
{
struct menu *child;
struct symbol *sym;
tristate visible;
if (!menu->prompt)
return false;
if (menu->visibility) {
if (expr_calc_value(menu->visibility) == no)
return false;
}
sym = menu->sym;
if (sym) {
sym_calc_value(sym);
visible = menu->prompt->visible.tri;
} else
visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);
if (visible != no)
return true;
if (!sym || sym_get_tristate_value(menu->sym) == no)
return false;
for (child = menu->list; child; child = child->next)
if (menu_is_visible(child))
return true;
return false;
}
const char *menu_get_prompt(const struct menu *menu)
{
if (menu->prompt)
return menu->prompt->text;
else if (menu->sym)
return menu->sym->name;
return NULL;
}
struct menu *menu_get_parent_menu(struct menu *menu)
{
enum prop_type type;
for (; menu != &rootmenu; menu = menu->parent) {
type = menu->prompt ? menu->prompt->type : 0;
if (type == P_MENU)
break;
}
return menu;
}
static void get_def_str(struct gstr *r, const struct menu *menu)
kconfig: list all definitions of a symbol in help text In Kconfig, each symbol (representing a config option) can be defined in multiple places. Each definition may or may not have a prompt, which allows the option to be set via an interface like menuconfig. Each definition has a set of dependencies, which determine whether its prompt is visible and whether other pieces of the definition, like a default value, take effect. Historically, a symbol's help text (i.e. what's shown when a user presses '?' in menuconfig) contained some symbol-wide information not tied to any particular definition (e.g. what other symbols it selects) as well as the location (file name and line number) and dependencies of each prompt. Notably, the help text did not show the location or dependencies of definitions without prompts. Because this made it hard to reason about symbols that had no prompts, commit bcdedcc1afd6 ("menuconfig: print more info for symbol without prompts") changed the help text so that, instead of containing the location and dependencies of each prompt, it contained the location and dependencies of the symbol's first definition, regardless of whether or not that definition had a prompt. For symbols with only one definition, that change makes sense. However, it breaks down for symbols with multiple definitions: each definition has its own set of dependencies (the `dep` field of `struct menu`), and those dependencies are ORed together to get the symbol's dependency list (the `dir_dep` field of `struct symbol`). By printing only the dependencies of the first definition, the help text misleads users into believing that an option is more narrowly-applicable than it actually is. For an extreme example of this, we can look at the SYS_TEXT_BASE symbol in the Das U-Boot project (version 2019.10), which also uses Kconfig. (I unfortunately could not find an illustrative example in Linux.) This config option specifies the load address of the built binary and, as such, is applicable to basically every configuration possible. And yet, without this patch, its help text is as follows: Symbol: SYS_TEXT_BASE [=] Type : hex Prompt: U-Boot base address Location: -> ARM architecture Prompt: Text Base Location: -> Boot images Defined at arch/arm/mach-aspeed/Kconfig:9 Depends on: ARM [=n] && ARCH_ASPEED [=n] The help text indicates that the option is applicable only for a specific unselected architecture (aspeed), because that architecture's promptless definition (which just sets a default value), happens to be the first one seen. No definition or dependency information is printed for either of the two prompts listed. Because source locations and dependencies are fundamentally properties of definitions and not of symbols, we should treat them as such. This patch brings back the pre-bcdedcc1afd6 behavior for definitions with prompts but also separately prints the location and dependencies of those without prompts, solving the original problem in a different way. With this change, our SYS_TEXT_BASE example becomes Symbol: SYS_TEXT_BASE [=] Type : hex Defined at arch/arm/mach-stm32mp/Kconfig:83 Prompt: U-Boot base address Depends on: ARM [=n] && ARCH_STM32MP [=n] Location: -> ARM architecture Defined at Kconfig:532 Prompt: Text Base Depends on: !NIOS2 [=n] && !XTENSA [=n] && !EFI_APP [=n] Location: -> Boot images Defined at arch/arm/mach-aspeed/Kconfig:9 Depends on: ARM [=n] && ARCH_ASPEED [=n] Defined at arch/arm/mach-socfpga/Kconfig:25 Depends on: ARM [=n] && ARCH_SOCFPGA [=n] <snip> Defined at board/sifive/fu540/Kconfig:15 Depends on: RISCV [=n] && TARGET_SIFIVE_FU540 [=n] which is a much more accurate representation. Note that there is one notable difference between what gets printed for prompts after this change and what got printed before bcdedcc1afd6: the "Depends on" line now accurately represents the prompt's dependencies instead of conflating those with the prompt's visibility (which can include extra conditions). See the patch later in this series titled "kconfig: distinguish between dependencies and visibility in help text" for more details and better handling of that nuance. Signed-off-by: Thomas Hebb <tommyhebb@gmail.com> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2019-12-17 16:15:43 +00:00
{
str_printf(r, "Defined at %s:%d\n",
menu->filename, menu->lineno);
kconfig: list all definitions of a symbol in help text In Kconfig, each symbol (representing a config option) can be defined in multiple places. Each definition may or may not have a prompt, which allows the option to be set via an interface like menuconfig. Each definition has a set of dependencies, which determine whether its prompt is visible and whether other pieces of the definition, like a default value, take effect. Historically, a symbol's help text (i.e. what's shown when a user presses '?' in menuconfig) contained some symbol-wide information not tied to any particular definition (e.g. what other symbols it selects) as well as the location (file name and line number) and dependencies of each prompt. Notably, the help text did not show the location or dependencies of definitions without prompts. Because this made it hard to reason about symbols that had no prompts, commit bcdedcc1afd6 ("menuconfig: print more info for symbol without prompts") changed the help text so that, instead of containing the location and dependencies of each prompt, it contained the location and dependencies of the symbol's first definition, regardless of whether or not that definition had a prompt. For symbols with only one definition, that change makes sense. However, it breaks down for symbols with multiple definitions: each definition has its own set of dependencies (the `dep` field of `struct menu`), and those dependencies are ORed together to get the symbol's dependency list (the `dir_dep` field of `struct symbol`). By printing only the dependencies of the first definition, the help text misleads users into believing that an option is more narrowly-applicable than it actually is. For an extreme example of this, we can look at the SYS_TEXT_BASE symbol in the Das U-Boot project (version 2019.10), which also uses Kconfig. (I unfortunately could not find an illustrative example in Linux.) This config option specifies the load address of the built binary and, as such, is applicable to basically every configuration possible. And yet, without this patch, its help text is as follows: Symbol: SYS_TEXT_BASE [=] Type : hex Prompt: U-Boot base address Location: -> ARM architecture Prompt: Text Base Location: -> Boot images Defined at arch/arm/mach-aspeed/Kconfig:9 Depends on: ARM [=n] && ARCH_ASPEED [=n] The help text indicates that the option is applicable only for a specific unselected architecture (aspeed), because that architecture's promptless definition (which just sets a default value), happens to be the first one seen. No definition or dependency information is printed for either of the two prompts listed. Because source locations and dependencies are fundamentally properties of definitions and not of symbols, we should treat them as such. This patch brings back the pre-bcdedcc1afd6 behavior for definitions with prompts but also separately prints the location and dependencies of those without prompts, solving the original problem in a different way. With this change, our SYS_TEXT_BASE example becomes Symbol: SYS_TEXT_BASE [=] Type : hex Defined at arch/arm/mach-stm32mp/Kconfig:83 Prompt: U-Boot base address Depends on: ARM [=n] && ARCH_STM32MP [=n] Location: -> ARM architecture Defined at Kconfig:532 Prompt: Text Base Depends on: !NIOS2 [=n] && !XTENSA [=n] && !EFI_APP [=n] Location: -> Boot images Defined at arch/arm/mach-aspeed/Kconfig:9 Depends on: ARM [=n] && ARCH_ASPEED [=n] Defined at arch/arm/mach-socfpga/Kconfig:25 Depends on: ARM [=n] && ARCH_SOCFPGA [=n] <snip> Defined at board/sifive/fu540/Kconfig:15 Depends on: RISCV [=n] && TARGET_SIFIVE_FU540 [=n] which is a much more accurate representation. Note that there is one notable difference between what gets printed for prompts after this change and what got printed before bcdedcc1afd6: the "Depends on" line now accurately represents the prompt's dependencies instead of conflating those with the prompt's visibility (which can include extra conditions). See the patch later in this series titled "kconfig: distinguish between dependencies and visibility in help text" for more details and better handling of that nuance. Signed-off-by: Thomas Hebb <tommyhebb@gmail.com> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2019-12-17 16:15:43 +00:00
}
static void get_dep_str(struct gstr *r, const struct expr *expr,
const char *prefix)
kconfig: list all definitions of a symbol in help text In Kconfig, each symbol (representing a config option) can be defined in multiple places. Each definition may or may not have a prompt, which allows the option to be set via an interface like menuconfig. Each definition has a set of dependencies, which determine whether its prompt is visible and whether other pieces of the definition, like a default value, take effect. Historically, a symbol's help text (i.e. what's shown when a user presses '?' in menuconfig) contained some symbol-wide information not tied to any particular definition (e.g. what other symbols it selects) as well as the location (file name and line number) and dependencies of each prompt. Notably, the help text did not show the location or dependencies of definitions without prompts. Because this made it hard to reason about symbols that had no prompts, commit bcdedcc1afd6 ("menuconfig: print more info for symbol without prompts") changed the help text so that, instead of containing the location and dependencies of each prompt, it contained the location and dependencies of the symbol's first definition, regardless of whether or not that definition had a prompt. For symbols with only one definition, that change makes sense. However, it breaks down for symbols with multiple definitions: each definition has its own set of dependencies (the `dep` field of `struct menu`), and those dependencies are ORed together to get the symbol's dependency list (the `dir_dep` field of `struct symbol`). By printing only the dependencies of the first definition, the help text misleads users into believing that an option is more narrowly-applicable than it actually is. For an extreme example of this, we can look at the SYS_TEXT_BASE symbol in the Das U-Boot project (version 2019.10), which also uses Kconfig. (I unfortunately could not find an illustrative example in Linux.) This config option specifies the load address of the built binary and, as such, is applicable to basically every configuration possible. And yet, without this patch, its help text is as follows: Symbol: SYS_TEXT_BASE [=] Type : hex Prompt: U-Boot base address Location: -> ARM architecture Prompt: Text Base Location: -> Boot images Defined at arch/arm/mach-aspeed/Kconfig:9 Depends on: ARM [=n] && ARCH_ASPEED [=n] The help text indicates that the option is applicable only for a specific unselected architecture (aspeed), because that architecture's promptless definition (which just sets a default value), happens to be the first one seen. No definition or dependency information is printed for either of the two prompts listed. Because source locations and dependencies are fundamentally properties of definitions and not of symbols, we should treat them as such. This patch brings back the pre-bcdedcc1afd6 behavior for definitions with prompts but also separately prints the location and dependencies of those without prompts, solving the original problem in a different way. With this change, our SYS_TEXT_BASE example becomes Symbol: SYS_TEXT_BASE [=] Type : hex Defined at arch/arm/mach-stm32mp/Kconfig:83 Prompt: U-Boot base address Depends on: ARM [=n] && ARCH_STM32MP [=n] Location: -> ARM architecture Defined at Kconfig:532 Prompt: Text Base Depends on: !NIOS2 [=n] && !XTENSA [=n] && !EFI_APP [=n] Location: -> Boot images Defined at arch/arm/mach-aspeed/Kconfig:9 Depends on: ARM [=n] && ARCH_ASPEED [=n] Defined at arch/arm/mach-socfpga/Kconfig:25 Depends on: ARM [=n] && ARCH_SOCFPGA [=n] <snip> Defined at board/sifive/fu540/Kconfig:15 Depends on: RISCV [=n] && TARGET_SIFIVE_FU540 [=n] which is a much more accurate representation. Note that there is one notable difference between what gets printed for prompts after this change and what got printed before bcdedcc1afd6: the "Depends on" line now accurately represents the prompt's dependencies instead of conflating those with the prompt's visibility (which can include extra conditions). See the patch later in this series titled "kconfig: distinguish between dependencies and visibility in help text" for more details and better handling of that nuance. Signed-off-by: Thomas Hebb <tommyhebb@gmail.com> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2019-12-17 16:15:43 +00:00
{
if (!expr_is_yes(expr)) {
str_append(r, prefix);
expr_gstr_print(expr, r);
str_append(r, "\n");
}
}
int __attribute__((weak)) get_jump_key_char(void)
{
return -1;
}
static void get_prompt_str(struct gstr *r, struct property *prop,
struct list_head *head)
{
int i, j;
struct menu *submenu[8], *menu, *location = NULL;
struct jump_key *jump = NULL;
kconfig: list all definitions of a symbol in help text In Kconfig, each symbol (representing a config option) can be defined in multiple places. Each definition may or may not have a prompt, which allows the option to be set via an interface like menuconfig. Each definition has a set of dependencies, which determine whether its prompt is visible and whether other pieces of the definition, like a default value, take effect. Historically, a symbol's help text (i.e. what's shown when a user presses '?' in menuconfig) contained some symbol-wide information not tied to any particular definition (e.g. what other symbols it selects) as well as the location (file name and line number) and dependencies of each prompt. Notably, the help text did not show the location or dependencies of definitions without prompts. Because this made it hard to reason about symbols that had no prompts, commit bcdedcc1afd6 ("menuconfig: print more info for symbol without prompts") changed the help text so that, instead of containing the location and dependencies of each prompt, it contained the location and dependencies of the symbol's first definition, regardless of whether or not that definition had a prompt. For symbols with only one definition, that change makes sense. However, it breaks down for symbols with multiple definitions: each definition has its own set of dependencies (the `dep` field of `struct menu`), and those dependencies are ORed together to get the symbol's dependency list (the `dir_dep` field of `struct symbol`). By printing only the dependencies of the first definition, the help text misleads users into believing that an option is more narrowly-applicable than it actually is. For an extreme example of this, we can look at the SYS_TEXT_BASE symbol in the Das U-Boot project (version 2019.10), which also uses Kconfig. (I unfortunately could not find an illustrative example in Linux.) This config option specifies the load address of the built binary and, as such, is applicable to basically every configuration possible. And yet, without this patch, its help text is as follows: Symbol: SYS_TEXT_BASE [=] Type : hex Prompt: U-Boot base address Location: -> ARM architecture Prompt: Text Base Location: -> Boot images Defined at arch/arm/mach-aspeed/Kconfig:9 Depends on: ARM [=n] && ARCH_ASPEED [=n] The help text indicates that the option is applicable only for a specific unselected architecture (aspeed), because that architecture's promptless definition (which just sets a default value), happens to be the first one seen. No definition or dependency information is printed for either of the two prompts listed. Because source locations and dependencies are fundamentally properties of definitions and not of symbols, we should treat them as such. This patch brings back the pre-bcdedcc1afd6 behavior for definitions with prompts but also separately prints the location and dependencies of those without prompts, solving the original problem in a different way. With this change, our SYS_TEXT_BASE example becomes Symbol: SYS_TEXT_BASE [=] Type : hex Defined at arch/arm/mach-stm32mp/Kconfig:83 Prompt: U-Boot base address Depends on: ARM [=n] && ARCH_STM32MP [=n] Location: -> ARM architecture Defined at Kconfig:532 Prompt: Text Base Depends on: !NIOS2 [=n] && !XTENSA [=n] && !EFI_APP [=n] Location: -> Boot images Defined at arch/arm/mach-aspeed/Kconfig:9 Depends on: ARM [=n] && ARCH_ASPEED [=n] Defined at arch/arm/mach-socfpga/Kconfig:25 Depends on: ARM [=n] && ARCH_SOCFPGA [=n] <snip> Defined at board/sifive/fu540/Kconfig:15 Depends on: RISCV [=n] && TARGET_SIFIVE_FU540 [=n] which is a much more accurate representation. Note that there is one notable difference between what gets printed for prompts after this change and what got printed before bcdedcc1afd6: the "Depends on" line now accurately represents the prompt's dependencies instead of conflating those with the prompt's visibility (which can include extra conditions). See the patch later in this series titled "kconfig: distinguish between dependencies and visibility in help text" for more details and better handling of that nuance. Signed-off-by: Thomas Hebb <tommyhebb@gmail.com> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2019-12-17 16:15:43 +00:00
str_printf(r, " Prompt: %s\n", prop->text);
get_dep_str(r, prop->menu->dep, " Depends on: ");
kconfig: distinguish between dependencies and visibility in help text Kconfig makes a distinction between dependencies (defined by "depends on" expressions and enclosing "if" blocks) and visibility (which includes all dependencies, but also includes inline "if" expressions of individual properties as well as, for prompts, "visible if" expressions of enclosing menus). Before commit bcdedcc1afd6 ("menuconfig: print more info for symbol without prompts"), the "Depends on" lines of a symbol's help text indicated the visibility of the prompt property they appeared under. After bcdedcc1afd, there was always only a single "Depends on" line, which indicated the visibility of the first P_SYMBOL property of the symbol. Since P_SYMBOLs never have inline if expressions, this was in effect the same as the dependencies of the menu item that the P_SYMBOL was attached to. Neither of these situations accurately conveyed the dependencies of a symbol--the first because it was actually the visibility, and the second because it only showed the dependencies from a single definition. With this series, we are back to printing separate dependencies for each definition, but we print the actual dependencies (rather than the visibility) in the "Depends on" line. However, it can still be useful to know the visibility of a prompt, so this patch adds a "Visible if" line that shows the visibility only if the visibility is different from the dependencies (which it isn't for most prompts in Linux). Before: Symbol: THUMB2_KERNEL [=n] Type : bool Defined at arch/arm/Kconfig:1417 Prompt: Compile the kernel in Thumb-2 mode Depends on: (CPU_V7 [=y] || CPU_V7M [=n]) && !CPU_V6 [=n] && !CPU_V6K [=n] Location: -> Kernel Features Selects: ARM_UNWIND [=n] After: Symbol: THUMB2_KERNEL [=n] Type : bool Defined at arch/arm/Kconfig:1417 Prompt: Compile the kernel in Thumb-2 mode Depends on: (CPU_V7 [=y] || CPU_V7M [=n]) && !CPU_V6 [=n] && !CPU_V6K [=n] Visible if: (CPU_V7 [=y] || CPU_V7M [=n]) && !CPU_V6 [=n] && !CPU_V6K [=n] && !CPU_THUMBONLY [=n] Location: -> Kernel Features Selects: ARM_UNWIND [=n] Signed-off-by: Thomas Hebb <tommyhebb@gmail.com> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2019-12-17 16:15:44 +00:00
/*
* 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: ");
menu = prop->menu;
for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
submenu[i++] = menu;
if (location == NULL && menu_is_visible(menu))
location = menu;
}
if (head && location) {
jump = xmalloc(sizeof(struct jump_key));
jump->target = location;
list_add_tail(&jump->entries, head);
}
str_printf(r, " Location:\n");
for (j = 0; --i >= 0; j++) {
int jk = -1;
int indent = 2 * j + 4;
menu = submenu[i];
if (jump && menu == location) {
jump->offset = strlen(r->s);
jk = get_jump_key_char();
}
if (jk >= 0) {
str_printf(r, "(%c)", jk);
indent -= 3;
}
str_printf(r, "%*c-> %s", indent, ' ', menu_get_prompt(menu));
if (menu->sym) {
str_printf(r, " (%s [=%s])", menu->sym->name ?
menu->sym->name : "<choice>",
sym_get_string_value(menu->sym));
}
str_append(r, "\n");
}
}
Kconfig: Introduce the "imply" keyword The "imply" keyword is a weak version of "select" where the target config symbol can still be turned off, avoiding those pitfalls that come with the "select" keyword. This is useful e.g. with multiple drivers that want to indicate their ability to hook into a secondary subsystem while allowing the user to configure that subsystem out without also having to unset these drivers. Currently, the same effect can almost be achieved with: config DRIVER_A tristate config DRIVER_B tristate config DRIVER_C tristate config DRIVER_D tristate [...] config SUBSYSTEM_X tristate default DRIVER_A || DRIVER_B || DRIVER_C || DRIVER_D || [...] This is unwieldy to maintain especially with a large number of drivers. Furthermore, there is no easy way to restrict the choice for SUBSYSTEM_X to y or n, excluding m, when some drivers are built-in. The "select" keyword allows for excluding m, but it excludes n as well. Hence this "imply" keyword. The above becomes: config DRIVER_A tristate imply SUBSYSTEM_X config DRIVER_B tristate imply SUBSYSTEM_X [...] config SUBSYSTEM_X tristate This is much cleaner, and way more flexible than "select". SUBSYSTEM_X can still be configured out, and it can be set as a module when none of the drivers are configured in or all of them are modular. Signed-off-by: Nicolas Pitre <nico@linaro.org> Acked-by: Richard Cochran <richardcochran@gmail.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: John Stultz <john.stultz@linaro.org> Reviewed-by: Josh Triplett <josh@joshtriplett.org> Cc: Paul Bolle <pebolle@tiscali.nl> Cc: linux-kbuild@vger.kernel.org Cc: netdev@vger.kernel.org Cc: Michal Marek <mmarek@suse.com> Cc: Edward Cree <ecree@solarflare.com> Link: http://lkml.kernel.org/r/1478841010-28605-2-git-send-email-nicolas.pitre@linaro.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2016-11-11 05:10:05 +00:00
static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
enum prop_type tok, const char *prefix)
{
bool hit = false;
struct property *prop;
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");
}
/*
* head is optional and may be NULL
*/
static void get_symbol_str(struct gstr *r, struct symbol *sym,
struct list_head *head)
{
struct property *prop;
struct menu *menu;
if (sym && sym->name) {
str_printf(r, "Symbol: %s [=%s]\n", sym->name,
sym_get_string_value(sym));
str_printf(r, "Type : %s\n", sym_type_name(sym->type));
if (sym->type == S_INT || sym->type == S_HEX) {
prop = sym_get_range_prop(sym);
if (prop) {
str_printf(r, "Range : ");
expr_gstr_print(prop->expr, r);
str_append(r, "\n");
}
}
}
kconfig: list all definitions of a symbol in help text In Kconfig, each symbol (representing a config option) can be defined in multiple places. Each definition may or may not have a prompt, which allows the option to be set via an interface like menuconfig. Each definition has a set of dependencies, which determine whether its prompt is visible and whether other pieces of the definition, like a default value, take effect. Historically, a symbol's help text (i.e. what's shown when a user presses '?' in menuconfig) contained some symbol-wide information not tied to any particular definition (e.g. what other symbols it selects) as well as the location (file name and line number) and dependencies of each prompt. Notably, the help text did not show the location or dependencies of definitions without prompts. Because this made it hard to reason about symbols that had no prompts, commit bcdedcc1afd6 ("menuconfig: print more info for symbol without prompts") changed the help text so that, instead of containing the location and dependencies of each prompt, it contained the location and dependencies of the symbol's first definition, regardless of whether or not that definition had a prompt. For symbols with only one definition, that change makes sense. However, it breaks down for symbols with multiple definitions: each definition has its own set of dependencies (the `dep` field of `struct menu`), and those dependencies are ORed together to get the symbol's dependency list (the `dir_dep` field of `struct symbol`). By printing only the dependencies of the first definition, the help text misleads users into believing that an option is more narrowly-applicable than it actually is. For an extreme example of this, we can look at the SYS_TEXT_BASE symbol in the Das U-Boot project (version 2019.10), which also uses Kconfig. (I unfortunately could not find an illustrative example in Linux.) This config option specifies the load address of the built binary and, as such, is applicable to basically every configuration possible. And yet, without this patch, its help text is as follows: Symbol: SYS_TEXT_BASE [=] Type : hex Prompt: U-Boot base address Location: -> ARM architecture Prompt: Text Base Location: -> Boot images Defined at arch/arm/mach-aspeed/Kconfig:9 Depends on: ARM [=n] && ARCH_ASPEED [=n] The help text indicates that the option is applicable only for a specific unselected architecture (aspeed), because that architecture's promptless definition (which just sets a default value), happens to be the first one seen. No definition or dependency information is printed for either of the two prompts listed. Because source locations and dependencies are fundamentally properties of definitions and not of symbols, we should treat them as such. This patch brings back the pre-bcdedcc1afd6 behavior for definitions with prompts but also separately prints the location and dependencies of those without prompts, solving the original problem in a different way. With this change, our SYS_TEXT_BASE example becomes Symbol: SYS_TEXT_BASE [=] Type : hex Defined at arch/arm/mach-stm32mp/Kconfig:83 Prompt: U-Boot base address Depends on: ARM [=n] && ARCH_STM32MP [=n] Location: -> ARM architecture Defined at Kconfig:532 Prompt: Text Base Depends on: !NIOS2 [=n] && !XTENSA [=n] && !EFI_APP [=n] Location: -> Boot images Defined at arch/arm/mach-aspeed/Kconfig:9 Depends on: ARM [=n] && ARCH_ASPEED [=n] Defined at arch/arm/mach-socfpga/Kconfig:25 Depends on: ARM [=n] && ARCH_SOCFPGA [=n] <snip> Defined at board/sifive/fu540/Kconfig:15 Depends on: RISCV [=n] && TARGET_SIFIVE_FU540 [=n] which is a much more accurate representation. Note that there is one notable difference between what gets printed for prompts after this change and what got printed before bcdedcc1afd6: the "Depends on" line now accurately represents the prompt's dependencies instead of conflating those with the prompt's visibility (which can include extra conditions). See the patch later in this series titled "kconfig: distinguish between dependencies and visibility in help text" for more details and better handling of that nuance. Signed-off-by: Thomas Hebb <tommyhebb@gmail.com> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2019-12-17 16:15:43 +00:00
/* Print the definitions with prompts before the ones without */
list_for_each_entry(menu, &sym->menus, link) {
if (menu->prompt) {
get_def_str(r, menu);
get_prompt_str(r, menu->prompt, head);
kconfig: list all definitions of a symbol in help text In Kconfig, each symbol (representing a config option) can be defined in multiple places. Each definition may or may not have a prompt, which allows the option to be set via an interface like menuconfig. Each definition has a set of dependencies, which determine whether its prompt is visible and whether other pieces of the definition, like a default value, take effect. Historically, a symbol's help text (i.e. what's shown when a user presses '?' in menuconfig) contained some symbol-wide information not tied to any particular definition (e.g. what other symbols it selects) as well as the location (file name and line number) and dependencies of each prompt. Notably, the help text did not show the location or dependencies of definitions without prompts. Because this made it hard to reason about symbols that had no prompts, commit bcdedcc1afd6 ("menuconfig: print more info for symbol without prompts") changed the help text so that, instead of containing the location and dependencies of each prompt, it contained the location and dependencies of the symbol's first definition, regardless of whether or not that definition had a prompt. For symbols with only one definition, that change makes sense. However, it breaks down for symbols with multiple definitions: each definition has its own set of dependencies (the `dep` field of `struct menu`), and those dependencies are ORed together to get the symbol's dependency list (the `dir_dep` field of `struct symbol`). By printing only the dependencies of the first definition, the help text misleads users into believing that an option is more narrowly-applicable than it actually is. For an extreme example of this, we can look at the SYS_TEXT_BASE symbol in the Das U-Boot project (version 2019.10), which also uses Kconfig. (I unfortunately could not find an illustrative example in Linux.) This config option specifies the load address of the built binary and, as such, is applicable to basically every configuration possible. And yet, without this patch, its help text is as follows: Symbol: SYS_TEXT_BASE [=] Type : hex Prompt: U-Boot base address Location: -> ARM architecture Prompt: Text Base Location: -> Boot images Defined at arch/arm/mach-aspeed/Kconfig:9 Depends on: ARM [=n] && ARCH_ASPEED [=n] The help text indicates that the option is applicable only for a specific unselected architecture (aspeed), because that architecture's promptless definition (which just sets a default value), happens to be the first one seen. No definition or dependency information is printed for either of the two prompts listed. Because source locations and dependencies are fundamentally properties of definitions and not of symbols, we should treat them as such. This patch brings back the pre-bcdedcc1afd6 behavior for definitions with prompts but also separately prints the location and dependencies of those without prompts, solving the original problem in a different way. With this change, our SYS_TEXT_BASE example becomes Symbol: SYS_TEXT_BASE [=] Type : hex Defined at arch/arm/mach-stm32mp/Kconfig:83 Prompt: U-Boot base address Depends on: ARM [=n] && ARCH_STM32MP [=n] Location: -> ARM architecture Defined at Kconfig:532 Prompt: Text Base Depends on: !NIOS2 [=n] && !XTENSA [=n] && !EFI_APP [=n] Location: -> Boot images Defined at arch/arm/mach-aspeed/Kconfig:9 Depends on: ARM [=n] && ARCH_ASPEED [=n] Defined at arch/arm/mach-socfpga/Kconfig:25 Depends on: ARM [=n] && ARCH_SOCFPGA [=n] <snip> Defined at board/sifive/fu540/Kconfig:15 Depends on: RISCV [=n] && TARGET_SIFIVE_FU540 [=n] which is a much more accurate representation. Note that there is one notable difference between what gets printed for prompts after this change and what got printed before bcdedcc1afd6: the "Depends on" line now accurately represents the prompt's dependencies instead of conflating those with the prompt's visibility (which can include extra conditions). See the patch later in this series titled "kconfig: distinguish between dependencies and visibility in help text" for more details and better handling of that nuance. Signed-off-by: Thomas Hebb <tommyhebb@gmail.com> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2019-12-17 16:15:43 +00:00
}
}
list_for_each_entry(menu, &sym->menus, link) {
if (!menu->prompt) {
get_def_str(r, menu);
get_dep_str(r, menu->dep, " Depends on: ");
}
}
get_symbol_props_str(r, sym, P_SELECT, "Selects: ");
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");
}
Kconfig: Introduce the "imply" keyword The "imply" keyword is a weak version of "select" where the target config symbol can still be turned off, avoiding those pitfalls that come with the "select" keyword. This is useful e.g. with multiple drivers that want to indicate their ability to hook into a secondary subsystem while allowing the user to configure that subsystem out without also having to unset these drivers. Currently, the same effect can almost be achieved with: config DRIVER_A tristate config DRIVER_B tristate config DRIVER_C tristate config DRIVER_D tristate [...] config SUBSYSTEM_X tristate default DRIVER_A || DRIVER_B || DRIVER_C || DRIVER_D || [...] This is unwieldy to maintain especially with a large number of drivers. Furthermore, there is no easy way to restrict the choice for SUBSYSTEM_X to y or n, excluding m, when some drivers are built-in. The "select" keyword allows for excluding m, but it excludes n as well. Hence this "imply" keyword. The above becomes: config DRIVER_A tristate imply SUBSYSTEM_X config DRIVER_B tristate imply SUBSYSTEM_X [...] config SUBSYSTEM_X tristate This is much cleaner, and way more flexible than "select". SUBSYSTEM_X can still be configured out, and it can be set as a module when none of the drivers are configured in or all of them are modular. Signed-off-by: Nicolas Pitre <nico@linaro.org> Acked-by: Richard Cochran <richardcochran@gmail.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: John Stultz <john.stultz@linaro.org> Reviewed-by: Josh Triplett <josh@joshtriplett.org> Cc: Paul Bolle <pebolle@tiscali.nl> Cc: linux-kbuild@vger.kernel.org Cc: netdev@vger.kernel.org Cc: Michal Marek <mmarek@suse.com> Cc: Edward Cree <ecree@solarflare.com> Link: http://lkml.kernel.org/r/1478841010-28605-2-git-send-email-nicolas.pitre@linaro.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2016-11-11 05:10:05 +00:00
get_symbol_props_str(r, sym, P_IMPLY, "Implies: ");
Kconfig: Introduce the "imply" keyword The "imply" keyword is a weak version of "select" where the target config symbol can still be turned off, avoiding those pitfalls that come with the "select" keyword. This is useful e.g. with multiple drivers that want to indicate their ability to hook into a secondary subsystem while allowing the user to configure that subsystem out without also having to unset these drivers. Currently, the same effect can almost be achieved with: config DRIVER_A tristate config DRIVER_B tristate config DRIVER_C tristate config DRIVER_D tristate [...] config SUBSYSTEM_X tristate default DRIVER_A || DRIVER_B || DRIVER_C || DRIVER_D || [...] This is unwieldy to maintain especially with a large number of drivers. Furthermore, there is no easy way to restrict the choice for SUBSYSTEM_X to y or n, excluding m, when some drivers are built-in. The "select" keyword allows for excluding m, but it excludes n as well. Hence this "imply" keyword. The above becomes: config DRIVER_A tristate imply SUBSYSTEM_X config DRIVER_B tristate imply SUBSYSTEM_X [...] config SUBSYSTEM_X tristate This is much cleaner, and way more flexible than "select". SUBSYSTEM_X can still be configured out, and it can be set as a module when none of the drivers are configured in or all of them are modular. Signed-off-by: Nicolas Pitre <nico@linaro.org> Acked-by: Richard Cochran <richardcochran@gmail.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: John Stultz <john.stultz@linaro.org> Reviewed-by: Josh Triplett <josh@joshtriplett.org> Cc: Paul Bolle <pebolle@tiscali.nl> Cc: linux-kbuild@vger.kernel.org Cc: netdev@vger.kernel.org Cc: Michal Marek <mmarek@suse.com> Cc: Edward Cree <ecree@solarflare.com> Link: http://lkml.kernel.org/r/1478841010-28605-2-git-send-email-nicolas.pitre@linaro.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2016-11-11 05:10:05 +00:00
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");
Kconfig: Introduce the "imply" keyword The "imply" keyword is a weak version of "select" where the target config symbol can still be turned off, avoiding those pitfalls that come with the "select" keyword. This is useful e.g. with multiple drivers that want to indicate their ability to hook into a secondary subsystem while allowing the user to configure that subsystem out without also having to unset these drivers. Currently, the same effect can almost be achieved with: config DRIVER_A tristate config DRIVER_B tristate config DRIVER_C tristate config DRIVER_D tristate [...] config SUBSYSTEM_X tristate default DRIVER_A || DRIVER_B || DRIVER_C || DRIVER_D || [...] This is unwieldy to maintain especially with a large number of drivers. Furthermore, there is no easy way to restrict the choice for SUBSYSTEM_X to y or n, excluding m, when some drivers are built-in. The "select" keyword allows for excluding m, but it excludes n as well. Hence this "imply" keyword. The above becomes: config DRIVER_A tristate imply SUBSYSTEM_X config DRIVER_B tristate imply SUBSYSTEM_X [...] config SUBSYSTEM_X tristate This is much cleaner, and way more flexible than "select". SUBSYSTEM_X can still be configured out, and it can be set as a module when none of the drivers are configured in or all of them are modular. Signed-off-by: Nicolas Pitre <nico@linaro.org> Acked-by: Richard Cochran <richardcochran@gmail.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: John Stultz <john.stultz@linaro.org> Reviewed-by: Josh Triplett <josh@joshtriplett.org> Cc: Paul Bolle <pebolle@tiscali.nl> Cc: linux-kbuild@vger.kernel.org Cc: netdev@vger.kernel.org Cc: Michal Marek <mmarek@suse.com> Cc: Edward Cree <ecree@solarflare.com> Link: http://lkml.kernel.org/r/1478841010-28605-2-git-send-email-nicolas.pitre@linaro.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2016-11-11 05:10:05 +00:00
}
str_append(r, "\n\n");
}
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
{
struct symbol *sym;
struct gstr res = str_new();
int i;
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");
return res;
}
void menu_get_ext_help(struct menu *menu, struct gstr *help)
{
struct symbol *sym = menu->sym;
const char *help_text = nohelp_text;
if (menu->help) {
if (sym->name)
str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
help_text = menu->help;
}
str_printf(help, "%s\n", help_text);
if (sym)
get_symbol_str(help, sym, NULL);
}