2018-12-18 20:13:35 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
|
|
|
*/
|
|
|
|
|
2011-06-02 04:06:22 +08:00
|
|
|
#include <ctype.h>
|
2011-06-02 04:00:46 +08:00
|
|
|
#include <stdarg.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "lkc.h"
|
2021-04-13 23:08:17 +08:00
|
|
|
#include "internal.h"
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2011-08-04 09:52:07 +08:00
|
|
|
static const char nohelp_text[] = "There is no help available for this option.";
|
2009-07-12 16:11:44 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
struct menu rootmenu;
|
|
|
|
static struct menu **last_entry_ptr;
|
|
|
|
|
|
|
|
struct file *file_list;
|
|
|
|
struct file *current_file;
|
|
|
|
|
2008-01-14 11:50:54 +08:00
|
|
|
void menu_warn(struct menu *menu, const char *fmt, ...)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno);
|
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void prop_warn(struct property *prop, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno);
|
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
2009-11-25 18:28:43 +08:00
|
|
|
void _menu_init(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
current_entry = current_menu = &rootmenu;
|
|
|
|
last_entry_ptr = &rootmenu.list;
|
|
|
|
}
|
|
|
|
|
|
|
|
void menu_add_entry(struct symbol *sym)
|
|
|
|
{
|
|
|
|
struct menu *menu;
|
|
|
|
|
2012-11-06 22:32:08 +08:00
|
|
|
menu = xmalloc(sizeof(*menu));
|
2005-04-17 06:20:36 +08:00
|
|
|
memset(menu, 0, sizeof(*menu));
|
|
|
|
menu->sym = sym;
|
|
|
|
menu->parent = current_menu;
|
|
|
|
menu->file = current_file;
|
|
|
|
menu->lineno = zconf_lineno();
|
|
|
|
|
|
|
|
*last_entry_ptr = menu;
|
|
|
|
last_entry_ptr = &menu->next;
|
|
|
|
current_entry = menu;
|
2010-08-01 05:35:29 +08:00
|
|
|
if (sym)
|
|
|
|
menu_add_symbol(P_SYMBOL, sym, NULL);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2005-11-09 13:34:53 +08:00
|
|
|
struct menu *menu_add_menu(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
last_entry_ptr = ¤t_entry->list;
|
2020-04-13 23:35:42 +08:00
|
|
|
current_menu = current_entry;
|
|
|
|
return current_menu;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void menu_end_menu(void)
|
|
|
|
{
|
|
|
|
last_entry_ptr = ¤t_menu->next;
|
|
|
|
current_menu = current_menu->parent;
|
|
|
|
}
|
|
|
|
|
2017-10-05 20:01:13 +08:00
|
|
|
/*
|
|
|
|
* Rewrites 'm' to 'm' && MODULES, so that it evaluates to 'n' when running
|
|
|
|
* without modules
|
|
|
|
*/
|
|
|
|
static struct expr *rewrite_m(struct expr *e)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
if (!e)
|
|
|
|
return e;
|
|
|
|
|
|
|
|
switch (e->type) {
|
|
|
|
case E_NOT:
|
2017-10-05 20:01:13 +08:00
|
|
|
e->left.expr = rewrite_m(e->left.expr);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
case E_OR:
|
|
|
|
case E_AND:
|
2017-10-05 20:01:13 +08:00
|
|
|
e->left.expr = rewrite_m(e->left.expr);
|
|
|
|
e->right.expr = rewrite_m(e->right.expr);
|
2005-04-17 06:20:36 +08:00
|
|
|
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 20:01:15 +08:00
|
|
|
current_entry->dep = expr_alloc_and(current_entry->dep, dep);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2013-10-04 00:32:02 +08:00
|
|
|
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));
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2019-12-17 12:14:21 +08:00
|
|
|
static struct property *menu_add_prop(enum prop_type type, struct expr *expr,
|
|
|
|
struct expr *dep)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2019-12-17 12:14:23 +08:00
|
|
|
struct property *prop;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2019-12-17 12:14:23 +08:00
|
|
|
prop = xmalloc(sizeof(*prop));
|
|
|
|
memset(prop, 0, sizeof(*prop));
|
|
|
|
prop->type = type;
|
|
|
|
prop->file = current_file;
|
|
|
|
prop->lineno = zconf_lineno();
|
2005-04-17 06:20:36 +08:00
|
|
|
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 20:01:15 +08:00
|
|
|
prop->visible.expr = dep;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2019-12-17 12:14:23 +08:00
|
|
|
/* append property to the prop list of symbol */
|
|
|
|
if (current_entry->sym) {
|
|
|
|
struct property **propp;
|
|
|
|
|
|
|
|
for (propp = ¤t_entry->sym->prop;
|
|
|
|
*propp;
|
|
|
|
propp = &(*propp)->next)
|
|
|
|
;
|
|
|
|
*propp = prop;
|
|
|
|
}
|
|
|
|
|
2019-12-17 12:14:20 +08:00
|
|
|
return prop;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct property *menu_add_prompt(enum prop_type type, char *prompt,
|
|
|
|
struct expr *dep)
|
|
|
|
{
|
2019-12-17 12:14:21 +08:00
|
|
|
struct property *prop = menu_add_prop(type, NULL, dep);
|
2010-12-09 16:11:38 +08:00
|
|
|
|
2019-12-17 12:14:20 +08:00
|
|
|
if (isspace(*prompt)) {
|
|
|
|
prop_warn(prop, "leading whitespace ignored");
|
|
|
|
while (isspace(*prompt))
|
|
|
|
prompt++;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2019-12-17 12:14:20 +08:00
|
|
|
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) {
|
|
|
|
struct expr *dup_expr;
|
|
|
|
|
|
|
|
if (!menu->visibility)
|
|
|
|
continue;
|
|
|
|
/*
|
|
|
|
* Do not add a reference to the menu's visibility
|
|
|
|
* expression but use a copy of it. Otherwise the
|
|
|
|
* expression reduction functions will modify
|
|
|
|
* expressions that have multiple references which
|
|
|
|
* can cause unwanted side effects.
|
|
|
|
*/
|
|
|
|
dup_expr = expr_copy(menu->visibility);
|
|
|
|
|
|
|
|
prop->visible.expr = expr_alloc_and(prop->visible.expr,
|
|
|
|
dup_expr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
current_entry->prompt = prop;
|
2006-06-09 13:12:48 +08:00
|
|
|
prop->text = prompt;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
return prop;
|
|
|
|
}
|
|
|
|
|
2010-11-07 05:30:23 +08:00
|
|
|
void menu_add_visibility(struct expr *expr)
|
|
|
|
{
|
|
|
|
current_entry->visibility = expr_alloc_and(current_entry->visibility,
|
|
|
|
expr);
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
|
|
|
|
{
|
2019-12-17 12:14:21 +08:00
|
|
|
menu_add_prop(type, expr, dep);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
|
|
|
|
{
|
2019-12-17 12:14:21 +08:00
|
|
|
menu_add_prop(type, expr_alloc_symbol(sym), dep);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2010-12-05 14:29:25 +08:00
|
|
|
static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
|
2005-11-09 13:34:49 +08:00
|
|
|
{
|
|
|
|
return sym2->type == S_INT || sym2->type == S_HEX ||
|
|
|
|
(sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
|
|
|
|
}
|
|
|
|
|
2009-09-19 03:49:23 +08:00
|
|
|
static void sym_check_prop(struct symbol *sym)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct property *prop;
|
|
|
|
struct symbol *sym2;
|
2016-11-11 13:10:05 +08:00
|
|
|
char *use;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
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,
|
2010-04-14 11:44:05 +08:00
|
|
|
"default for config symbol '%s'"
|
2005-04-17 06:20:36 +08:00
|
|
|
" must be a single symbol", sym->name);
|
2010-12-05 14:29:25 +08:00
|
|
|
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);
|
|
|
|
}
|
2017-10-04 07:25:46 +08:00
|
|
|
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);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
case P_SELECT:
|
2016-11-11 13:10:05 +08:00
|
|
|
case P_IMPLY:
|
|
|
|
use = prop->type == P_SELECT ? "select" : "imply";
|
2005-04-17 06:20:36 +08:00
|
|
|
sym2 = prop_get_symbol(prop);
|
|
|
|
if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
|
|
|
|
prop_warn(prop,
|
2016-11-11 13:10:05 +08:00
|
|
|
"config symbol '%s' uses %s, but is "
|
2017-12-15 23:38:02 +08:00
|
|
|
"not bool or tristate", sym->name, use);
|
2008-02-03 04:09:57 +08:00
|
|
|
else if (sym2->type != S_UNKNOWN &&
|
2014-06-10 18:08:13 +08:00
|
|
|
sym2->type != S_BOOLEAN &&
|
|
|
|
sym2->type != S_TRISTATE)
|
2005-04-17 06:20:36 +08:00
|
|
|
prop_warn(prop,
|
2016-11-11 13:10:05 +08:00
|
|
|
"'%s' has wrong type. '%s' only "
|
2017-12-15 23:38:02 +08:00
|
|
|
"accept arguments of bool and "
|
2016-11-11 13:10:05 +08:00
|
|
|
"tristate type", sym2->name, use);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
case P_RANGE:
|
|
|
|
if (sym->type != S_INT && sym->type != S_HEX)
|
|
|
|
prop_warn(prop, "range is only allowed "
|
2014-06-10 18:08:13 +08:00
|
|
|
"for int or hex symbols");
|
2010-12-05 14:29:25 +08:00
|
|
|
if (!menu_validate_number(sym, prop->expr->left.sym) ||
|
|
|
|
!menu_validate_number(sym, prop->expr->right.sym))
|
2005-04-17 06:20:36 +08:00
|
|
|
prop_warn(prop, "range is invalid");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void menu_finalize(struct menu *parent)
|
|
|
|
{
|
|
|
|
struct menu *menu, *last_menu;
|
|
|
|
struct symbol *sym;
|
|
|
|
struct property *prop;
|
|
|
|
struct expr *parentdep, *basedep, *dep, *dep2, **ep;
|
|
|
|
|
|
|
|
sym = parent->sym;
|
|
|
|
if (parent->list) {
|
2017-10-05 20:01:14 +08:00
|
|
|
/*
|
|
|
|
* This menu node has children. We (recursively) process them
|
|
|
|
* and propagate parent dependencies before moving on.
|
|
|
|
*/
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
if (sym && sym_is_choice(sym)) {
|
2008-02-29 12:11:50 +08:00
|
|
|
if (sym->type == S_UNKNOWN) {
|
|
|
|
/* find the first choice value to find out choice type */
|
|
|
|
current_entry = parent;
|
|
|
|
for (menu = parent->list; menu; menu = menu->next) {
|
|
|
|
if (menu->sym && menu->sym->type != S_UNKNOWN) {
|
2008-01-24 19:54:23 +08:00
|
|
|
menu_set_type(menu->sym->type);
|
2008-02-29 12:11:50 +08:00
|
|
|
break;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
2008-02-29 12:11:50 +08:00
|
|
|
/* set the type of the remaining choice values */
|
|
|
|
for (menu = parent->list; menu; menu = menu->next) {
|
|
|
|
current_entry = menu;
|
|
|
|
if (menu->sym && menu->sym->type == S_UNKNOWN)
|
|
|
|
menu_set_type(sym->type);
|
|
|
|
}
|
2018-01-14 22:12:05 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
parentdep = expr_alloc_symbol(sym);
|
2019-12-17 12:14:17 +08:00
|
|
|
} else {
|
|
|
|
/* Menu node for 'menu', 'if' */
|
2005-04-17 06:20:36 +08:00
|
|
|
parentdep = parent->dep;
|
2019-12-17 12:14:17 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2017-10-05 20:01:14 +08:00
|
|
|
/* For each child menu node... */
|
2005-04-17 06:20:36 +08:00
|
|
|
for (menu = parent->list; menu; menu = menu->next) {
|
2017-10-05 20:01:14 +08:00
|
|
|
/*
|
|
|
|
* 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 20:01:15 +08:00
|
|
|
basedep = rewrite_m(menu->dep);
|
|
|
|
basedep = expr_transform(basedep);
|
2007-10-20 12:25:45 +08:00
|
|
|
basedep = expr_alloc_and(expr_copy(parentdep), basedep);
|
2005-04-17 06:20:36 +08:00
|
|
|
basedep = expr_eliminate_dups(basedep);
|
|
|
|
menu->dep = basedep;
|
2017-10-05 20:01:14 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
if (menu->sym)
|
2017-10-05 20:01:14 +08:00
|
|
|
/*
|
|
|
|
* Note: For symbols, all prompts are included
|
|
|
|
* too in the symbol's own property list
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
prop = menu->sym->prop;
|
|
|
|
else
|
2017-10-05 20:01:14 +08:00
|
|
|
/*
|
|
|
|
* For non-symbol menu nodes, we just need to
|
|
|
|
* handle the prompt
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
prop = menu->prompt;
|
2017-10-05 20:01:14 +08:00
|
|
|
|
|
|
|
/* For each property... */
|
2005-04-17 06:20:36 +08:00
|
|
|
for (; prop; prop = prop->next) {
|
|
|
|
if (prop->menu != menu)
|
2017-10-05 20:01:14 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
continue;
|
2017-10-05 20:01:14 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 20:01:15 +08:00
|
|
|
dep = rewrite_m(prop->visible.expr);
|
|
|
|
dep = expr_transform(dep);
|
2005-04-17 06:20:36 +08:00
|
|
|
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;
|
2017-10-05 20:01:14 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle selects and implies, which modify the
|
|
|
|
* dependencies of the selected/implied symbol
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
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)));
|
2016-11-11 13:10:05 +08:00
|
|
|
} 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)));
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-10-05 20:01:14 +08:00
|
|
|
|
2017-10-09 01:35:46 +08:00
|
|
|
if (sym && sym_is_choice(sym))
|
|
|
|
expr_free(parentdep);
|
|
|
|
|
2017-10-05 20:01:14 +08:00
|
|
|
/*
|
|
|
|
* Recursively process children in the same fashion before
|
|
|
|
* moving on
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
for (menu = parent->list; menu; menu = menu->next)
|
|
|
|
menu_finalize(menu);
|
|
|
|
} else if (sym) {
|
2017-10-09 01:42:18 +08:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
* ...
|
|
|
|
*/
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
|
|
|
|
basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
|
|
|
|
basedep = expr_eliminate_dups(expr_transform(basedep));
|
2017-10-09 01:42:18 +08:00
|
|
|
|
|
|
|
/* Examine consecutive elements after sym */
|
2005-04-17 06:20:36 +08:00
|
|
|
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))
|
2017-10-09 01:42:18 +08:00
|
|
|
/* No dependency, quit */
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
if (expr_depends_symbol(dep, sym))
|
2017-10-09 01:42:18 +08:00
|
|
|
/* Absolute dependency, put in submenu */
|
2005-04-17 06:20:36 +08:00
|
|
|
goto next;
|
2017-10-09 01:42:18 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
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)) {
|
2017-10-09 01:42:18 +08:00
|
|
|
/* Not superset, quit */
|
2005-04-17 06:20:36 +08:00
|
|
|
expr_free(dep2);
|
|
|
|
break;
|
|
|
|
}
|
2017-10-09 01:42:18 +08:00
|
|
|
/* Superset, put in submenu */
|
2005-04-17 06:20:36 +08:00
|
|
|
expr_free(dep2);
|
|
|
|
next:
|
|
|
|
menu_finalize(menu);
|
|
|
|
menu->parent = parent;
|
|
|
|
last_menu = menu;
|
|
|
|
}
|
2017-10-09 01:35:44 +08:00
|
|
|
expr_free(basedep);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (last_menu) {
|
|
|
|
parent->list = parent->next;
|
|
|
|
parent->next = last_menu->next;
|
|
|
|
last_menu->next = NULL;
|
|
|
|
}
|
2010-09-27 04:22:03 +08:00
|
|
|
|
2011-06-08 13:42:11 +08:00
|
|
|
sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
for (menu = parent->list; menu; menu = menu->next) {
|
2008-02-29 12:11:50 +08:00
|
|
|
if (sym && sym_is_choice(sym) &&
|
|
|
|
menu->sym && !sym_is_choice_value(menu->sym)) {
|
|
|
|
current_entry = menu;
|
2005-04-17 06:20:36 +08:00
|
|
|
menu->sym->flags |= SYMBOL_CHOICEVAL;
|
|
|
|
if (!menu->prompt)
|
|
|
|
menu_warn(menu, "choice value must have a prompt");
|
|
|
|
for (prop = menu->sym->prop; prop; prop = prop->next) {
|
|
|
|
if (prop->type == P_DEFAULT)
|
|
|
|
prop_warn(prop, "defaults for choice "
|
2008-02-29 12:11:50 +08:00
|
|
|
"values not supported");
|
|
|
|
if (prop->menu == menu)
|
|
|
|
continue;
|
|
|
|
if (prop->type == P_PROMPT &&
|
|
|
|
prop->menu->parent->sym != sym)
|
|
|
|
prop_warn(prop, "choice value used outside its choice group");
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2008-01-24 19:54:23 +08:00
|
|
|
/* Non-tristate choice values of tristate choices must
|
|
|
|
* depend on the choice being set to Y. The choice
|
|
|
|
* values' dependencies were propagated to their
|
|
|
|
* properties above, so the change here must be re-
|
2008-02-29 12:11:50 +08:00
|
|
|
* propagated.
|
|
|
|
*/
|
2008-01-24 19:54:23 +08:00
|
|
|
if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
|
|
|
|
basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
|
2008-02-29 12:11:50 +08:00
|
|
|
menu->dep = expr_alloc_and(basedep, menu->dep);
|
2008-01-24 19:54:23 +08:00
|
|
|
for (prop = menu->sym->prop; prop; prop = prop->next) {
|
|
|
|
if (prop->menu != menu)
|
|
|
|
continue;
|
2008-02-29 12:11:50 +08:00
|
|
|
prop->visible.expr = expr_alloc_and(expr_copy(basedep),
|
|
|
|
prop->visible.expr);
|
2008-01-24 19:54:23 +08:00
|
|
|
}
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
menu_add_symbol(P_CHOICE, sym, NULL);
|
|
|
|
prop = sym_get_choice_prop(sym);
|
|
|
|
for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)
|
|
|
|
;
|
2008-01-14 11:50:23 +08:00
|
|
|
*ep = expr_alloc_one(E_LIST, NULL);
|
2005-04-17 06:20:36 +08:00
|
|
|
(*ep)->right.sym = menu->sym;
|
|
|
|
}
|
2018-01-14 22:49:26 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
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)
|
2006-06-09 13:12:48 +08:00
|
|
|
menu_warn(parent, "config symbol defined without type");
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (sym_is_choice(sym) && !parent->prompt)
|
2006-06-09 13:12:48 +08:00
|
|
|
menu_warn(parent, "choice must have a prompt");
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* Check properties connected to this symbol */
|
|
|
|
sym_check_prop(sym);
|
|
|
|
sym->flags |= SYMBOL_WARNED;
|
|
|
|
}
|
|
|
|
|
2018-01-14 17:56:20 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
if (sym && !sym_is_optional(sym) && parent->prompt) {
|
|
|
|
sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
|
|
|
|
expr_alloc_and(parent->prompt->visible.expr,
|
|
|
|
expr_alloc_symbol(&symbol_mod)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
menuconfig: add support to show hidden options which have prompts
Usage:
Press <Z> to show all config symbols which have prompts.
Quote Tim Bird:
| I've been bitten by this numerous times. I most often
| use ftrace on ARM, but when I go back to x86, I almost
| always go through a sequence of searching for the
| function graph tracer in the menus, then realizing it's
| completely missing until I disable CC_OPTIMIZE_FOR_SIZE.
|
| Is there any way to have the menu item appear, but be
| unsettable unless the SIZE option is disabled? I'm
| not a Kconfig guru...
I myself found this useful too. For example, I need to test
ftrace/tracing and want to be sure all the tracing features are
enabled, so I enter the "Tracers" menu, and press <Z> to
see if there is any config hidden.
I also noticed gconfig and xconfig have a button "Show all options",
but that's a bit too much, and I think normally what we are not
interested in those configs which have no prompt thus can't be
changed by users.
Exmaple:
--- Tracers
-*- Kernel Function Tracer
- - Kernel Function Graph Tracer
[*] Interrupts-off Latency Tracer
- - Preemption-off Latency Tracer
[*] Sysprof Tracer
Here you can see 2 tracers are not selectable, and then can find
out how to make them selectable.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: Michal Marek <mmarek@suse.cz>
2010-04-14 11:46:02 +08:00
|
|
|
bool menu_has_prompt(struct menu *menu)
|
|
|
|
{
|
|
|
|
if (!menu->prompt)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-05-20 03:49:34 +08:00
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
bool menu_is_visible(struct menu *menu)
|
|
|
|
{
|
|
|
|
struct menu *child;
|
|
|
|
struct symbol *sym;
|
|
|
|
tristate visible;
|
|
|
|
|
|
|
|
if (!menu->prompt)
|
|
|
|
return false;
|
menuconfig: add support to show hidden options which have prompts
Usage:
Press <Z> to show all config symbols which have prompts.
Quote Tim Bird:
| I've been bitten by this numerous times. I most often
| use ftrace on ARM, but when I go back to x86, I almost
| always go through a sequence of searching for the
| function graph tracer in the menus, then realizing it's
| completely missing until I disable CC_OPTIMIZE_FOR_SIZE.
|
| Is there any way to have the menu item appear, but be
| unsettable unless the SIZE option is disabled? I'm
| not a Kconfig guru...
I myself found this useful too. For example, I need to test
ftrace/tracing and want to be sure all the tracing features are
enabled, so I enter the "Tracers" menu, and press <Z> to
see if there is any config hidden.
I also noticed gconfig and xconfig have a button "Show all options",
but that's a bit too much, and I think normally what we are not
interested in those configs which have no prompt thus can't be
changed by users.
Exmaple:
--- Tracers
-*- Kernel Function Tracer
- - Kernel Function Graph Tracer
[*] Interrupts-off Latency Tracer
- - Preemption-off Latency Tracer
[*] Sysprof Tracer
Here you can see 2 tracers are not selectable, and then can find
out how to make them selectable.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: Michal Marek <mmarek@suse.cz>
2010-04-14 11:46:02 +08:00
|
|
|
|
2010-11-07 05:30:23 +08:00
|
|
|
if (menu->visibility) {
|
|
|
|
if (expr_calc_value(menu->visibility) == no)
|
2016-01-02 00:34:05 +08:00
|
|
|
return false;
|
2010-11-07 05:30:23 +08:00
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
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;
|
menuconfig: add support to show hidden options which have prompts
Usage:
Press <Z> to show all config symbols which have prompts.
Quote Tim Bird:
| I've been bitten by this numerous times. I most often
| use ftrace on ARM, but when I go back to x86, I almost
| always go through a sequence of searching for the
| function graph tracer in the menus, then realizing it's
| completely missing until I disable CC_OPTIMIZE_FOR_SIZE.
|
| Is there any way to have the menu item appear, but be
| unsettable unless the SIZE option is disabled? I'm
| not a Kconfig guru...
I myself found this useful too. For example, I need to test
ftrace/tracing and want to be sure all the tracing features are
enabled, so I enter the "Tracers" menu, and press <Z> to
see if there is any config hidden.
I also noticed gconfig and xconfig have a button "Show all options",
but that's a bit too much, and I think normally what we are not
interested in those configs which have no prompt thus can't be
changed by users.
Exmaple:
--- Tracers
-*- Kernel Function Tracer
- - Kernel Function Graph Tracer
[*] Interrupts-off Latency Tracer
- - Preemption-off Latency Tracer
[*] Sysprof Tracer
Here you can see 2 tracers are not selectable, and then can find
out how to make them selectable.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: Michal Marek <mmarek@suse.cz>
2010-04-14 11:46:02 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
if (!sym || sym_get_tristate_value(menu->sym) == no)
|
|
|
|
return false;
|
|
|
|
|
2010-05-07 13:57:07 +08:00
|
|
|
for (child = menu->list; child; child = child->next) {
|
|
|
|
if (menu_is_visible(child)) {
|
|
|
|
if (sym)
|
|
|
|
sym->flags |= SYMBOL_DEF_USER;
|
2005-04-17 06:20:36 +08:00
|
|
|
return true;
|
2010-05-07 13:57:07 +08:00
|
|
|
}
|
|
|
|
}
|
menuconfig: add support to show hidden options which have prompts
Usage:
Press <Z> to show all config symbols which have prompts.
Quote Tim Bird:
| I've been bitten by this numerous times. I most often
| use ftrace on ARM, but when I go back to x86, I almost
| always go through a sequence of searching for the
| function graph tracer in the menus, then realizing it's
| completely missing until I disable CC_OPTIMIZE_FOR_SIZE.
|
| Is there any way to have the menu item appear, but be
| unsettable unless the SIZE option is disabled? I'm
| not a Kconfig guru...
I myself found this useful too. For example, I need to test
ftrace/tracing and want to be sure all the tracing features are
enabled, so I enter the "Tracers" menu, and press <Z> to
see if there is any config hidden.
I also noticed gconfig and xconfig have a button "Show all options",
but that's a bit too much, and I think normally what we are not
interested in those configs which have no prompt thus can't be
changed by users.
Exmaple:
--- Tracers
-*- Kernel Function Tracer
- - Kernel Function Graph Tracer
[*] Interrupts-off Latency Tracer
- - Preemption-off Latency Tracer
[*] Sysprof Tracer
Here you can see 2 tracers are not selectable, and then can find
out how to make them selectable.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: Michal Marek <mmarek@suse.cz>
2010-04-14 11:46:02 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *menu_get_prompt(struct menu *menu)
|
|
|
|
{
|
|
|
|
if (menu->prompt)
|
2008-01-12 06:53:43 +08:00
|
|
|
return menu->prompt->text;
|
2005-04-17 06:20:36 +08:00
|
|
|
else if (menu->sym)
|
2008-01-12 06:53:43 +08:00
|
|
|
return menu->sym->name;
|
2005-04-17 06:20:36 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2007-07-21 06:00:36 +08:00
|
|
|
bool menu_has_help(struct menu *menu)
|
|
|
|
{
|
|
|
|
return menu->help != NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *menu_get_help(struct menu *menu)
|
|
|
|
{
|
|
|
|
if (menu->help)
|
|
|
|
return menu->help;
|
|
|
|
else
|
|
|
|
return "";
|
|
|
|
}
|
2009-07-12 16:11:44 +08:00
|
|
|
|
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-18 00:15:43 +08:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-24 02:55:08 +08:00
|
|
|
static void get_prompt_str(struct gstr *r, struct property *prop,
|
2012-10-21 17:27:53 +08:00
|
|
|
struct list_head *head)
|
2009-07-12 16:11:44 +08:00
|
|
|
{
|
|
|
|
int i, j;
|
2012-08-24 02:55:06 +08:00
|
|
|
struct menu *submenu[8], *menu, *location = NULL;
|
2014-11-04 19:01:59 +08:00
|
|
|
struct jump_key *jump = NULL;
|
2009-07-12 16:11:44 +08:00
|
|
|
|
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-18 00:15:43 +08: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-18 00:15:44 +08: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: ");
|
|
|
|
|
2022-10-24 03:10:55 +08:00
|
|
|
menu = prop->menu;
|
|
|
|
for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
|
2009-07-12 16:11:44 +08:00
|
|
|
submenu[i++] = menu;
|
2022-11-13 18:59:41 +08:00
|
|
|
if (location == NULL && menu_is_visible(menu))
|
2012-08-24 02:55:06 +08:00
|
|
|
location = menu;
|
|
|
|
}
|
2012-08-24 02:55:08 +08:00
|
|
|
if (head && location) {
|
2012-11-06 22:32:08 +08:00
|
|
|
jump = xmalloc(sizeof(struct jump_key));
|
2012-08-24 02:55:08 +08:00
|
|
|
|
2022-10-24 03:10:55 +08:00
|
|
|
jump->target = location;
|
2012-08-24 02:55:08 +08:00
|
|
|
|
2012-10-21 17:27:53 +08:00
|
|
|
if (list_empty(head))
|
2012-08-24 02:55:08 +08:00
|
|
|
jump->index = 0;
|
|
|
|
else
|
2012-10-21 17:27:53 +08:00
|
|
|
jump->index = list_entry(head->prev, struct jump_key,
|
|
|
|
entries)->index + 1;
|
2012-08-24 02:55:08 +08:00
|
|
|
|
2012-10-21 17:27:53 +08:00
|
|
|
list_add_tail(&jump->entries, head);
|
2012-08-24 02:55:08 +08:00
|
|
|
}
|
2012-08-24 02:55:06 +08:00
|
|
|
|
2021-09-14 00:45:14 +08:00
|
|
|
str_printf(r, " Location:\n");
|
|
|
|
for (j = 4; --i >= 0; j += 2) {
|
|
|
|
menu = submenu[i];
|
|
|
|
if (jump && menu == location)
|
|
|
|
jump->offset = strlen(r->s);
|
2022-10-24 03:10:55 +08:00
|
|
|
str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu));
|
2021-09-14 00:45:14 +08:00
|
|
|
if (menu->sym) {
|
|
|
|
str_printf(r, " (%s [=%s])", menu->sym->name ?
|
|
|
|
menu->sym->name : "<choice>",
|
|
|
|
sym_get_string_value(menu->sym));
|
2009-07-12 16:11:44 +08:00
|
|
|
}
|
2021-09-14 00:45:14 +08:00
|
|
|
str_append(r, "\n");
|
2009-07-12 16:11:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-11 13:10:05 +08: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");
|
|
|
|
}
|
|
|
|
|
2012-08-24 02:55:06 +08:00
|
|
|
/*
|
2012-08-24 02:55:08 +08:00
|
|
|
* head is optional and may be NULL
|
2012-08-24 02:55:06 +08:00
|
|
|
*/
|
2015-02-24 23:37:13 +08:00
|
|
|
static void get_symbol_str(struct gstr *r, struct symbol *sym,
|
2012-10-21 17:27:53 +08:00
|
|
|
struct list_head *head)
|
2009-07-12 16:11:44 +08:00
|
|
|
{
|
|
|
|
struct property *prop;
|
|
|
|
|
2010-05-07 13:56:33 +08:00
|
|
|
if (sym && sym->name) {
|
2009-07-12 16:11:44 +08:00
|
|
|
str_printf(r, "Symbol: %s [=%s]\n", sym->name,
|
|
|
|
sym_get_string_value(sym));
|
2010-05-07 13:56:33 +08:00
|
|
|
str_printf(r, "Type : %s\n", sym_type_name(sym->type));
|
2010-05-07 13:56:50 +08:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
2010-05-07 13:56:33 +08:00
|
|
|
}
|
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-18 00:15:43 +08:00
|
|
|
|
|
|
|
/* 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_properties(sym, prop, P_SYMBOL) {
|
|
|
|
if (!prop->menu->prompt) {
|
|
|
|
get_def_str(r, prop->menu);
|
|
|
|
get_dep_str(r, prop->menu->dep, " Depends on: ");
|
2013-05-07 21:56:54 +08:00
|
|
|
}
|
2013-05-01 06:28:46 +08:00
|
|
|
}
|
2013-05-07 21:56:54 +08:00
|
|
|
|
2019-12-18 00:15:45 +08:00
|
|
|
get_symbol_props_str(r, sym, P_SELECT, "Selects: ");
|
2009-07-12 16:11:44 +08:00
|
|
|
if (sym->rev_dep.expr) {
|
2019-12-18 00:15:45 +08:00
|
|
|
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");
|
2009-07-12 16:11:44 +08:00
|
|
|
}
|
2016-11-11 13:10:05 +08:00
|
|
|
|
2019-12-18 00:15:45 +08:00
|
|
|
get_symbol_props_str(r, sym, P_IMPLY, "Implies: ");
|
2016-11-11 13:10:05 +08:00
|
|
|
if (sym->implied.expr) {
|
2019-12-18 00:15:45 +08:00
|
|
|
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");
|
2016-11-11 13:10:05 +08:00
|
|
|
}
|
|
|
|
|
2009-07-12 16:11:44 +08:00
|
|
|
str_append(r, "\n\n");
|
|
|
|
}
|
|
|
|
|
2012-10-21 17:27:53 +08:00
|
|
|
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
|
2009-11-25 18:28:43 +08:00
|
|
|
{
|
|
|
|
struct symbol *sym;
|
|
|
|
struct gstr res = str_new();
|
2012-08-24 02:55:08 +08:00
|
|
|
int i;
|
2009-11-25 18:28:43 +08:00
|
|
|
|
|
|
|
for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
|
2012-08-24 02:55:08 +08:00
|
|
|
get_symbol_str(&res, sym, head);
|
2009-11-25 18:28:43 +08:00
|
|
|
if (!i)
|
2018-05-23 03:36:12 +08:00
|
|
|
str_append(&res, "No matches found.\n");
|
2009-11-25 18:28:43 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-12 16:11:44 +08:00
|
|
|
void menu_get_ext_help(struct menu *menu, struct gstr *help)
|
|
|
|
{
|
|
|
|
struct symbol *sym = menu->sym;
|
2011-08-04 09:52:07 +08:00
|
|
|
const char *help_text = nohelp_text;
|
2009-07-12 16:11:44 +08:00
|
|
|
|
|
|
|
if (menu_has_help(menu)) {
|
2011-08-03 01:49:52 +08:00
|
|
|
if (sym->name)
|
2010-08-15 11:57:43 +08:00
|
|
|
str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
|
2011-08-04 09:52:07 +08:00
|
|
|
help_text = menu_get_help(menu);
|
2009-07-12 16:11:44 +08:00
|
|
|
}
|
2018-05-23 03:36:12 +08:00
|
|
|
str_printf(help, "%s\n", help_text);
|
2009-07-12 16:11:46 +08:00
|
|
|
if (sym)
|
2012-08-24 02:55:08 +08:00
|
|
|
get_symbol_str(help, sym, NULL);
|
2009-07-12 16:11:44 +08:00
|
|
|
}
|