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>
|
|
|
|
*/
|
|
|
|
|
2020-11-23 17:38:18 +08:00
|
|
|
#include <sys/types.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <regex.h>
|
|
|
|
|
2024-09-08 20:43:16 +08:00
|
|
|
#include <hash.h>
|
2024-08-12 20:48:50 +08:00
|
|
|
#include <xalloc.h>
|
2024-02-11 20:41:05 +08:00
|
|
|
#include "internal.h"
|
2005-04-17 06:20:36 +08:00
|
|
|
#include "lkc.h"
|
|
|
|
|
|
|
|
struct symbol symbol_yes = {
|
|
|
|
.name = "y",
|
kconfig: fix comparison to constant symbols, 'm', 'n'
Currently, comparisons to 'm' or 'n' result in incorrect output.
[Test Code]
config MODULES
def_bool y
modules
config A
def_tristate m
config B
def_bool A > n
CONFIG_B is unset, while CONFIG_B=y is expected.
The reason for the issue is because Kconfig compares the tristate values
as strings.
Currently, the .type fields in the constant symbol definitions,
symbol_{yes,mod,no} are unspecified, i.e., S_UNKNOWN.
When expr_calc_value() evaluates 'A > n', it checks the types of 'A' and
'n' to determine how to compare them.
The left-hand side, 'A', is a tristate symbol with a value of 'm', which
corresponds to a numeric value of 1. (Internally, 'y', 'm', and 'n' are
represented as 2, 1, and 0, respectively.)
The right-hand side, 'n', has an unknown type, so it is treated as the
string "n" during the comparison.
expr_calc_value() compares two values numerically only when both can
have numeric values. Otherwise, they are compared as strings.
symbol numeric value ASCII code
-------------------------------------
y 2 0x79
m 1 0x6d
n 0 0x6e
'm' is greater than 'n' if compared numerically (since 1 is greater
than 0), but smaller than 'n' if compared as strings (since the ASCII
code 0x6d is smaller than 0x6e).
Specifying .type=S_TRISTATE for symbol_{yes,mod,no} fixes the above
test code.
Doing so, however, would cause a regression to the following test code.
[Test Code 2]
config MODULES
def_bool n
modules
config A
def_tristate n
config B
def_bool A = m
You would get CONFIG_B=y, while CONFIG_B should not be set.
The reason is because sym_get_string_value() turns 'm' into 'n' when the
module feature is disabled. Consequently, expr_calc_value() evaluates
'A = n' instead of 'A = m'. This oddity has been hidden because the type
of 'm' was previously S_UNKNOWN instead of S_TRISTATE.
sym_get_string_value() should not tweak the string because the tristate
value has already been correctly calculated. There is no reason to
return the string "n" where its tristate value is mod.
Fixes: 31847b67bec0 ("kconfig: allow use of relations other than (in)equality")
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-05-19 17:22:27 +08:00
|
|
|
.type = S_TRISTATE,
|
2005-04-17 06:20:36 +08:00
|
|
|
.curr = { "y", yes },
|
2024-03-03 12:00:33 +08:00
|
|
|
.menus = LIST_HEAD_INIT(symbol_yes.menus),
|
2006-06-09 13:12:40 +08:00
|
|
|
.flags = SYMBOL_CONST|SYMBOL_VALID,
|
2020-07-29 11:18:37 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct symbol symbol_mod = {
|
2005-04-17 06:20:36 +08:00
|
|
|
.name = "m",
|
kconfig: fix comparison to constant symbols, 'm', 'n'
Currently, comparisons to 'm' or 'n' result in incorrect output.
[Test Code]
config MODULES
def_bool y
modules
config A
def_tristate m
config B
def_bool A > n
CONFIG_B is unset, while CONFIG_B=y is expected.
The reason for the issue is because Kconfig compares the tristate values
as strings.
Currently, the .type fields in the constant symbol definitions,
symbol_{yes,mod,no} are unspecified, i.e., S_UNKNOWN.
When expr_calc_value() evaluates 'A > n', it checks the types of 'A' and
'n' to determine how to compare them.
The left-hand side, 'A', is a tristate symbol with a value of 'm', which
corresponds to a numeric value of 1. (Internally, 'y', 'm', and 'n' are
represented as 2, 1, and 0, respectively.)
The right-hand side, 'n', has an unknown type, so it is treated as the
string "n" during the comparison.
expr_calc_value() compares two values numerically only when both can
have numeric values. Otherwise, they are compared as strings.
symbol numeric value ASCII code
-------------------------------------
y 2 0x79
m 1 0x6d
n 0 0x6e
'm' is greater than 'n' if compared numerically (since 1 is greater
than 0), but smaller than 'n' if compared as strings (since the ASCII
code 0x6d is smaller than 0x6e).
Specifying .type=S_TRISTATE for symbol_{yes,mod,no} fixes the above
test code.
Doing so, however, would cause a regression to the following test code.
[Test Code 2]
config MODULES
def_bool n
modules
config A
def_tristate n
config B
def_bool A = m
You would get CONFIG_B=y, while CONFIG_B should not be set.
The reason is because sym_get_string_value() turns 'm' into 'n' when the
module feature is disabled. Consequently, expr_calc_value() evaluates
'A = n' instead of 'A = m'. This oddity has been hidden because the type
of 'm' was previously S_UNKNOWN instead of S_TRISTATE.
sym_get_string_value() should not tweak the string because the tristate
value has already been correctly calculated. There is no reason to
return the string "n" where its tristate value is mod.
Fixes: 31847b67bec0 ("kconfig: allow use of relations other than (in)equality")
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-05-19 17:22:27 +08:00
|
|
|
.type = S_TRISTATE,
|
2005-04-17 06:20:36 +08:00
|
|
|
.curr = { "m", mod },
|
2024-03-03 12:00:33 +08:00
|
|
|
.menus = LIST_HEAD_INIT(symbol_mod.menus),
|
2006-06-09 13:12:40 +08:00
|
|
|
.flags = SYMBOL_CONST|SYMBOL_VALID,
|
2020-07-29 11:18:37 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct symbol symbol_no = {
|
2005-04-17 06:20:36 +08:00
|
|
|
.name = "n",
|
kconfig: fix comparison to constant symbols, 'm', 'n'
Currently, comparisons to 'm' or 'n' result in incorrect output.
[Test Code]
config MODULES
def_bool y
modules
config A
def_tristate m
config B
def_bool A > n
CONFIG_B is unset, while CONFIG_B=y is expected.
The reason for the issue is because Kconfig compares the tristate values
as strings.
Currently, the .type fields in the constant symbol definitions,
symbol_{yes,mod,no} are unspecified, i.e., S_UNKNOWN.
When expr_calc_value() evaluates 'A > n', it checks the types of 'A' and
'n' to determine how to compare them.
The left-hand side, 'A', is a tristate symbol with a value of 'm', which
corresponds to a numeric value of 1. (Internally, 'y', 'm', and 'n' are
represented as 2, 1, and 0, respectively.)
The right-hand side, 'n', has an unknown type, so it is treated as the
string "n" during the comparison.
expr_calc_value() compares two values numerically only when both can
have numeric values. Otherwise, they are compared as strings.
symbol numeric value ASCII code
-------------------------------------
y 2 0x79
m 1 0x6d
n 0 0x6e
'm' is greater than 'n' if compared numerically (since 1 is greater
than 0), but smaller than 'n' if compared as strings (since the ASCII
code 0x6d is smaller than 0x6e).
Specifying .type=S_TRISTATE for symbol_{yes,mod,no} fixes the above
test code.
Doing so, however, would cause a regression to the following test code.
[Test Code 2]
config MODULES
def_bool n
modules
config A
def_tristate n
config B
def_bool A = m
You would get CONFIG_B=y, while CONFIG_B should not be set.
The reason is because sym_get_string_value() turns 'm' into 'n' when the
module feature is disabled. Consequently, expr_calc_value() evaluates
'A = n' instead of 'A = m'. This oddity has been hidden because the type
of 'm' was previously S_UNKNOWN instead of S_TRISTATE.
sym_get_string_value() should not tweak the string because the tristate
value has already been correctly calculated. There is no reason to
return the string "n" where its tristate value is mod.
Fixes: 31847b67bec0 ("kconfig: allow use of relations other than (in)equality")
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-05-19 17:22:27 +08:00
|
|
|
.type = S_TRISTATE,
|
2005-04-17 06:20:36 +08:00
|
|
|
.curr = { "n", no },
|
2024-03-03 12:00:33 +08:00
|
|
|
.menus = LIST_HEAD_INIT(symbol_no.menus),
|
2006-06-09 13:12:40 +08:00
|
|
|
.flags = SYMBOL_CONST|SYMBOL_VALID,
|
2020-07-29 11:18:37 +08:00
|
|
|
};
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
struct symbol *modules_sym;
|
2020-07-29 11:18:37 +08:00
|
|
|
static tristate modules_val;
|
2023-11-22 11:47:45 +08:00
|
|
|
static int sym_warnings;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2024-07-07 23:38:05 +08:00
|
|
|
enum symbol_type sym_get_type(const struct symbol *sym)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
enum symbol_type type = sym->type;
|
|
|
|
|
kconfig: remove tristate choice support
I previously submitted a fix for a bug in the choice feature [1], where
I mentioned, "Another (much cleaner) approach would be to remove the
tristate choice support entirely".
There are more issues in the tristate choice feature. For example, you
can observe a couple of bugs in the following test code.
[Test Code]
config MODULES
def_bool y
modules
choice
prompt "tristate choice"
default A
config A
tristate "A"
config B
tristate "B"
endchoice
Bug 1: the 'default' property is not correctly processed
'make alldefconfig' produces:
CONFIG_MODULES=y
# CONFIG_A is not set
# CONFIG_B is not set
However, the correct output should be:
CONFIG_MODULES=y
CONFIG_A=y
# CONFIG_B is not set
The unit test file, scripts/kconfig/tests/choice/alldef_expected_config,
is wrong as well.
Bug 2: choice members never get 'y' with randconfig
For the test code above, the following combinations are possible:
A B
(1) y n
(2) n y
(3) m m
(4) m n
(5) n m
(6) n n
'make randconfig' never produces (1) or (2).
These bugs are fixable, but a more critical problem is the lack of a
sensible syntax to specify the default for the tristate choice.
The default for the choice must be one of the choice members, which
cannot specify any of the patterns (3) through (6) above.
In addition, I have never seen it being used in a useful way.
The following commits removed unnecessary use of tristate choices:
- df8df5e4bc37 ("usb: get rid of 'choice' for legacy gadget drivers")
- bfb57ef0544a ("rapidio: remove choice for enumeration")
This commit removes the tristate choice support entirely, which allows
me to delete a lot of code, making further refactoring easier.
Note:
This includes the revert of commit fa64e5f6a35e ("kconfig/symbol.c:
handle choice_values that depend on 'm' symbols"). It was suspicious
because it did not address the root cause but introduced inconsistency
in visibility between choice members and other symbols.
[1]: https://lore.kernel.org/linux-kbuild/20240427104231.2728905-1-masahiroy@kernel.org/T/#m0a1bb6992581462ceca861b409bb33cb8fd7dbae
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Reviewed-by: Nicolas Schier <nicolas@fjasle.eu>
2024-06-02 20:54:14 +08:00
|
|
|
if (type == S_TRISTATE && modules_val == no)
|
|
|
|
type = S_BOOLEAN;
|
2005-04-17 06:20:36 +08:00
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *sym_type_name(enum symbol_type type)
|
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case S_BOOLEAN:
|
2017-12-15 23:38:02 +08:00
|
|
|
return "bool";
|
2005-04-17 06:20:36 +08:00
|
|
|
case S_TRISTATE:
|
|
|
|
return "tristate";
|
|
|
|
case S_INT:
|
|
|
|
return "integer";
|
|
|
|
case S_HEX:
|
|
|
|
return "hex";
|
|
|
|
case S_STRING:
|
|
|
|
return "string";
|
|
|
|
case S_UNKNOWN:
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
return "???";
|
|
|
|
}
|
|
|
|
|
2024-05-05 02:33:28 +08:00
|
|
|
/**
|
|
|
|
* sym_get_choice_menu - get the parent choice menu if present
|
|
|
|
*
|
|
|
|
* @sym: a symbol pointer
|
|
|
|
*
|
|
|
|
* Return: a choice menu if this function is called against a choice member.
|
|
|
|
*/
|
2024-07-07 23:38:05 +08:00
|
|
|
struct menu *sym_get_choice_menu(const struct symbol *sym)
|
2024-05-05 02:33:28 +08:00
|
|
|
{
|
|
|
|
struct menu *menu = NULL;
|
|
|
|
struct menu *m;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Choice members must have a prompt. Find a menu entry with a prompt,
|
|
|
|
* and assume it resides inside a choice block.
|
|
|
|
*/
|
|
|
|
list_for_each_entry(m, &sym->menus, link)
|
|
|
|
if (m->prompt) {
|
|
|
|
menu = m;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!menu)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
do {
|
|
|
|
menu = menu->parent;
|
|
|
|
} while (menu && !menu->sym);
|
|
|
|
|
|
|
|
if (menu && menu->sym && sym_is_choice(menu->sym))
|
|
|
|
return menu;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-02-24 23:37:13 +08:00
|
|
|
static struct property *sym_get_default_prop(struct symbol *sym)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct property *prop;
|
|
|
|
|
|
|
|
for_all_defaults(sym, prop) {
|
|
|
|
prop->visible.tri = expr_calc_value(prop->visible.expr);
|
|
|
|
if (prop->visible.tri != no)
|
|
|
|
return prop;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-12-21 16:33:04 +08:00
|
|
|
struct property *sym_get_range_prop(struct symbol *sym)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct property *prop;
|
|
|
|
|
|
|
|
for_all_properties(sym, prop, P_RANGE) {
|
|
|
|
prop->visible.tri = expr_calc_value(prop->visible.expr);
|
|
|
|
if (prop->visible.tri != no)
|
|
|
|
return prop;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-07-19 02:32:01 +08:00
|
|
|
static long long sym_get_range_val(struct symbol *sym, int base)
|
2005-11-09 13:34:49 +08:00
|
|
|
{
|
|
|
|
sym_calc_value(sym);
|
|
|
|
switch (sym->type) {
|
|
|
|
case S_INT:
|
|
|
|
base = 10;
|
|
|
|
break;
|
|
|
|
case S_HEX:
|
|
|
|
base = 16;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2013-07-19 02:32:01 +08:00
|
|
|
return strtoll(sym->curr.val, NULL, base);
|
2005-11-09 13:34:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void sym_validate_range(struct symbol *sym)
|
|
|
|
{
|
|
|
|
struct property *prop;
|
2023-11-15 12:16:53 +08:00
|
|
|
struct symbol *range_sym;
|
2013-07-19 02:32:01 +08:00
|
|
|
int base;
|
|
|
|
long long val, val2;
|
2005-11-09 13:34:49 +08:00
|
|
|
|
|
|
|
switch (sym->type) {
|
|
|
|
case S_INT:
|
|
|
|
base = 10;
|
|
|
|
break;
|
|
|
|
case S_HEX:
|
|
|
|
base = 16;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
prop = sym_get_range_prop(sym);
|
|
|
|
if (!prop)
|
|
|
|
return;
|
2013-07-19 02:32:01 +08:00
|
|
|
val = strtoll(sym->curr.val, NULL, base);
|
2023-11-15 12:16:53 +08:00
|
|
|
range_sym = prop->expr->left.sym;
|
|
|
|
val2 = sym_get_range_val(range_sym, base);
|
2005-11-09 13:34:49 +08:00
|
|
|
if (val >= val2) {
|
2023-11-15 12:16:53 +08:00
|
|
|
range_sym = prop->expr->right.sym;
|
|
|
|
val2 = sym_get_range_val(range_sym, base);
|
2005-11-09 13:34:49 +08:00
|
|
|
if (val <= val2)
|
|
|
|
return;
|
|
|
|
}
|
2023-11-15 12:16:53 +08:00
|
|
|
sym->curr.val = range_sym->curr.val;
|
2005-11-09 13:34:49 +08:00
|
|
|
}
|
|
|
|
|
2015-02-24 23:37:13 +08:00
|
|
|
static void sym_set_changed(struct symbol *sym)
|
|
|
|
{
|
2024-05-05 02:33:27 +08:00
|
|
|
struct menu *menu;
|
2015-02-24 23:37:13 +08:00
|
|
|
|
2024-05-05 02:33:27 +08:00
|
|
|
list_for_each_entry(menu, &sym->menus, link)
|
|
|
|
menu->flags |= MENU_CHANGED;
|
2015-02-24 23:37:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void sym_set_all_changed(void)
|
|
|
|
{
|
|
|
|
struct symbol *sym;
|
|
|
|
|
2024-02-11 20:41:05 +08:00
|
|
|
for_all_symbols(sym)
|
2015-02-24 23:37:13 +08:00
|
|
|
sym_set_changed(sym);
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static void sym_calc_visibility(struct symbol *sym)
|
|
|
|
{
|
|
|
|
struct property *prop;
|
|
|
|
tristate tri;
|
|
|
|
|
|
|
|
/* any prompt visible? */
|
|
|
|
tri = no;
|
|
|
|
for_all_prompts(sym, prop) {
|
|
|
|
prop->visible.tri = expr_calc_value(prop->visible.expr);
|
2008-01-08 04:09:55 +08:00
|
|
|
tri = EXPR_OR(tri, prop->visible.tri);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
|
|
|
|
tri = yes;
|
|
|
|
if (sym->visible != tri) {
|
|
|
|
sym->visible = tri;
|
|
|
|
sym_set_changed(sym);
|
|
|
|
}
|
|
|
|
if (sym_is_choice_value(sym))
|
|
|
|
return;
|
2010-06-09 00:25:57 +08:00
|
|
|
/* defaulting to "yes" if no explicit "depends on" are given */
|
|
|
|
tri = yes;
|
|
|
|
if (sym->dir_dep.expr)
|
|
|
|
tri = expr_calc_value(sym->dir_dep.expr);
|
2018-03-13 17:56:07 +08:00
|
|
|
if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
|
2010-06-09 00:25:57 +08:00
|
|
|
tri = yes;
|
|
|
|
if (sym->dir_dep.tri != tri) {
|
|
|
|
sym->dir_dep.tri = tri;
|
|
|
|
sym_set_changed(sym);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
tri = no;
|
|
|
|
if (sym->rev_dep.expr)
|
|
|
|
tri = expr_calc_value(sym->rev_dep.expr);
|
|
|
|
if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
|
|
|
|
tri = yes;
|
|
|
|
if (sym->rev_dep.tri != tri) {
|
|
|
|
sym->rev_dep.tri = tri;
|
|
|
|
sym_set_changed(sym);
|
|
|
|
}
|
2016-11-11 13:10:05 +08:00
|
|
|
tri = no;
|
2020-03-02 14:23:40 +08:00
|
|
|
if (sym->implied.expr)
|
2016-11-11 13:10:05 +08:00
|
|
|
tri = expr_calc_value(sym->implied.expr);
|
|
|
|
if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
|
|
|
|
tri = yes;
|
|
|
|
if (sym->implied.tri != tri) {
|
|
|
|
sym->implied.tri = tri;
|
|
|
|
sym_set_changed(sym);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2010-08-01 05:35:32 +08:00
|
|
|
/*
|
|
|
|
* Find the default symbol for a choice.
|
|
|
|
* First try the default values for the choice symbol
|
|
|
|
* Next locate the first visible choice value
|
|
|
|
* Return NULL if none was found
|
|
|
|
*/
|
2024-06-18 18:35:24 +08:00
|
|
|
struct symbol *sym_choice_default(struct menu *choice)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2024-06-18 18:35:25 +08:00
|
|
|
struct menu *menu;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct symbol *def_sym;
|
|
|
|
struct property *prop;
|
|
|
|
|
|
|
|
/* any of the defaults visible? */
|
2024-06-18 18:35:24 +08:00
|
|
|
for_all_defaults(choice->sym, prop) {
|
2005-04-17 06:20:36 +08:00
|
|
|
prop->visible.tri = expr_calc_value(prop->visible.expr);
|
|
|
|
if (prop->visible.tri == no)
|
|
|
|
continue;
|
|
|
|
def_sym = prop_get_symbol(prop);
|
|
|
|
if (def_sym->visible != no)
|
|
|
|
return def_sym;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* just get the first visible value */
|
2024-06-18 18:35:25 +08:00
|
|
|
menu_for_each_sub_entry(menu, choice)
|
|
|
|
if (menu->sym && menu->sym->visible != no)
|
|
|
|
return menu->sym;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2010-08-01 05:35:32 +08:00
|
|
|
/* failed to locate any defaults */
|
2005-04-17 06:20:36 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
/*
|
|
|
|
* sym_calc_choice - calculate symbol values in a choice
|
|
|
|
*
|
|
|
|
* @choice: a menu of the choice
|
|
|
|
*
|
|
|
|
* Return: a chosen symbol
|
|
|
|
*/
|
2024-06-18 18:35:22 +08:00
|
|
|
struct symbol *sym_calc_choice(struct menu *choice)
|
2010-08-01 05:35:32 +08:00
|
|
|
{
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
struct symbol *res = NULL;
|
|
|
|
struct symbol *sym;
|
|
|
|
struct menu *menu;
|
2010-08-01 05:35:32 +08:00
|
|
|
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
/* Traverse the list of choice members in the priority order. */
|
|
|
|
list_for_each_entry(sym, &choice->choice_members, choice_link) {
|
|
|
|
sym_calc_visibility(sym);
|
|
|
|
if (sym->visible == no)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* The first visible symble with the user value 'y'. */
|
|
|
|
if (sym_has_value(sym) && sym->def[S_DEF_USER].tri == yes) {
|
|
|
|
res = sym;
|
|
|
|
break;
|
|
|
|
}
|
2012-01-24 06:29:05 +08:00
|
|
|
}
|
|
|
|
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
/*
|
|
|
|
* If 'y' is not found in the user input, use the default, unless it is
|
|
|
|
* explicitly set to 'n'.
|
|
|
|
*/
|
|
|
|
if (!res) {
|
2024-06-18 18:35:24 +08:00
|
|
|
res = sym_choice_default(choice);
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
if (res && sym_has_value(res) && res->def[S_DEF_USER].tri == no)
|
|
|
|
res = NULL;
|
|
|
|
}
|
2010-08-01 05:35:32 +08:00
|
|
|
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
/* Still not found. Pick up the first visible, user-unspecified symbol. */
|
|
|
|
if (!res) {
|
|
|
|
menu_for_each_sub_entry(menu, choice) {
|
|
|
|
sym = menu->sym;
|
2010-08-01 05:35:32 +08:00
|
|
|
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
if (!sym || sym->visible == no || sym_has_value(sym))
|
|
|
|
continue;
|
2010-08-01 05:35:32 +08:00
|
|
|
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
res = sym;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Still not found. Traverse the linked list in the _reverse_ order to
|
|
|
|
* pick up the least prioritized 'n'.
|
|
|
|
*/
|
|
|
|
if (!res) {
|
|
|
|
list_for_each_entry_reverse(sym, &choice->choice_members,
|
|
|
|
choice_link) {
|
|
|
|
if (sym->visible == no)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
res = sym;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
menu_for_each_sub_entry(menu, choice) {
|
|
|
|
tristate val;
|
|
|
|
|
|
|
|
sym = menu->sym;
|
|
|
|
|
|
|
|
if (!sym || sym->visible == no)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
val = sym == res ? yes : no;
|
2010-08-01 05:35:32 +08:00
|
|
|
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
if (sym->curr.tri != val)
|
|
|
|
sym_set_changed(sym);
|
|
|
|
|
|
|
|
sym->curr.tri = val;
|
|
|
|
sym->flags |= SYMBOL_VALID | SYMBOL_WRITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2024-07-07 23:38:05 +08:00
|
|
|
static void sym_warn_unmet_dep(const struct symbol *sym)
|
kconfig: make unmet dependency warnings readable
Currently, the unmet dependency warnings end up with endlessly long
expressions, most of which are false positives.
Here is test code to demonstrate how it currently works.
[Test Case]
config DEP1
def_bool y
config DEP2
bool "DEP2"
config A
bool "A"
select E
config B
bool "B"
depends on DEP2
select E
config C
bool "C"
depends on DEP1 && DEP2
select E
config D
def_bool n
select E
config E
bool
depends on DEP1 && DEP2
[Result]
$ make config
scripts/kconfig/conf --oldaskconfig Kconfig
*
* Linux Kernel Configuration
*
DEP2 (DEP2) [N/y/?] (NEW) n
A (A) [N/y/?] (NEW) y
warning: (A && B && D) selects E which has unmet direct
dependencies (DEP1 && DEP2)
Here, I see some points to be improved.
First, '(A || B || D)' would make more sense than '(A && B && D)'.
I am not sure if this is intentional, but expr_simplify_unmet_dep()
turns OR expressions into AND, like follows:
case E_OR:
return expr_alloc_and(
Second, we see false positives. 'A' is a real unmet dependency.
'B' is false positive because 'DEP1' is fixed to 'y', and 'B' depends
on 'DEP2'. 'C' was correctly dropped by expr_simplify_unmet_dep().
'D' is also false positive because it has no chance to be enabled.
Current expr_simplify_unmet_dep() cannot avoid those false positives.
After all, I decided to use the same helpers as used for printing
reverse dependencies in the help.
With this commit, unreadable warnings (most of the reported symbols are
false positives) in the real world:
$ make ARCH=score allyesconfig
scripts/kconfig/conf --allyesconfig Kconfig
warning: (HWSPINLOCK_QCOM && AHCI_MTK && STMMAC_PLATFORM &&
DWMAC_IPQ806X && DWMAC_LPC18XX && DWMAC_OXNAS && DWMAC_ROCKCHIP &&
DWMAC_SOCFPGA && DWMAC_STI && TI_CPSW && PINCTRL_GEMINI &&
PINCTRL_OXNAS && PINCTRL_ROCKCHIP && PINCTRL_DOVE &&
PINCTRL_ARMADA_37XX && PINCTRL_STM32 && S3C2410_WATCHDOG &&
VIDEO_OMAP3 && VIDEO_S5P_FIMC && USB_XHCI_MTK && RTC_DRV_AT91SAM9 &&
LPC18XX_DMAMUX && VIDEO_OMAP4 && COMMON_CLK_GEMINI &&
COMMON_CLK_ASPEED && COMMON_CLK_NXP && COMMON_CLK_OXNAS &&
COMMON_CLK_BOSTON && QCOM_ADSP_PIL && QCOM_Q6V5_PIL && QCOM_GSBI &&
ATMEL_EBI && ST_IRQCHIP && RESET_IMX7 && PHY_HI6220_USB &&
PHY_RALINK_USB && PHY_ROCKCHIP_PCIE && PHY_DA8XX_USB) selects
MFD_SYSCON which has unmet direct dependencies (HAS_IOMEM)
warning: (PINCTRL_AT91 && PINCTRL_AT91PIO4 && PINCTRL_OXNAS &&
PINCTRL_PISTACHIO && PINCTRL_PIC32 && PINCTRL_MESON &&
PINCTRL_NOMADIK && PINCTRL_MTK && PINCTRL_MT7622 && GPIO_TB10X)
selects OF_GPIO which has unmet direct dependencies (GPIOLIB && OF &&
HAS_IOMEM)
warning: (FAULT_INJECTION_STACKTRACE_FILTER && LATENCYTOP && LOCKDEP)
selects FRAME_POINTER which has unmet direct dependencies
(DEBUG_KERNEL && (CRIS || M68K || FRV || UML || SUPERH || BLACKFIN ||
MN10300 || METAG) || ARCH_WANT_FRAME_POINTERS)
will be turned into:
$ make ARCH=score allyesconfig
scripts/kconfig/conf --allyesconfig Kconfig
WARNING: unmet direct dependencies detected for MFD_SYSCON
Depends on [n]: HAS_IOMEM [=n]
Selected by [y]:
- PINCTRL_STM32 [=y] && PINCTRL [=y] && (ARCH_STM32 ||
COMPILE_TEST [=y]) && OF [=y]
- RTC_DRV_AT91SAM9 [=y] && RTC_CLASS [=y] && (ARCH_AT91 ||
COMPILE_TEST [=y])
- RESET_IMX7 [=y] && RESET_CONTROLLER [=y]
- PHY_HI6220_USB [=y] && (ARCH_HISI && ARM64 ||
COMPILE_TEST [=y])
- PHY_RALINK_USB [=y] && (RALINK || COMPILE_TEST [=y])
- PHY_ROCKCHIP_PCIE [=y] && (ARCH_ROCKCHIP && OF [=y] ||
COMPILE_TEST [=y])
WARNING: unmet direct dependencies detected for OF_GPIO
Depends on [n]: GPIOLIB [=y] && OF [=y] && HAS_IOMEM [=n]
Selected by [y]:
- PINCTRL_MTK [=y] && PINCTRL [=y] && (ARCH_MEDIATEK ||
COMPILE_TEST [=y]) && OF [=y]
- PINCTRL_MT7622 [=y] && PINCTRL [=y] && (ARCH_MEDIATEK ||
COMPILE_TEST [=y]) && OF [=y] && (ARM64 || COMPILE_TEST [=y])
WARNING: unmet direct dependencies detected for FRAME_POINTER
Depends on [n]: DEBUG_KERNEL [=y] && (CRIS || M68K || FRV || UML ||
SUPERH || BLACKFIN || MN10300 || METAG) || ARCH_WANT_FRAME_POINTERS [=n]
Selected by [y]:
- LATENCYTOP [=y] && DEBUG_KERNEL [=y] && STACKTRACE_SUPPORT [=y] &&
PROC_FS [=y] && !MIPS && !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND &&
!ARC && !X86
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Reviewed-by: Petr Vorel <petr.vorel@gmail.com>
2018-03-13 17:56:08 +08:00
|
|
|
{
|
|
|
|
struct gstr gs = str_new();
|
|
|
|
|
|
|
|
str_printf(&gs,
|
|
|
|
"\nWARNING: unmet direct dependencies detected for %s\n",
|
|
|
|
sym->name);
|
|
|
|
str_printf(&gs,
|
|
|
|
" Depends on [%c]: ",
|
|
|
|
sym->dir_dep.tri == mod ? 'm' : 'n');
|
|
|
|
expr_gstr_print(sym->dir_dep.expr, &gs);
|
|
|
|
str_printf(&gs, "\n");
|
|
|
|
|
|
|
|
expr_gstr_print_revdep(sym->rev_dep.expr, &gs, yes,
|
|
|
|
" Selected by [y]:\n");
|
|
|
|
expr_gstr_print_revdep(sym->rev_dep.expr, &gs, mod,
|
|
|
|
" Selected by [m]:\n");
|
|
|
|
|
|
|
|
fputs(str_get(&gs), stderr);
|
2023-11-22 11:47:45 +08:00
|
|
|
sym_warnings++;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool sym_dep_errors(void)
|
|
|
|
{
|
|
|
|
if (sym_warnings)
|
|
|
|
return getenv("KCONFIG_WERROR");
|
|
|
|
return false;
|
kconfig: make unmet dependency warnings readable
Currently, the unmet dependency warnings end up with endlessly long
expressions, most of which are false positives.
Here is test code to demonstrate how it currently works.
[Test Case]
config DEP1
def_bool y
config DEP2
bool "DEP2"
config A
bool "A"
select E
config B
bool "B"
depends on DEP2
select E
config C
bool "C"
depends on DEP1 && DEP2
select E
config D
def_bool n
select E
config E
bool
depends on DEP1 && DEP2
[Result]
$ make config
scripts/kconfig/conf --oldaskconfig Kconfig
*
* Linux Kernel Configuration
*
DEP2 (DEP2) [N/y/?] (NEW) n
A (A) [N/y/?] (NEW) y
warning: (A && B && D) selects E which has unmet direct
dependencies (DEP1 && DEP2)
Here, I see some points to be improved.
First, '(A || B || D)' would make more sense than '(A && B && D)'.
I am not sure if this is intentional, but expr_simplify_unmet_dep()
turns OR expressions into AND, like follows:
case E_OR:
return expr_alloc_and(
Second, we see false positives. 'A' is a real unmet dependency.
'B' is false positive because 'DEP1' is fixed to 'y', and 'B' depends
on 'DEP2'. 'C' was correctly dropped by expr_simplify_unmet_dep().
'D' is also false positive because it has no chance to be enabled.
Current expr_simplify_unmet_dep() cannot avoid those false positives.
After all, I decided to use the same helpers as used for printing
reverse dependencies in the help.
With this commit, unreadable warnings (most of the reported symbols are
false positives) in the real world:
$ make ARCH=score allyesconfig
scripts/kconfig/conf --allyesconfig Kconfig
warning: (HWSPINLOCK_QCOM && AHCI_MTK && STMMAC_PLATFORM &&
DWMAC_IPQ806X && DWMAC_LPC18XX && DWMAC_OXNAS && DWMAC_ROCKCHIP &&
DWMAC_SOCFPGA && DWMAC_STI && TI_CPSW && PINCTRL_GEMINI &&
PINCTRL_OXNAS && PINCTRL_ROCKCHIP && PINCTRL_DOVE &&
PINCTRL_ARMADA_37XX && PINCTRL_STM32 && S3C2410_WATCHDOG &&
VIDEO_OMAP3 && VIDEO_S5P_FIMC && USB_XHCI_MTK && RTC_DRV_AT91SAM9 &&
LPC18XX_DMAMUX && VIDEO_OMAP4 && COMMON_CLK_GEMINI &&
COMMON_CLK_ASPEED && COMMON_CLK_NXP && COMMON_CLK_OXNAS &&
COMMON_CLK_BOSTON && QCOM_ADSP_PIL && QCOM_Q6V5_PIL && QCOM_GSBI &&
ATMEL_EBI && ST_IRQCHIP && RESET_IMX7 && PHY_HI6220_USB &&
PHY_RALINK_USB && PHY_ROCKCHIP_PCIE && PHY_DA8XX_USB) selects
MFD_SYSCON which has unmet direct dependencies (HAS_IOMEM)
warning: (PINCTRL_AT91 && PINCTRL_AT91PIO4 && PINCTRL_OXNAS &&
PINCTRL_PISTACHIO && PINCTRL_PIC32 && PINCTRL_MESON &&
PINCTRL_NOMADIK && PINCTRL_MTK && PINCTRL_MT7622 && GPIO_TB10X)
selects OF_GPIO which has unmet direct dependencies (GPIOLIB && OF &&
HAS_IOMEM)
warning: (FAULT_INJECTION_STACKTRACE_FILTER && LATENCYTOP && LOCKDEP)
selects FRAME_POINTER which has unmet direct dependencies
(DEBUG_KERNEL && (CRIS || M68K || FRV || UML || SUPERH || BLACKFIN ||
MN10300 || METAG) || ARCH_WANT_FRAME_POINTERS)
will be turned into:
$ make ARCH=score allyesconfig
scripts/kconfig/conf --allyesconfig Kconfig
WARNING: unmet direct dependencies detected for MFD_SYSCON
Depends on [n]: HAS_IOMEM [=n]
Selected by [y]:
- PINCTRL_STM32 [=y] && PINCTRL [=y] && (ARCH_STM32 ||
COMPILE_TEST [=y]) && OF [=y]
- RTC_DRV_AT91SAM9 [=y] && RTC_CLASS [=y] && (ARCH_AT91 ||
COMPILE_TEST [=y])
- RESET_IMX7 [=y] && RESET_CONTROLLER [=y]
- PHY_HI6220_USB [=y] && (ARCH_HISI && ARM64 ||
COMPILE_TEST [=y])
- PHY_RALINK_USB [=y] && (RALINK || COMPILE_TEST [=y])
- PHY_ROCKCHIP_PCIE [=y] && (ARCH_ROCKCHIP && OF [=y] ||
COMPILE_TEST [=y])
WARNING: unmet direct dependencies detected for OF_GPIO
Depends on [n]: GPIOLIB [=y] && OF [=y] && HAS_IOMEM [=n]
Selected by [y]:
- PINCTRL_MTK [=y] && PINCTRL [=y] && (ARCH_MEDIATEK ||
COMPILE_TEST [=y]) && OF [=y]
- PINCTRL_MT7622 [=y] && PINCTRL [=y] && (ARCH_MEDIATEK ||
COMPILE_TEST [=y]) && OF [=y] && (ARM64 || COMPILE_TEST [=y])
WARNING: unmet direct dependencies detected for FRAME_POINTER
Depends on [n]: DEBUG_KERNEL [=y] && (CRIS || M68K || FRV || UML ||
SUPERH || BLACKFIN || MN10300 || METAG) || ARCH_WANT_FRAME_POINTERS [=n]
Selected by [y]:
- LATENCYTOP [=y] && DEBUG_KERNEL [=y] && STACKTRACE_SUPPORT [=y] &&
PROC_FS [=y] && !MIPS && !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND &&
!ARC && !X86
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Reviewed-by: Petr Vorel <petr.vorel@gmail.com>
2018-03-13 17:56:08 +08:00
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
void sym_calc_value(struct symbol *sym)
|
|
|
|
{
|
|
|
|
struct symbol_value newval, oldval;
|
|
|
|
struct property *prop;
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
struct menu *choice_menu;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (!sym)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (sym->flags & SYMBOL_VALID)
|
|
|
|
return;
|
2013-06-07 11:37:00 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
sym->flags |= SYMBOL_VALID;
|
|
|
|
|
|
|
|
oldval = sym->curr;
|
|
|
|
|
kconfig: initialize sym->curr.tri to 'no' for all symbol types again
Geert Uytterhoeven reported that commit 4e244c10eab3 ("kconfig: remove
unneeded symbol_empty variable") changed the default value of
CONFIG_LOG_CPU_MAX_BUF_SHIFT from 12 to 0.
As it turned out, this is an undefined behavior because sym_calc_value()
stopped setting the sym->curr.tri field for 'int', 'hex', and 'string'
symbols.
This commit restores the original behavior, where 'int', 'hex', 'string'
symbols are interpreted as false if used in boolean contexts.
CONFIG_LOG_CPU_MAX_BUF_SHIFT will default to 12 again, irrespective
of CONFIG_BASE_SMALL. Presumably, this is not the intended behavior,
as already reported [1], but this is another issue that should be
addressed by a separate patch.
[1]: https://lore.kernel.org/all/f6856be8-54b7-0fa0-1d17-39632bf29ada@oracle.com/
Fixes: 4e244c10eab3 ("kconfig: remove unneeded symbol_empty variable")
Reported-by: Geert Uytterhoeven <geert+renesas@glider.be>
Closes: https://lore.kernel.org/all/CAMuHMdWm6u1wX7efZQf=2XUAHascps76YQac6rdnQGhc8nop_Q@mail.gmail.com/
Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-01-26 21:30:10 +08:00
|
|
|
newval.tri = no;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
switch (sym->type) {
|
|
|
|
case S_INT:
|
2023-11-26 00:35:59 +08:00
|
|
|
newval.val = "0";
|
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
case S_HEX:
|
2023-11-26 00:35:59 +08:00
|
|
|
newval.val = "0x0";
|
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
case S_STRING:
|
2023-11-26 00:35:58 +08:00
|
|
|
newval.val = "";
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
case S_BOOLEAN:
|
|
|
|
case S_TRISTATE:
|
kconfig: initialize sym->curr.tri to 'no' for all symbol types again
Geert Uytterhoeven reported that commit 4e244c10eab3 ("kconfig: remove
unneeded symbol_empty variable") changed the default value of
CONFIG_LOG_CPU_MAX_BUF_SHIFT from 12 to 0.
As it turned out, this is an undefined behavior because sym_calc_value()
stopped setting the sym->curr.tri field for 'int', 'hex', and 'string'
symbols.
This commit restores the original behavior, where 'int', 'hex', 'string'
symbols are interpreted as false if used in boolean contexts.
CONFIG_LOG_CPU_MAX_BUF_SHIFT will default to 12 again, irrespective
of CONFIG_BASE_SMALL. Presumably, this is not the intended behavior,
as already reported [1], but this is another issue that should be
addressed by a separate patch.
[1]: https://lore.kernel.org/all/f6856be8-54b7-0fa0-1d17-39632bf29ada@oracle.com/
Fixes: 4e244c10eab3 ("kconfig: remove unneeded symbol_empty variable")
Reported-by: Geert Uytterhoeven <geert+renesas@glider.be>
Closes: https://lore.kernel.org/all/CAMuHMdWm6u1wX7efZQf=2XUAHascps76YQac6rdnQGhc8nop_Q@mail.gmail.com/
Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-01-26 21:30:10 +08:00
|
|
|
newval.val = "n";
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sym->curr.val = sym->name;
|
|
|
|
sym->curr.tri = no;
|
|
|
|
return;
|
|
|
|
}
|
2018-02-06 08:34:42 +08:00
|
|
|
sym->flags &= ~SYMBOL_WRITE;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
sym_calc_visibility(sym);
|
|
|
|
|
2018-02-06 08:34:42 +08:00
|
|
|
if (sym->visible != no)
|
|
|
|
sym->flags |= SYMBOL_WRITE;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/* set default if recursively called */
|
|
|
|
sym->curr = newval;
|
|
|
|
|
|
|
|
switch (sym_get_type(sym)) {
|
|
|
|
case S_BOOLEAN:
|
|
|
|
case S_TRISTATE:
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
choice_menu = sym_get_choice_menu(sym);
|
|
|
|
|
|
|
|
if (choice_menu) {
|
|
|
|
sym_calc_choice(choice_menu);
|
|
|
|
newval.tri = sym->curr.tri;
|
2008-02-12 04:13:47 +08:00
|
|
|
} else {
|
|
|
|
if (sym->visible != no) {
|
|
|
|
/* if the symbol is visible use the user value
|
|
|
|
* if available, otherwise try the default value
|
|
|
|
*/
|
|
|
|
if (sym_has_value(sym)) {
|
|
|
|
newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
|
|
|
|
sym->visible);
|
|
|
|
goto calc_newval;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2008-02-12 04:13:47 +08:00
|
|
|
if (sym->rev_dep.tri != no)
|
2005-04-17 06:20:36 +08:00
|
|
|
sym->flags |= SYMBOL_WRITE;
|
2008-02-12 04:13:47 +08:00
|
|
|
if (!sym_is_choice(sym)) {
|
|
|
|
prop = sym_get_default_prop(sym);
|
|
|
|
if (prop) {
|
|
|
|
newval.tri = EXPR_AND(expr_calc_value(prop->expr),
|
|
|
|
prop->visible.tri);
|
kconfig: only write '# CONFIG_FOO is not set' for visible symbols
=== Background ===
- Visible n-valued bool/tristate symbols generate a
'# CONFIG_FOO is not set' line in the .config file. The idea is to
remember the user selection without having to set a Makefile
variable. Having n correspond to the variable being undefined in the
Makefiles makes for easy CONFIG_* tests.
- Invisible n-valued bool/tristate symbols normally do not generate a
'# CONFIG_FOO is not set' line, because user values from .config
files have no effect on invisible symbols anyway.
Currently, there is one exception to this rule: Any bool/tristate symbol
that gets the value n through a 'default' property generates a
'# CONFIG_FOO is not set' line, even if the symbol is invisible.
Note that this only applies to explicitly given defaults, and not when
the symbol implicitly defaults to n (like bool/tristate symbols without
'default' properties do).
This is inconsistent, and seems redundant:
- As mentioned, the '# CONFIG_FOO is not set' won't affect the symbol
once the .config is read back in.
- Even if the symbol is invisible at first but becomes visible later,
there shouldn't be any harm in recalculating the default value
rather than viewing the '# CONFIG_FOO is not set' as a previous
user value of n.
=== Changes ===
Change sym_calc_value() to only set SYMBOL_WRITE (write to .config) for
non-n-valued 'default' properties.
Note that SYMBOL_WRITE is always set for visible symbols regardless of whether
they have 'default' properties or not, so this change only affects invisible
symbols.
This reduces the size of the x86 .config on my system by about 1% (due
to removed '# CONFIG_FOO is not set' entries).
One side effect of (and the main motivation for) this change is making
the following two definitions behave exactly the same:
config FOO
bool
config FOO
bool
default n
With this change, neither of these will generate a
'# CONFIG_FOO is not set' line (assuming FOO isn't selected/implied).
That might make it clearer to people that a bare 'default n' is
redundant.
This change only affects generated .config files and not autoconf.h:
autoconf.h only includes #defines for non-n bool/tristate symbols.
=== Testing ===
The following testing was done with the x86 Kconfigs:
- .config files generated before and after the change were compared to
verify that the only difference is some '# CONFIG_FOO is not set'
entries disappearing. A couple of these were inspected manually, and
most turned out to be from redundant 'default n/def_bool n'
properties.
- The generated include/generated/autoconf.h was compared before and
after the change and verified to be identical.
- As a sanity check, the same modification was done to Kconfiglib.
The Kconfiglib test suite was then run to check for any mismatches
against the output of the C implementation.
Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2018-02-23 19:49:01 +08:00
|
|
|
if (newval.tri != no)
|
|
|
|
sym->flags |= SYMBOL_WRITE;
|
2008-02-12 04:13:47 +08:00
|
|
|
}
|
2016-11-11 13:10:05 +08:00
|
|
|
if (sym->implied.tri != no) {
|
|
|
|
sym->flags |= SYMBOL_WRITE;
|
|
|
|
newval.tri = EXPR_OR(newval.tri, sym->implied.tri);
|
2020-03-02 14:23:40 +08:00
|
|
|
newval.tri = EXPR_AND(newval.tri,
|
|
|
|
sym->dir_dep.tri);
|
2016-11-11 13:10:05 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2008-02-12 04:13:47 +08:00
|
|
|
calc_newval:
|
kconfig: make unmet dependency warnings readable
Currently, the unmet dependency warnings end up with endlessly long
expressions, most of which are false positives.
Here is test code to demonstrate how it currently works.
[Test Case]
config DEP1
def_bool y
config DEP2
bool "DEP2"
config A
bool "A"
select E
config B
bool "B"
depends on DEP2
select E
config C
bool "C"
depends on DEP1 && DEP2
select E
config D
def_bool n
select E
config E
bool
depends on DEP1 && DEP2
[Result]
$ make config
scripts/kconfig/conf --oldaskconfig Kconfig
*
* Linux Kernel Configuration
*
DEP2 (DEP2) [N/y/?] (NEW) n
A (A) [N/y/?] (NEW) y
warning: (A && B && D) selects E which has unmet direct
dependencies (DEP1 && DEP2)
Here, I see some points to be improved.
First, '(A || B || D)' would make more sense than '(A && B && D)'.
I am not sure if this is intentional, but expr_simplify_unmet_dep()
turns OR expressions into AND, like follows:
case E_OR:
return expr_alloc_and(
Second, we see false positives. 'A' is a real unmet dependency.
'B' is false positive because 'DEP1' is fixed to 'y', and 'B' depends
on 'DEP2'. 'C' was correctly dropped by expr_simplify_unmet_dep().
'D' is also false positive because it has no chance to be enabled.
Current expr_simplify_unmet_dep() cannot avoid those false positives.
After all, I decided to use the same helpers as used for printing
reverse dependencies in the help.
With this commit, unreadable warnings (most of the reported symbols are
false positives) in the real world:
$ make ARCH=score allyesconfig
scripts/kconfig/conf --allyesconfig Kconfig
warning: (HWSPINLOCK_QCOM && AHCI_MTK && STMMAC_PLATFORM &&
DWMAC_IPQ806X && DWMAC_LPC18XX && DWMAC_OXNAS && DWMAC_ROCKCHIP &&
DWMAC_SOCFPGA && DWMAC_STI && TI_CPSW && PINCTRL_GEMINI &&
PINCTRL_OXNAS && PINCTRL_ROCKCHIP && PINCTRL_DOVE &&
PINCTRL_ARMADA_37XX && PINCTRL_STM32 && S3C2410_WATCHDOG &&
VIDEO_OMAP3 && VIDEO_S5P_FIMC && USB_XHCI_MTK && RTC_DRV_AT91SAM9 &&
LPC18XX_DMAMUX && VIDEO_OMAP4 && COMMON_CLK_GEMINI &&
COMMON_CLK_ASPEED && COMMON_CLK_NXP && COMMON_CLK_OXNAS &&
COMMON_CLK_BOSTON && QCOM_ADSP_PIL && QCOM_Q6V5_PIL && QCOM_GSBI &&
ATMEL_EBI && ST_IRQCHIP && RESET_IMX7 && PHY_HI6220_USB &&
PHY_RALINK_USB && PHY_ROCKCHIP_PCIE && PHY_DA8XX_USB) selects
MFD_SYSCON which has unmet direct dependencies (HAS_IOMEM)
warning: (PINCTRL_AT91 && PINCTRL_AT91PIO4 && PINCTRL_OXNAS &&
PINCTRL_PISTACHIO && PINCTRL_PIC32 && PINCTRL_MESON &&
PINCTRL_NOMADIK && PINCTRL_MTK && PINCTRL_MT7622 && GPIO_TB10X)
selects OF_GPIO which has unmet direct dependencies (GPIOLIB && OF &&
HAS_IOMEM)
warning: (FAULT_INJECTION_STACKTRACE_FILTER && LATENCYTOP && LOCKDEP)
selects FRAME_POINTER which has unmet direct dependencies
(DEBUG_KERNEL && (CRIS || M68K || FRV || UML || SUPERH || BLACKFIN ||
MN10300 || METAG) || ARCH_WANT_FRAME_POINTERS)
will be turned into:
$ make ARCH=score allyesconfig
scripts/kconfig/conf --allyesconfig Kconfig
WARNING: unmet direct dependencies detected for MFD_SYSCON
Depends on [n]: HAS_IOMEM [=n]
Selected by [y]:
- PINCTRL_STM32 [=y] && PINCTRL [=y] && (ARCH_STM32 ||
COMPILE_TEST [=y]) && OF [=y]
- RTC_DRV_AT91SAM9 [=y] && RTC_CLASS [=y] && (ARCH_AT91 ||
COMPILE_TEST [=y])
- RESET_IMX7 [=y] && RESET_CONTROLLER [=y]
- PHY_HI6220_USB [=y] && (ARCH_HISI && ARM64 ||
COMPILE_TEST [=y])
- PHY_RALINK_USB [=y] && (RALINK || COMPILE_TEST [=y])
- PHY_ROCKCHIP_PCIE [=y] && (ARCH_ROCKCHIP && OF [=y] ||
COMPILE_TEST [=y])
WARNING: unmet direct dependencies detected for OF_GPIO
Depends on [n]: GPIOLIB [=y] && OF [=y] && HAS_IOMEM [=n]
Selected by [y]:
- PINCTRL_MTK [=y] && PINCTRL [=y] && (ARCH_MEDIATEK ||
COMPILE_TEST [=y]) && OF [=y]
- PINCTRL_MT7622 [=y] && PINCTRL [=y] && (ARCH_MEDIATEK ||
COMPILE_TEST [=y]) && OF [=y] && (ARM64 || COMPILE_TEST [=y])
WARNING: unmet direct dependencies detected for FRAME_POINTER
Depends on [n]: DEBUG_KERNEL [=y] && (CRIS || M68K || FRV || UML ||
SUPERH || BLACKFIN || MN10300 || METAG) || ARCH_WANT_FRAME_POINTERS [=n]
Selected by [y]:
- LATENCYTOP [=y] && DEBUG_KERNEL [=y] && STACKTRACE_SUPPORT [=y] &&
PROC_FS [=y] && !MIPS && !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND &&
!ARC && !X86
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Reviewed-by: Petr Vorel <petr.vorel@gmail.com>
2018-03-13 17:56:08 +08:00
|
|
|
if (sym->dir_dep.tri < sym->rev_dep.tri)
|
|
|
|
sym_warn_unmet_dep(sym);
|
2008-02-12 04:13:47 +08:00
|
|
|
newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2020-03-02 14:23:39 +08:00
|
|
|
if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
|
2005-04-17 06:20:36 +08:00
|
|
|
newval.tri = yes;
|
|
|
|
break;
|
|
|
|
case S_STRING:
|
|
|
|
case S_HEX:
|
|
|
|
case S_INT:
|
2018-02-06 08:34:42 +08:00
|
|
|
if (sym->visible != no && sym_has_value(sym)) {
|
|
|
|
newval.val = sym->def[S_DEF_USER].val;
|
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
prop = sym_get_default_prop(sym);
|
|
|
|
if (prop) {
|
|
|
|
struct symbol *ds = prop_get_symbol(prop);
|
|
|
|
if (ds) {
|
|
|
|
sym->flags |= SYMBOL_WRITE;
|
|
|
|
sym_calc_value(ds);
|
|
|
|
newval.val = ds->curr.val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
sym->curr = newval;
|
2005-11-09 13:34:49 +08:00
|
|
|
sym_validate_range(sym);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-06-09 13:12:45 +08:00
|
|
|
if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
|
2005-04-17 06:20:36 +08:00
|
|
|
sym_set_changed(sym);
|
2006-06-09 13:12:45 +08:00
|
|
|
if (modules_sym == sym) {
|
|
|
|
sym_set_all_changed();
|
|
|
|
modules_val = modules_sym->curr.tri;
|
|
|
|
}
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
if (sym_is_choice(sym))
|
2008-02-29 12:11:50 +08:00
|
|
|
sym->flags &= ~SYMBOL_WRITE;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void sym_clear_all_valid(void)
|
|
|
|
{
|
|
|
|
struct symbol *sym;
|
|
|
|
|
2024-02-11 20:41:05 +08:00
|
|
|
for_all_symbols(sym)
|
2005-04-17 06:20:36 +08:00
|
|
|
sym->flags &= ~SYMBOL_VALID;
|
2024-09-08 20:43:21 +08:00
|
|
|
expr_invalidate_all();
|
2021-04-10 14:57:22 +08:00
|
|
|
conf_set_changed(true);
|
2015-07-08 03:48:23 +08:00
|
|
|
sym_calc_value(modules_sym);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2024-07-07 23:38:05 +08:00
|
|
|
bool sym_tristate_within_range(const struct symbol *sym, tristate val)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
int type = sym_get_type(sym);
|
|
|
|
|
|
|
|
if (sym->visible == no)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (type != S_BOOLEAN && type != S_TRISTATE)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (type == S_BOOLEAN && val == mod)
|
|
|
|
return false;
|
|
|
|
if (sym->visible <= sym->rev_dep.tri)
|
|
|
|
return false;
|
|
|
|
return val >= sym->rev_dep.tri && val <= sym->visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool sym_set_tristate_value(struct symbol *sym, tristate val)
|
|
|
|
{
|
|
|
|
tristate oldval = sym_get_tristate_value(sym);
|
|
|
|
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
if (!sym_tristate_within_range(sym, val))
|
2005-04-17 06:20:36 +08:00
|
|
|
return false;
|
|
|
|
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
if (!(sym->flags & SYMBOL_DEF_USER) || sym->def[S_DEF_USER].tri != val) {
|
|
|
|
sym->def[S_DEF_USER].tri = val;
|
2006-06-09 13:12:42 +08:00
|
|
|
sym->flags |= SYMBOL_DEF_USER;
|
2005-04-17 06:20:36 +08:00
|
|
|
sym_set_changed(sym);
|
|
|
|
}
|
|
|
|
|
2006-06-09 13:12:45 +08:00
|
|
|
if (oldval != val)
|
2005-04-17 06:20:36 +08:00
|
|
|
sym_clear_all_valid();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-06-12 01:55:12 +08:00
|
|
|
/**
|
|
|
|
* choice_set_value - set the user input to a choice
|
|
|
|
*
|
|
|
|
* @choice: menu entry for the choice
|
|
|
|
* @sym: selected symbol
|
|
|
|
*/
|
|
|
|
void choice_set_value(struct menu *choice, struct symbol *sym)
|
|
|
|
{
|
|
|
|
struct menu *menu;
|
|
|
|
bool changed = false;
|
|
|
|
|
|
|
|
menu_for_each_sub_entry(menu, choice) {
|
|
|
|
tristate val;
|
|
|
|
|
|
|
|
if (!menu->sym)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (menu->sym->visible == no)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
val = menu->sym == sym ? yes : no;
|
|
|
|
|
|
|
|
if (menu->sym->curr.tri != val)
|
|
|
|
changed = true;
|
|
|
|
|
|
|
|
menu->sym->def[S_DEF_USER].tri = val;
|
|
|
|
menu->sym->flags |= SYMBOL_DEF_USER;
|
|
|
|
|
kconfig: refactor choice value calculation
Handling choices has always been in a PITA in Kconfig.
For example, fixes and reverts were repeated for randconfig with
KCONFIG_ALLCONFIG:
- 422c809f03f0 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 23a5dfdad22a ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
- 8357b48549e1 ("kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG")
- 490f16171119 ("Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG"")
As these commits pointed out, randconfig does not randomize choices when
KCONFIG_ALLCONFIG is used. This issue still remains.
[Test Case]
choice
prompt "choose"
config A
bool "A"
config B
bool "B"
endchoice
$ echo > all.config
$ make KCONFIG_ALLCONFIG=1 randconfig
The output is always as follows:
CONFIG_A=y
# CONFIG_B is not set
Not only randconfig, but other all*config variants are also broken with
KCONFIG_ALLCONFIG.
With the same Kconfig,
$ echo '# CONFIG_A is not set' > all.config
$ make KCONFIG_ALLCONFIG=1 allyesconfig
You will get this:
CONFIG_A=y
# CONFIG_B is not set
This is incorrect because it does not respect all.config.
The correct output should be:
# CONFIG_A is not set
CONFIG_B=y
To handle user inputs more accurately, this commit refactors the code
based on the following principles:
- When a user value is given, Kconfig must set it immediately.
Do not defer it by setting SYMBOL_NEED_SET_CHOICE_VALUES.
- The SYMBOL_DEF_USER flag must not be cleared, unless a new config
file is loaded. Kconfig must not forget user inputs.
In addition, user values for choices must be managed with priority.
If user inputs conflict within a choice block, the newest value wins.
The values given by randconfig have lower priority than explicit user
inputs.
This commit implements it by using a linked list. Every time a choice
block gets a new input, it is moved to the top of the list.
Let me explain how it works.
Let's say, we have a choice block that consists of five symbols:
A, B, C, D, and E.
Initially, the linked list looks like this:
A(=?) --> B(=?) --> C(=?) --> D(=?) --> E(=?)
Suppose randconfig is executed with the following KCONFIG_ALLCONFIG:
CONFIG_C=y
# CONFIG_A is not set
CONFIG_D=y
First, CONFIG_C=y is read. C is set to 'y' and moved to the top.
C(=y) --> A(=?) --> B(=?) --> D(=?) --> E(=?)
Next, '# CONFIG_A is not set' is read. A is set to 'n' and moved to
the top.
A(=n) --> C(=y) --> B(=?) --> D(=?) --> E(=?)
Then, 'CONFIG_D=y' is read. D is set to 'y' and moved to the top.
D(=y) --> A(=n) --> C(=y) --> B(=?) --> E(=?)
Lastly, randconfig shuffles the order of the remaining symbols,
resulting in:
D(=y) --> A(=n) --> C(=y) --> B(=y) --> E(=y)
or
D(=y) --> A(=n) --> C(=y) --> E(=y) --> B(=y)
When calculating the output, the linked list is traversed and the first
visible symbol with 'y' is taken. In this case, it is D if visible.
If D is hidden by 'depends on', the next node, A, is examined. Since
it is already specified as 'n', it is skipped. Next, C is checked, and
selected if it is visible.
If C is also invisible, either B or E is chosen as a result of the
randomization.
If B and E are also invisible, the linked list is traversed in the
reverse order, and the least prioritized 'n' symbol is chosen. It is
A in this case.
Now, Kconfig remembers all user values. This is a big difference from
the previous implementation, where Kconfig would forget CONFIG_C=y when
CONFIG_D=y appeared in the same input file.
The new appaorch respects user-specified values as much as possible.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-06-18 18:35:21 +08:00
|
|
|
/*
|
|
|
|
* Now, the user has explicitly enabled or disabled this symbol,
|
|
|
|
* it should be given the highest priority. We are possibly
|
|
|
|
* setting multiple symbols to 'n', where the first symbol is
|
|
|
|
* given the least prioritized 'n'. This works well when the
|
|
|
|
* choice block ends up with selecting 'n' symbol.
|
|
|
|
* (see sym_calc_choice())
|
|
|
|
*/
|
|
|
|
list_move(&menu->sym->choice_link, &choice->choice_members);
|
|
|
|
}
|
2024-06-12 01:55:12 +08:00
|
|
|
|
|
|
|
if (changed)
|
|
|
|
sym_clear_all_valid();
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
tristate sym_toggle_tristate_value(struct symbol *sym)
|
|
|
|
{
|
2024-06-12 01:55:12 +08:00
|
|
|
struct menu *choice;
|
2005-04-17 06:20:36 +08:00
|
|
|
tristate oldval, newval;
|
|
|
|
|
2024-06-12 01:55:12 +08:00
|
|
|
choice = sym_get_choice_menu(sym);
|
|
|
|
if (choice) {
|
|
|
|
choice_set_value(choice, sym);
|
|
|
|
return yes;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
oldval = newval = sym_get_tristate_value(sym);
|
|
|
|
do {
|
|
|
|
switch (newval) {
|
|
|
|
case no:
|
|
|
|
newval = mod;
|
|
|
|
break;
|
|
|
|
case mod:
|
|
|
|
newval = yes;
|
|
|
|
break;
|
|
|
|
case yes:
|
|
|
|
newval = no;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (sym_set_tristate_value(sym, newval))
|
|
|
|
break;
|
|
|
|
} while (oldval != newval);
|
|
|
|
return newval;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool sym_string_valid(struct symbol *sym, const char *str)
|
|
|
|
{
|
|
|
|
signed char ch;
|
|
|
|
|
|
|
|
switch (sym->type) {
|
|
|
|
case S_STRING:
|
|
|
|
return true;
|
|
|
|
case S_INT:
|
|
|
|
ch = *str++;
|
|
|
|
if (ch == '-')
|
|
|
|
ch = *str++;
|
|
|
|
if (!isdigit(ch))
|
|
|
|
return false;
|
|
|
|
if (ch == '0' && *str != 0)
|
|
|
|
return false;
|
|
|
|
while ((ch = *str++)) {
|
|
|
|
if (!isdigit(ch))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
case S_HEX:
|
|
|
|
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
|
|
|
|
str += 2;
|
|
|
|
ch = *str++;
|
|
|
|
do {
|
|
|
|
if (!isxdigit(ch))
|
|
|
|
return false;
|
|
|
|
} while ((ch = *str++));
|
|
|
|
return true;
|
|
|
|
case S_BOOLEAN:
|
|
|
|
case S_TRISTATE:
|
|
|
|
switch (str[0]) {
|
|
|
|
case 'y': case 'Y':
|
|
|
|
case 'm': case 'M':
|
|
|
|
case 'n': case 'N':
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool sym_string_within_range(struct symbol *sym, const char *str)
|
|
|
|
{
|
|
|
|
struct property *prop;
|
2013-07-19 02:32:01 +08:00
|
|
|
long long val;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
switch (sym->type) {
|
|
|
|
case S_STRING:
|
|
|
|
return sym_string_valid(sym, str);
|
|
|
|
case S_INT:
|
|
|
|
if (!sym_string_valid(sym, str))
|
|
|
|
return false;
|
|
|
|
prop = sym_get_range_prop(sym);
|
|
|
|
if (!prop)
|
|
|
|
return true;
|
2013-07-19 02:32:01 +08:00
|
|
|
val = strtoll(str, NULL, 10);
|
2005-11-09 13:34:49 +08:00
|
|
|
return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
|
|
|
|
val <= sym_get_range_val(prop->expr->right.sym, 10);
|
2005-04-17 06:20:36 +08:00
|
|
|
case S_HEX:
|
|
|
|
if (!sym_string_valid(sym, str))
|
|
|
|
return false;
|
|
|
|
prop = sym_get_range_prop(sym);
|
|
|
|
if (!prop)
|
|
|
|
return true;
|
2013-07-19 02:32:01 +08:00
|
|
|
val = strtoll(str, NULL, 16);
|
2005-11-09 13:34:49 +08:00
|
|
|
return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
|
|
|
|
val <= sym_get_range_val(prop->expr->right.sym, 16);
|
2005-04-17 06:20:36 +08:00
|
|
|
case S_BOOLEAN:
|
|
|
|
case S_TRISTATE:
|
|
|
|
switch (str[0]) {
|
|
|
|
case 'y': case 'Y':
|
|
|
|
return sym_tristate_within_range(sym, yes);
|
|
|
|
case 'm': case 'M':
|
|
|
|
return sym_tristate_within_range(sym, mod);
|
|
|
|
case 'n': case 'N':
|
|
|
|
return sym_tristate_within_range(sym, no);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool sym_set_string_value(struct symbol *sym, const char *newval)
|
|
|
|
{
|
|
|
|
const char *oldval;
|
|
|
|
char *val;
|
|
|
|
int size;
|
|
|
|
|
|
|
|
switch (sym->type) {
|
|
|
|
case S_BOOLEAN:
|
|
|
|
case S_TRISTATE:
|
|
|
|
switch (newval[0]) {
|
|
|
|
case 'y': case 'Y':
|
|
|
|
return sym_set_tristate_value(sym, yes);
|
|
|
|
case 'm': case 'M':
|
|
|
|
return sym_set_tristate_value(sym, mod);
|
|
|
|
case 'n': case 'N':
|
|
|
|
return sym_set_tristate_value(sym, no);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sym_string_within_range(sym, newval))
|
|
|
|
return false;
|
|
|
|
|
2006-06-09 13:12:42 +08:00
|
|
|
if (!(sym->flags & SYMBOL_DEF_USER)) {
|
|
|
|
sym->flags |= SYMBOL_DEF_USER;
|
2005-04-17 06:20:36 +08:00
|
|
|
sym_set_changed(sym);
|
|
|
|
}
|
|
|
|
|
2006-06-09 13:12:41 +08:00
|
|
|
oldval = sym->def[S_DEF_USER].val;
|
2005-04-17 06:20:36 +08:00
|
|
|
size = strlen(newval) + 1;
|
|
|
|
if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
|
|
|
|
size += 2;
|
2012-11-06 22:32:08 +08:00
|
|
|
sym->def[S_DEF_USER].val = val = xmalloc(size);
|
2005-04-17 06:20:36 +08:00
|
|
|
*val++ = '0';
|
|
|
|
*val++ = 'x';
|
|
|
|
} else if (!oldval || strcmp(oldval, newval))
|
2012-11-06 22:32:08 +08:00
|
|
|
sym->def[S_DEF_USER].val = val = xmalloc(size);
|
2005-04-17 06:20:36 +08:00
|
|
|
else
|
|
|
|
return true;
|
|
|
|
|
|
|
|
strcpy(val, newval);
|
|
|
|
free((void *)oldval);
|
|
|
|
sym_clear_all_valid();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-08-01 05:35:34 +08:00
|
|
|
/*
|
|
|
|
* Find the default value associated to a symbol.
|
|
|
|
* For tristate symbol handle the modules=n case
|
|
|
|
* in which case "m" becomes "y".
|
|
|
|
* If the symbol does not have any default then fallback
|
|
|
|
* to the fixed default values.
|
|
|
|
*/
|
|
|
|
const char *sym_get_string_default(struct symbol *sym)
|
|
|
|
{
|
|
|
|
struct property *prop;
|
|
|
|
struct symbol *ds;
|
2023-11-26 00:35:58 +08:00
|
|
|
const char *str = "";
|
2010-08-01 05:35:34 +08:00
|
|
|
tristate val;
|
|
|
|
|
|
|
|
sym_calc_visibility(sym);
|
|
|
|
sym_calc_value(modules_sym);
|
|
|
|
val = symbol_no.curr.tri;
|
|
|
|
|
|
|
|
/* If symbol has a default value look it up */
|
|
|
|
prop = sym_get_default_prop(sym);
|
|
|
|
if (prop != NULL) {
|
|
|
|
switch (sym->type) {
|
|
|
|
case S_BOOLEAN:
|
|
|
|
case S_TRISTATE:
|
2010-12-05 14:41:16 +08:00
|
|
|
/* The visibility may limit the value from yes => mod */
|
2010-08-01 05:35:34 +08:00
|
|
|
val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* The following fails to handle the situation
|
|
|
|
* where a default value is further limited by
|
|
|
|
* the valid range.
|
|
|
|
*/
|
|
|
|
ds = prop_get_symbol(prop);
|
|
|
|
if (ds != NULL) {
|
|
|
|
sym_calc_value(ds);
|
|
|
|
str = (const char *)ds->curr.val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle select statements */
|
|
|
|
val = EXPR_OR(val, sym->rev_dep.tri);
|
|
|
|
|
|
|
|
/* transpose mod to yes if modules are not enabled */
|
|
|
|
if (val == mod)
|
|
|
|
if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
|
|
|
|
val = yes;
|
|
|
|
|
|
|
|
/* transpose mod to yes if type is bool */
|
|
|
|
if (sym->type == S_BOOLEAN && val == mod)
|
|
|
|
val = yes;
|
|
|
|
|
2016-11-11 13:10:05 +08:00
|
|
|
/* adjust the default value if this symbol is implied by another */
|
|
|
|
if (val < sym->implied.tri)
|
|
|
|
val = sym->implied.tri;
|
|
|
|
|
2010-08-01 05:35:34 +08:00
|
|
|
switch (sym->type) {
|
|
|
|
case S_BOOLEAN:
|
|
|
|
case S_TRISTATE:
|
|
|
|
switch (val) {
|
|
|
|
case no: return "n";
|
|
|
|
case mod: return "m";
|
|
|
|
case yes: return "y";
|
|
|
|
}
|
|
|
|
case S_INT:
|
2023-11-26 00:35:59 +08:00
|
|
|
if (!str[0])
|
|
|
|
str = "0";
|
|
|
|
break;
|
2010-08-01 05:35:34 +08:00
|
|
|
case S_HEX:
|
2023-11-26 00:35:59 +08:00
|
|
|
if (!str[0])
|
|
|
|
str = "0x0";
|
|
|
|
break;
|
|
|
|
default:
|
2010-08-01 05:35:34 +08:00
|
|
|
break;
|
|
|
|
}
|
2023-11-26 00:35:59 +08:00
|
|
|
return str;
|
2010-08-01 05:35:34 +08:00
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
const char *sym_get_string_value(struct symbol *sym)
|
|
|
|
{
|
|
|
|
tristate val;
|
|
|
|
|
|
|
|
switch (sym->type) {
|
|
|
|
case S_BOOLEAN:
|
|
|
|
case S_TRISTATE:
|
|
|
|
val = sym_get_tristate_value(sym);
|
|
|
|
switch (val) {
|
|
|
|
case no:
|
|
|
|
return "n";
|
|
|
|
case mod:
|
kconfig: fix comparison to constant symbols, 'm', 'n'
Currently, comparisons to 'm' or 'n' result in incorrect output.
[Test Code]
config MODULES
def_bool y
modules
config A
def_tristate m
config B
def_bool A > n
CONFIG_B is unset, while CONFIG_B=y is expected.
The reason for the issue is because Kconfig compares the tristate values
as strings.
Currently, the .type fields in the constant symbol definitions,
symbol_{yes,mod,no} are unspecified, i.e., S_UNKNOWN.
When expr_calc_value() evaluates 'A > n', it checks the types of 'A' and
'n' to determine how to compare them.
The left-hand side, 'A', is a tristate symbol with a value of 'm', which
corresponds to a numeric value of 1. (Internally, 'y', 'm', and 'n' are
represented as 2, 1, and 0, respectively.)
The right-hand side, 'n', has an unknown type, so it is treated as the
string "n" during the comparison.
expr_calc_value() compares two values numerically only when both can
have numeric values. Otherwise, they are compared as strings.
symbol numeric value ASCII code
-------------------------------------
y 2 0x79
m 1 0x6d
n 0 0x6e
'm' is greater than 'n' if compared numerically (since 1 is greater
than 0), but smaller than 'n' if compared as strings (since the ASCII
code 0x6d is smaller than 0x6e).
Specifying .type=S_TRISTATE for symbol_{yes,mod,no} fixes the above
test code.
Doing so, however, would cause a regression to the following test code.
[Test Code 2]
config MODULES
def_bool n
modules
config A
def_tristate n
config B
def_bool A = m
You would get CONFIG_B=y, while CONFIG_B should not be set.
The reason is because sym_get_string_value() turns 'm' into 'n' when the
module feature is disabled. Consequently, expr_calc_value() evaluates
'A = n' instead of 'A = m'. This oddity has been hidden because the type
of 'm' was previously S_UNKNOWN instead of S_TRISTATE.
sym_get_string_value() should not tweak the string because the tristate
value has already been correctly calculated. There is no reason to
return the string "n" where its tristate value is mod.
Fixes: 31847b67bec0 ("kconfig: allow use of relations other than (in)equality")
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2024-05-19 17:22:27 +08:00
|
|
|
return "m";
|
2005-04-17 06:20:36 +08:00
|
|
|
case yes:
|
|
|
|
return "y";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
return (const char *)sym->curr.val;
|
|
|
|
}
|
|
|
|
|
2024-07-07 23:38:05 +08:00
|
|
|
bool sym_is_changeable(const struct symbol *sym)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
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-27 02:22:01 +08:00
|
|
|
return !sym_is_choice(sym) && sym->visible > sym->rev_dep.tri;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2024-07-07 23:38:06 +08:00
|
|
|
bool sym_is_choice_value(const struct symbol *sym)
|
|
|
|
{
|
|
|
|
return !list_empty(&sym->choice_link);
|
|
|
|
}
|
|
|
|
|
2024-02-11 20:41:05 +08:00
|
|
|
HASHTABLE_DEFINE(sym_hashtable, SYMBOL_HASHSIZE);
|
|
|
|
|
2008-02-29 12:11:50 +08:00
|
|
|
struct symbol *sym_lookup(const char *name, int flags)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct symbol *symbol;
|
|
|
|
char *new_name;
|
2010-01-14 00:02:44 +08:00
|
|
|
int hash;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
if (name) {
|
|
|
|
if (name[0] && !name[1]) {
|
|
|
|
switch (name[0]) {
|
|
|
|
case 'y': return &symbol_yes;
|
|
|
|
case 'm': return &symbol_mod;
|
|
|
|
case 'n': return &symbol_no;
|
|
|
|
}
|
|
|
|
}
|
2024-09-08 20:43:16 +08:00
|
|
|
hash = hash_str(name);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2024-02-11 20:41:05 +08:00
|
|
|
hash_for_each_possible(sym_hashtable, symbol, node, hash) {
|
2010-01-14 00:02:44 +08:00
|
|
|
if (symbol->name &&
|
|
|
|
!strcmp(symbol->name, name) &&
|
2008-02-29 12:11:50 +08:00
|
|
|
(flags ? symbol->flags & flags
|
2024-04-23 00:10:54 +08:00
|
|
|
: !(symbol->flags & SYMBOL_CONST)))
|
2008-02-29 12:11:50 +08:00
|
|
|
return symbol;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2018-02-17 02:38:31 +08:00
|
|
|
new_name = xstrdup(name);
|
2005-04-17 06:20:36 +08:00
|
|
|
} else {
|
|
|
|
new_name = NULL;
|
2010-01-14 00:02:44 +08:00
|
|
|
hash = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2012-11-06 22:32:08 +08:00
|
|
|
symbol = xmalloc(sizeof(*symbol));
|
2005-04-17 06:20:36 +08:00
|
|
|
memset(symbol, 0, sizeof(*symbol));
|
|
|
|
symbol->name = new_name;
|
|
|
|
symbol->type = S_UNKNOWN;
|
2020-04-13 23:33:20 +08:00
|
|
|
symbol->flags = flags;
|
2024-03-03 12:00:33 +08:00
|
|
|
INIT_LIST_HEAD(&symbol->menus);
|
2024-07-07 23:38:06 +08:00
|
|
|
INIT_LIST_HEAD(&symbol->choice_link);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2024-02-11 20:41:05 +08:00
|
|
|
hash_add(sym_hashtable, &symbol->node, hash);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
return symbol;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct symbol *sym_find(const char *name)
|
|
|
|
{
|
|
|
|
struct symbol *symbol = NULL;
|
|
|
|
int hash = 0;
|
|
|
|
|
|
|
|
if (!name)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (name[0] && !name[1]) {
|
|
|
|
switch (name[0]) {
|
|
|
|
case 'y': return &symbol_yes;
|
|
|
|
case 'm': return &symbol_mod;
|
|
|
|
case 'n': return &symbol_no;
|
|
|
|
}
|
|
|
|
}
|
2024-09-08 20:43:16 +08:00
|
|
|
hash = hash_str(name);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2024-02-11 20:41:05 +08:00
|
|
|
hash_for_each_possible(sym_hashtable, symbol, node, hash) {
|
2010-01-14 00:02:44 +08:00
|
|
|
if (symbol->name &&
|
|
|
|
!strcmp(symbol->name, name) &&
|
2005-04-17 06:20:36 +08:00
|
|
|
!(symbol->flags & SYMBOL_CONST))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return symbol;
|
|
|
|
}
|
|
|
|
|
2013-05-06 20:57:47 +08:00
|
|
|
struct sym_match {
|
|
|
|
struct symbol *sym;
|
|
|
|
off_t so, eo;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Compare matched symbols as thus:
|
|
|
|
* - first, symbols that match exactly
|
|
|
|
* - then, alphabetical sort
|
|
|
|
*/
|
2013-07-17 02:28:51 +08:00
|
|
|
static int sym_rel_comp(const void *sym1, const void *sym2)
|
2013-05-06 20:57:47 +08:00
|
|
|
{
|
2013-07-17 02:39:42 +08:00
|
|
|
const struct sym_match *s1 = sym1;
|
|
|
|
const struct sym_match *s2 = sym2;
|
2013-07-13 21:09:43 +08:00
|
|
|
int exact1, exact2;
|
2013-05-06 20:57:47 +08:00
|
|
|
|
|
|
|
/* Exact match:
|
|
|
|
* - if matched length on symbol s1 is the length of that symbol,
|
|
|
|
* then this symbol should come first;
|
|
|
|
* - if matched length on symbol s2 is the length of that symbol,
|
|
|
|
* then this symbol should come first.
|
|
|
|
* Note: since the search can be a regexp, both symbols may match
|
|
|
|
* exactly; if this is the case, we can't decide which comes first,
|
|
|
|
* and we fallback to sorting alphabetically.
|
|
|
|
*/
|
2013-07-13 21:09:43 +08:00
|
|
|
exact1 = (s1->eo - s1->so) == strlen(s1->sym->name);
|
|
|
|
exact2 = (s2->eo - s2->so) == strlen(s2->sym->name);
|
|
|
|
if (exact1 && !exact2)
|
2013-05-06 20:57:47 +08:00
|
|
|
return -1;
|
2013-07-13 21:09:43 +08:00
|
|
|
if (!exact1 && exact2)
|
2013-05-06 20:57:47 +08:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* As a fallback, sort symbols alphabetically */
|
|
|
|
return strcmp(s1->sym->name, s2->sym->name);
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
struct symbol **sym_re_search(const char *pattern)
|
|
|
|
{
|
|
|
|
struct symbol *sym, **sym_arr = NULL;
|
2013-07-17 02:39:42 +08:00
|
|
|
struct sym_match *sym_match_arr = NULL;
|
2005-04-17 06:20:36 +08:00
|
|
|
int i, cnt, size;
|
|
|
|
regex_t re;
|
2013-05-06 20:57:47 +08:00
|
|
|
regmatch_t match[1];
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
cnt = size = 0;
|
|
|
|
/* Skip if empty */
|
|
|
|
if (strlen(pattern) == 0)
|
|
|
|
return NULL;
|
2013-05-06 20:57:47 +08:00
|
|
|
if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE))
|
2005-04-17 06:20:36 +08:00
|
|
|
return NULL;
|
|
|
|
|
2024-02-11 20:41:05 +08:00
|
|
|
for_all_symbols(sym) {
|
2005-04-17 06:20:36 +08:00
|
|
|
if (sym->flags & SYMBOL_CONST || !sym->name)
|
|
|
|
continue;
|
2013-05-06 20:57:47 +08:00
|
|
|
if (regexec(&re, sym->name, 1, match, 0))
|
2005-04-17 06:20:36 +08:00
|
|
|
continue;
|
2013-07-17 02:32:33 +08:00
|
|
|
if (cnt >= size) {
|
2013-05-06 20:57:47 +08:00
|
|
|
void *tmp;
|
2005-04-17 06:20:36 +08:00
|
|
|
size += 16;
|
2013-07-17 02:39:42 +08:00
|
|
|
tmp = realloc(sym_match_arr, size * sizeof(struct sym_match));
|
2013-07-17 02:28:51 +08:00
|
|
|
if (!tmp)
|
2013-05-06 20:57:47 +08:00
|
|
|
goto sym_re_search_free;
|
|
|
|
sym_match_arr = tmp;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2010-03-19 14:57:47 +08:00
|
|
|
sym_calc_value(sym);
|
2013-07-17 02:28:51 +08:00
|
|
|
/* As regexec returned 0, we know we have a match, so
|
2013-05-06 20:57:47 +08:00
|
|
|
* we can use match[0].rm_[se]o without further checks
|
|
|
|
*/
|
2013-07-17 02:39:42 +08:00
|
|
|
sym_match_arr[cnt].so = match[0].rm_so;
|
|
|
|
sym_match_arr[cnt].eo = match[0].rm_eo;
|
|
|
|
sym_match_arr[cnt++].sym = sym;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2013-05-06 20:57:47 +08:00
|
|
|
if (sym_match_arr) {
|
2013-07-17 02:39:42 +08:00
|
|
|
qsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp);
|
2017-11-09 05:09:59 +08:00
|
|
|
sym_arr = malloc((cnt+1) * sizeof(struct symbol *));
|
2013-05-06 20:57:47 +08:00
|
|
|
if (!sym_arr)
|
|
|
|
goto sym_re_search_free;
|
|
|
|
for (i = 0; i < cnt; i++)
|
2013-07-17 02:39:42 +08:00
|
|
|
sym_arr[i] = sym_match_arr[i].sym;
|
2005-04-17 06:20:36 +08:00
|
|
|
sym_arr[cnt] = NULL;
|
2013-05-06 20:57:47 +08:00
|
|
|
}
|
|
|
|
sym_re_search_free:
|
2013-07-17 02:39:42 +08:00
|
|
|
/* sym_match_arr can be NULL if no match, but free(NULL) is OK */
|
|
|
|
free(sym_match_arr);
|
2005-04-17 06:20:36 +08:00
|
|
|
regfree(&re);
|
|
|
|
|
|
|
|
return sym_arr;
|
|
|
|
}
|
|
|
|
|
2010-08-01 05:35:30 +08:00
|
|
|
/*
|
|
|
|
* When we check for recursive dependencies we use a stack to save
|
|
|
|
* current state so we can print out relevant info to user.
|
|
|
|
* The entries are located on the call stack so no need to free memory.
|
2013-10-03 23:28:14 +08:00
|
|
|
* Note insert() remove() must always match to properly clear the stack.
|
2010-08-01 05:35:30 +08:00
|
|
|
*/
|
|
|
|
static struct dep_stack {
|
|
|
|
struct dep_stack *prev, *next;
|
|
|
|
struct symbol *sym;
|
|
|
|
struct property *prop;
|
2018-08-15 13:59:45 +08:00
|
|
|
struct expr **expr;
|
2010-08-01 05:35:30 +08:00
|
|
|
} *check_top;
|
|
|
|
|
|
|
|
static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
|
|
|
|
{
|
|
|
|
memset(stack, 0, sizeof(*stack));
|
|
|
|
if (check_top)
|
|
|
|
check_top->next = stack;
|
|
|
|
stack->prev = check_top;
|
|
|
|
stack->sym = sym;
|
|
|
|
check_top = stack;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dep_stack_remove(void)
|
|
|
|
{
|
|
|
|
check_top = check_top->prev;
|
|
|
|
if (check_top)
|
|
|
|
check_top->next = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called when we have detected a recursive dependency.
|
|
|
|
* check_top point to the top of the stact so we use
|
|
|
|
* the ->prev pointer to locate the bottom of the stack.
|
|
|
|
*/
|
|
|
|
static void sym_check_print_recursive(struct symbol *last_sym)
|
|
|
|
{
|
|
|
|
struct dep_stack *stack;
|
|
|
|
struct symbol *sym, *next_sym;
|
2024-06-18 18:35:27 +08:00
|
|
|
struct menu *choice;
|
2010-08-01 05:35:30 +08:00
|
|
|
struct dep_stack cv_stack;
|
2024-07-17 09:50:41 +08:00
|
|
|
enum prop_type type;
|
2010-08-01 05:35:30 +08:00
|
|
|
|
2024-06-18 18:35:27 +08:00
|
|
|
choice = sym_get_choice_menu(last_sym);
|
|
|
|
if (choice) {
|
2010-08-01 05:35:30 +08:00
|
|
|
dep_stack_insert(&cv_stack, last_sym);
|
2024-06-18 18:35:27 +08:00
|
|
|
last_sym = choice->sym;
|
2010-08-01 05:35:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (stack = check_top; stack != NULL; stack = stack->prev)
|
|
|
|
if (stack->sym == last_sym)
|
|
|
|
break;
|
|
|
|
if (!stack) {
|
|
|
|
fprintf(stderr, "unexpected recursive dependency error\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (; stack; stack = stack->next) {
|
|
|
|
sym = stack->sym;
|
|
|
|
next_sym = stack->next ? stack->next->sym : last_sym;
|
2024-07-17 09:50:41 +08:00
|
|
|
type = stack->prop ? stack->prop->type : P_UNKNOWN;
|
|
|
|
|
2010-08-01 05:35:30 +08:00
|
|
|
if (stack->sym == last_sym)
|
2024-07-17 09:50:41 +08:00
|
|
|
fprintf(stderr, "error: recursive dependency detected!\n");
|
2017-12-15 23:28:42 +08:00
|
|
|
|
2024-06-27 02:22:03 +08:00
|
|
|
if (sym_is_choice(next_sym)) {
|
2024-06-27 02:22:04 +08:00
|
|
|
choice = list_first_entry(&next_sym->menus, struct menu, link);
|
|
|
|
|
2024-07-17 09:50:41 +08:00
|
|
|
fprintf(stderr, "\tsymbol %s is part of choice block at %s:%d\n",
|
2010-08-01 05:35:30 +08:00
|
|
|
sym->name ? sym->name : "<choice>",
|
2024-06-27 02:22:04 +08:00
|
|
|
choice->filename, choice->lineno);
|
2018-08-15 13:59:45 +08:00
|
|
|
} else if (stack->expr == &sym->dir_dep.expr) {
|
2024-07-17 09:50:41 +08:00
|
|
|
fprintf(stderr, "\tsymbol %s depends on %s\n",
|
2010-08-01 05:35:30 +08:00
|
|
|
sym->name ? sym->name : "<choice>",
|
2024-06-27 02:22:04 +08:00
|
|
|
next_sym->name);
|
2018-08-15 13:59:45 +08:00
|
|
|
} else if (stack->expr == &sym->rev_dep.expr) {
|
2024-07-17 09:50:41 +08:00
|
|
|
fprintf(stderr, "\tsymbol %s is selected by %s\n",
|
2024-06-27 02:22:04 +08:00
|
|
|
sym->name, next_sym->name);
|
2018-08-15 13:59:45 +08:00
|
|
|
} else if (stack->expr == &sym->implied.expr) {
|
2024-07-17 09:50:41 +08:00
|
|
|
fprintf(stderr, "\tsymbol %s is implied by %s\n",
|
2024-06-27 02:22:04 +08:00
|
|
|
sym->name, next_sym->name);
|
2018-08-15 13:59:45 +08:00
|
|
|
} else if (stack->expr) {
|
2024-07-17 09:50:41 +08:00
|
|
|
fprintf(stderr, "\tsymbol %s %s value contains %s\n",
|
2018-08-15 13:59:45 +08:00
|
|
|
sym->name ? sym->name : "<choice>",
|
2024-07-17 09:50:41 +08:00
|
|
|
prop_get_type_name(type),
|
2024-06-27 02:22:04 +08:00
|
|
|
next_sym->name);
|
2010-08-01 05:35:30 +08:00
|
|
|
} else {
|
2024-07-17 09:50:41 +08:00
|
|
|
fprintf(stderr, "\tsymbol %s %s is visible depending on %s\n",
|
2010-08-01 05:35:30 +08:00
|
|
|
sym->name ? sym->name : "<choice>",
|
2024-07-17 09:50:41 +08:00
|
|
|
prop_get_type_name(type),
|
2024-06-27 02:22:04 +08:00
|
|
|
next_sym->name);
|
2010-08-01 05:35:30 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-15 23:28:42 +08:00
|
|
|
fprintf(stderr,
|
2019-06-13 01:52:48 +08:00
|
|
|
"For a resolution refer to Documentation/kbuild/kconfig-language.rst\n"
|
2017-12-15 23:28:42 +08:00
|
|
|
"subsection \"Kconfig recursive dependency limitations\"\n"
|
|
|
|
"\n");
|
|
|
|
|
2010-08-01 05:35:30 +08:00
|
|
|
if (check_top == &cv_stack)
|
|
|
|
dep_stack_remove();
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2024-07-07 23:38:05 +08:00
|
|
|
static struct symbol *sym_check_expr_deps(const struct expr *e)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct symbol *sym;
|
|
|
|
|
|
|
|
if (!e)
|
|
|
|
return NULL;
|
|
|
|
switch (e->type) {
|
|
|
|
case E_OR:
|
|
|
|
case E_AND:
|
|
|
|
sym = sym_check_expr_deps(e->left.expr);
|
|
|
|
if (sym)
|
|
|
|
return sym;
|
|
|
|
return sym_check_expr_deps(e->right.expr);
|
|
|
|
case E_NOT:
|
|
|
|
return sym_check_expr_deps(e->left.expr);
|
|
|
|
case E_EQUAL:
|
2015-06-15 20:00:21 +08:00
|
|
|
case E_GEQ:
|
|
|
|
case E_GTH:
|
|
|
|
case E_LEQ:
|
|
|
|
case E_LTH:
|
2005-04-17 06:20:36 +08:00
|
|
|
case E_UNEQUAL:
|
|
|
|
sym = sym_check_deps(e->left.sym);
|
|
|
|
if (sym)
|
|
|
|
return sym;
|
|
|
|
return sym_check_deps(e->right.sym);
|
|
|
|
case E_SYMBOL:
|
|
|
|
return sym_check_deps(e->left.sym);
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2018-02-06 08:34:41 +08:00
|
|
|
fprintf(stderr, "Oops! How to check %d?\n", e->type);
|
2005-04-17 06:20:36 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-05-06 15:20:10 +08:00
|
|
|
/* return NULL when dependencies are OK */
|
2008-02-29 12:10:24 +08:00
|
|
|
static struct symbol *sym_check_sym_deps(struct symbol *sym)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct symbol *sym2;
|
|
|
|
struct property *prop;
|
2010-08-01 05:35:30 +08:00
|
|
|
struct dep_stack stack;
|
|
|
|
|
|
|
|
dep_stack_insert(&stack, sym);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2018-08-15 13:59:45 +08:00
|
|
|
stack.expr = &sym->dir_dep.expr;
|
|
|
|
sym2 = sym_check_expr_deps(sym->dir_dep.expr);
|
|
|
|
if (sym2)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
stack.expr = &sym->rev_dep.expr;
|
2005-04-17 06:20:36 +08:00
|
|
|
sym2 = sym_check_expr_deps(sym->rev_dep.expr);
|
|
|
|
if (sym2)
|
2010-08-01 05:35:30 +08:00
|
|
|
goto out;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2018-08-15 13:59:45 +08:00
|
|
|
stack.expr = &sym->implied.expr;
|
2018-08-15 13:59:44 +08:00
|
|
|
sym2 = sym_check_expr_deps(sym->implied.expr);
|
|
|
|
if (sym2)
|
|
|
|
goto out;
|
|
|
|
|
2018-08-15 13:59:45 +08:00
|
|
|
stack.expr = NULL;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
for (prop = sym->prop; prop; prop = prop->next) {
|
2024-06-18 18:35:30 +08:00
|
|
|
if (prop->type == P_SELECT || prop->type == P_IMPLY)
|
2005-04-17 06:20:36 +08:00
|
|
|
continue;
|
2010-08-01 05:35:30 +08:00
|
|
|
stack.prop = prop;
|
2005-04-17 06:20:36 +08:00
|
|
|
sym2 = sym_check_expr_deps(prop->visible.expr);
|
|
|
|
if (sym2)
|
2008-02-29 12:10:24 +08:00
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
if (prop->type != P_DEFAULT || sym_is_choice(sym))
|
|
|
|
continue;
|
2018-08-15 13:59:45 +08:00
|
|
|
stack.expr = &prop->expr;
|
2005-04-17 06:20:36 +08:00
|
|
|
sym2 = sym_check_expr_deps(prop->expr);
|
|
|
|
if (sym2)
|
2008-02-29 12:10:24 +08:00
|
|
|
break;
|
2010-08-01 05:35:30 +08:00
|
|
|
stack.expr = NULL;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2008-02-29 12:10:24 +08:00
|
|
|
|
2010-08-01 05:35:30 +08:00
|
|
|
out:
|
|
|
|
dep_stack_remove();
|
|
|
|
|
2008-02-29 12:10:24 +08:00
|
|
|
return sym2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct symbol *sym_check_choice_deps(struct symbol *choice)
|
|
|
|
{
|
2024-05-05 02:33:30 +08:00
|
|
|
struct menu *choice_menu, *menu;
|
|
|
|
struct symbol *sym2;
|
2010-08-01 05:35:30 +08:00
|
|
|
struct dep_stack stack;
|
|
|
|
|
|
|
|
dep_stack_insert(&stack, choice);
|
2008-02-29 12:10:24 +08:00
|
|
|
|
2024-05-05 02:33:30 +08:00
|
|
|
choice_menu = list_first_entry(&choice->menus, struct menu, link);
|
|
|
|
|
|
|
|
menu_for_each_sub_entry(menu, choice_menu) {
|
|
|
|
if (menu->sym)
|
|
|
|
menu->sym->flags |= SYMBOL_CHECK | SYMBOL_CHECKED;
|
|
|
|
}
|
2008-02-29 12:10:24 +08:00
|
|
|
|
|
|
|
choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
|
|
|
|
sym2 = sym_check_sym_deps(choice);
|
|
|
|
choice->flags &= ~SYMBOL_CHECK;
|
2007-05-06 15:20:10 +08:00
|
|
|
if (sym2)
|
2008-02-29 12:10:24 +08:00
|
|
|
goto out;
|
|
|
|
|
2024-05-05 02:33:30 +08:00
|
|
|
menu_for_each_sub_entry(menu, choice_menu) {
|
|
|
|
if (!menu->sym)
|
|
|
|
continue;
|
|
|
|
sym2 = sym_check_sym_deps(menu->sym);
|
2010-08-01 05:35:30 +08:00
|
|
|
if (sym2)
|
2008-02-29 12:10:24 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
out:
|
2024-05-05 02:33:30 +08:00
|
|
|
menu_for_each_sub_entry(menu, choice_menu)
|
|
|
|
if (menu->sym)
|
|
|
|
menu->sym->flags &= ~SYMBOL_CHECK;
|
2008-02-29 12:10:24 +08:00
|
|
|
|
2024-06-18 18:35:28 +08:00
|
|
|
if (sym2) {
|
|
|
|
struct menu *choice_menu2;
|
|
|
|
|
|
|
|
choice_menu2 = sym_get_choice_menu(sym2);
|
|
|
|
if (choice_menu2 == choice_menu)
|
|
|
|
sym2 = choice;
|
|
|
|
}
|
2008-02-29 12:10:24 +08:00
|
|
|
|
2010-08-01 05:35:30 +08:00
|
|
|
dep_stack_remove();
|
|
|
|
|
2008-02-29 12:10:24 +08:00
|
|
|
return sym2;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct symbol *sym_check_deps(struct symbol *sym)
|
|
|
|
{
|
2024-06-18 18:35:29 +08:00
|
|
|
struct menu *choice;
|
2008-02-29 12:10:24 +08:00
|
|
|
struct symbol *sym2;
|
|
|
|
|
|
|
|
if (sym->flags & SYMBOL_CHECK) {
|
2010-08-01 05:35:30 +08:00
|
|
|
sym_check_print_recursive(sym);
|
2008-02-29 12:10:24 +08:00
|
|
|
return sym;
|
|
|
|
}
|
|
|
|
if (sym->flags & SYMBOL_CHECKED)
|
|
|
|
return NULL;
|
|
|
|
|
2024-06-18 18:35:29 +08:00
|
|
|
choice = sym_get_choice_menu(sym);
|
|
|
|
if (choice) {
|
2010-08-01 05:35:30 +08:00
|
|
|
struct dep_stack stack;
|
|
|
|
|
2008-02-29 12:10:24 +08:00
|
|
|
/* for choice groups start the check with main choice symbol */
|
2010-08-01 05:35:30 +08:00
|
|
|
dep_stack_insert(&stack, sym);
|
2024-06-18 18:35:29 +08:00
|
|
|
sym2 = sym_check_deps(choice->sym);
|
2010-08-01 05:35:30 +08:00
|
|
|
dep_stack_remove();
|
2008-02-29 12:10:24 +08:00
|
|
|
} else if (sym_is_choice(sym)) {
|
|
|
|
sym2 = sym_check_choice_deps(sym);
|
|
|
|
} else {
|
|
|
|
sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
|
|
|
|
sym2 = sym_check_sym_deps(sym);
|
|
|
|
sym->flags &= ~SYMBOL_CHECK;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
return sym2;
|
|
|
|
}
|
|
|
|
|
2024-07-07 23:38:05 +08:00
|
|
|
struct symbol *prop_get_symbol(const struct property *prop)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2024-06-18 18:35:31 +08:00
|
|
|
if (prop->expr && prop->expr->type == E_SYMBOL)
|
2005-04-17 06:20:36 +08:00
|
|
|
return prop->expr->left.sym;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *prop_get_type_name(enum prop_type type)
|
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case P_PROMPT:
|
|
|
|
return "prompt";
|
|
|
|
case P_COMMENT:
|
|
|
|
return "comment";
|
|
|
|
case P_MENU:
|
|
|
|
return "menu";
|
|
|
|
case P_DEFAULT:
|
|
|
|
return "default";
|
|
|
|
case P_SELECT:
|
|
|
|
return "select";
|
2016-11-11 13:10:05 +08:00
|
|
|
case P_IMPLY:
|
|
|
|
return "imply";
|
2005-04-17 06:20:36 +08:00
|
|
|
case P_RANGE:
|
|
|
|
return "range";
|
|
|
|
case P_UNKNOWN:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return "unknown";
|
|
|
|
}
|