2018-12-18 12:13:35 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
|
|
|
*/
|
2018-12-18 12:13:35 +00:00
|
|
|
%{
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
2024-08-12 12:48:50 +00:00
|
|
|
#include <xalloc.h>
|
2005-11-09 05:34:51 +00:00
|
|
|
#include "lkc.h"
|
2021-04-13 15:08:17 +00:00
|
|
|
#include "internal.h"
|
2024-02-02 15:58:06 +00:00
|
|
|
#include "preprocess.h"
|
2005-11-09 05:34:51 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
|
|
|
|
|
|
|
|
#define PRINTD 0x0001
|
|
|
|
#define DEBUG_PARSE 0x0002
|
|
|
|
|
|
|
|
int cdebug = PRINTD;
|
|
|
|
|
2018-01-11 15:50:50 +00:00
|
|
|
static void yyerror(const char *err);
|
2005-11-09 05:34:53 +00:00
|
|
|
static void zconf_error(const char *err, ...);
|
2018-12-11 11:01:06 +00:00
|
|
|
static bool zconf_endtoken(const char *tokenname,
|
|
|
|
const char *expected_tokenname);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2024-06-11 17:55:13 +00:00
|
|
|
struct menu *current_menu, *current_entry, *current_choice;
|
2024-05-04 18:33:32 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
%}
|
|
|
|
|
|
|
|
%union
|
|
|
|
{
|
|
|
|
char *string;
|
|
|
|
struct symbol *symbol;
|
|
|
|
struct expr *expr;
|
|
|
|
struct menu *menu;
|
2018-12-11 11:00:59 +00:00
|
|
|
enum symbol_type type;
|
2018-05-28 09:21:50 +00:00
|
|
|
enum variable_flavor flavor;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
%token <string> T_HELPTEXT
|
|
|
|
%token <string> T_WORD
|
|
|
|
%token <string> T_WORD_QUOTE
|
2018-12-11 11:00:59 +00:00
|
|
|
%token T_BOOL
|
2018-12-11 11:01:07 +00:00
|
|
|
%token T_CHOICE
|
2005-04-16 22:20:36 +00:00
|
|
|
%token T_CLOSE_PAREN
|
2018-12-11 11:01:01 +00:00
|
|
|
%token T_COLON_EQUAL
|
2018-12-11 11:01:07 +00:00
|
|
|
%token T_COMMENT
|
|
|
|
%token T_CONFIG
|
2018-12-11 11:00:59 +00:00
|
|
|
%token T_DEFAULT
|
|
|
|
%token T_DEF_BOOL
|
|
|
|
%token T_DEF_TRISTATE
|
2018-12-11 11:01:07 +00:00
|
|
|
%token T_DEPENDS
|
|
|
|
%token T_ENDCHOICE
|
|
|
|
%token T_ENDIF
|
|
|
|
%token T_ENDMENU
|
|
|
|
%token T_HELP
|
2018-12-11 11:00:59 +00:00
|
|
|
%token T_HEX
|
2018-12-11 11:01:07 +00:00
|
|
|
%token T_IF
|
|
|
|
%token T_IMPLY
|
2018-12-11 11:00:59 +00:00
|
|
|
%token T_INT
|
2018-12-11 11:01:07 +00:00
|
|
|
%token T_MAINMENU
|
|
|
|
%token T_MENU
|
|
|
|
%token T_MENUCONFIG
|
2018-12-11 11:01:00 +00:00
|
|
|
%token T_MODULES
|
2018-12-11 11:01:07 +00:00
|
|
|
%token T_ON
|
2005-04-16 22:20:36 +00:00
|
|
|
%token T_OPEN_PAREN
|
2018-12-11 11:01:01 +00:00
|
|
|
%token T_PLUS_EQUAL
|
2018-12-11 11:01:07 +00:00
|
|
|
%token T_PROMPT
|
|
|
|
%token T_RANGE
|
|
|
|
%token T_SELECT
|
|
|
|
%token T_SOURCE
|
2018-12-11 11:00:59 +00:00
|
|
|
%token T_STRING
|
|
|
|
%token T_TRISTATE
|
2018-12-11 11:01:07 +00:00
|
|
|
%token T_VISIBLE
|
2005-11-09 05:34:52 +00:00
|
|
|
%token T_EOL
|
kconfig: support user-defined function and recursively expanded variable
Now, we got a basic ability to test compiler capability in Kconfig.
config CC_HAS_STACKPROTECTOR
def_bool $(shell,($(CC) -Werror -fstack-protector -E -x c /dev/null -o /dev/null 2>/dev/null) && echo y || echo n)
This works, but it is ugly to repeat this long boilerplate.
We want to describe like this:
config CC_HAS_STACKPROTECTOR
bool
default $(cc-option,-fstack-protector)
It is straight-forward to add a new function, but I do not like to
hard-code specialized functions like that. Hence, here is another
feature, user-defined function. This works as a textual shorthand
with parameterization.
A user-defined function is defined by using the = operator, and can
be referenced in the same way as built-in functions. A user-defined
function in Make is referenced like $(call my-func,arg1,arg2), but I
omitted the 'call' to make the syntax shorter.
The definition of a user-defined function contains $(1), $(2), etc.
in its body to reference the parameters. It is grammatically valid
to pass more or fewer arguments when calling it. We already exploit
this feature in our makefiles; scripts/Kbuild.include defines cc-option
which takes two arguments at most, but most of the callers pass only
one argument.
By the way, a variable is supported as a subset of this feature since
a variable is "a user-defined function with zero argument". In this
context, I mean "variable" as recursively expanded variable. I will
add a different flavored variable in the next commit.
The code above can be written as follows:
[Example Code]
success = $(shell,($(1)) >/dev/null 2>&1 && echo y || echo n)
cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)
config CC_HAS_STACKPROTECTOR
def_bool $(cc-option,-fstack-protector)
[Result]
$ make -s alldefconfig && tail -n 1 .config
CONFIG_CC_HAS_STACKPROTECTOR=y
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2018-05-28 09:21:49 +00:00
|
|
|
%token <string> T_ASSIGN_VAL
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
%left T_OR
|
|
|
|
%left T_AND
|
|
|
|
%left T_EQUAL T_UNEQUAL
|
2015-06-15 12:00:21 +00:00
|
|
|
%left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL
|
2005-04-16 22:20:36 +00:00
|
|
|
%nonassoc T_NOT
|
|
|
|
|
kconfig: Don't leak symbol names during parsing
Prior to this fix, zconf.y did not free symbol names from zconf.l in
these contexts:
- After T_CONFIG ('config LEAKED')
- After T_MENUCONFIG ('menuconfig LEAKED')
- After T_SELECT ('select LEAKED')
- After T_IMPLY ('imply LEAKED')
- After T_DEFAULT in a choice ('default LEAKED')
All of these come in the form of T_WORD tokens, which always have their
associated string allocated on the heap in zconf.l and need to be freed.
Fix by introducing a new nonterminal 'nonconst_symbol' which takes a
T_WORD, fetches the symbol, and then frees the T_WORD string. The
already existing 'symbol' nonterminal works the same way but also
accepts T_WORD_QUOTE, corresponding to a constant symbol. T_WORD_QUOTE
should not be accepted in any of the contexts above, so the 'symbol'
nonterminal can't be reused here.
Fetching the symbol in 'nonconst_symbol' also removes a bunch of
sym_lookup() calls from actions.
Summary from Valgrind on 'menuconfig' (ARCH=x86) before the fix:
LEAK SUMMARY:
definitely lost: 711,571 bytes in 37,756 blocks
...
Summary after the fix:
LEAK SUMMARY:
definitely lost: 387,504 bytes in 15,545 blocks
...
Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-08 17:11:18 +00:00
|
|
|
%type <symbol> nonconst_symbol
|
2005-04-16 22:20:36 +00:00
|
|
|
%type <symbol> symbol
|
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 12:54:14 +00:00
|
|
|
%type <type> type default
|
2005-04-16 22:20:36 +00:00
|
|
|
%type <expr> expr
|
|
|
|
%type <expr> if_expr
|
2018-12-11 11:01:06 +00:00
|
|
|
%type <string> end
|
2005-11-09 05:34:53 +00:00
|
|
|
%type <menu> if_entry menu_entry choice_entry
|
2024-03-03 04:00:35 +00:00
|
|
|
%type <string> assign_val
|
2018-12-11 11:01:01 +00:00
|
|
|
%type <flavor> assign_op
|
2005-11-09 05:34:53 +00:00
|
|
|
|
|
|
|
%destructor {
|
|
|
|
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
|
2024-02-02 15:58:09 +00:00
|
|
|
$$->filename, $$->lineno);
|
2005-11-09 05:34:53 +00:00
|
|
|
if (current_menu == $$)
|
|
|
|
menu_end_menu();
|
|
|
|
} if_entry menu_entry choice_entry
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
%%
|
2018-12-11 11:00:49 +00:00
|
|
|
input: mainmenu_stmt stmt_list | stmt_list;
|
2017-10-08 17:11:21 +00:00
|
|
|
|
|
|
|
/* mainmenu entry */
|
|
|
|
|
2019-12-17 04:14:19 +00:00
|
|
|
mainmenu_stmt: T_MAINMENU T_WORD_QUOTE T_EOL
|
2017-10-08 17:11:21 +00:00
|
|
|
{
|
|
|
|
menu_add_prompt(P_MENU, $2, NULL);
|
|
|
|
};
|
|
|
|
|
2005-11-09 05:34:53 +00:00
|
|
|
stmt_list:
|
|
|
|
/* empty */
|
kconfig: allow only 'config', 'comment', and 'if' inside 'choice'
The code block surrounded by 'if' ... 'endif' is reduced into if_stmt,
which is accepted in the 'choice' context. Therefore, you can write any
statements within a choice block by wrapping 'if y' ... 'end'.
For example, you can create a menu inside a choice, like follows:
---------------->8----------------
choice
prompt "choice"
config A
bool "A"
config B
bool "B"
if y
menu "strange menu"
config C
bool "C"
endmenu
endif
endchoice
---------------->8----------------
I want to change such a weird structure into a syntax error.
In fact, the USB gadget Kconfig had used nested 'choice' for no good
reason until commit df8df5e4bc37 ("usb: get rid of 'choice' for
legacy gadget drivers") killed it.
I think the 'source' inside 'choice' is on the fence. It is at least
gramatically sensible as long as the included file contains only
bool/tristate configs. However, it makes the code unreadable, and people
tend to forget the fact that the file is included from the choice
block. Commit 10e5e6c24963 ("usb: gadget: move choice ... endchoice to
legacy/Kconfig") got rid of the only usecase.
Going forward, you can only use 'config', 'comment', and 'if' inside
'choice'. This also recursively applies to 'if' blocks inside 'choice'.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2020-04-24 05:49:29 +00:00
|
|
|
| stmt_list assignment_stmt
|
2005-11-09 05:34:53 +00:00
|
|
|
| stmt_list choice_stmt
|
kconfig: allow only 'config', 'comment', and 'if' inside 'choice'
The code block surrounded by 'if' ... 'endif' is reduced into if_stmt,
which is accepted in the 'choice' context. Therefore, you can write any
statements within a choice block by wrapping 'if y' ... 'end'.
For example, you can create a menu inside a choice, like follows:
---------------->8----------------
choice
prompt "choice"
config A
bool "A"
config B
bool "B"
if y
menu "strange menu"
config C
bool "C"
endmenu
endif
endchoice
---------------->8----------------
I want to change such a weird structure into a syntax error.
In fact, the USB gadget Kconfig had used nested 'choice' for no good
reason until commit df8df5e4bc37 ("usb: get rid of 'choice' for
legacy gadget drivers") killed it.
I think the 'source' inside 'choice' is on the fence. It is at least
gramatically sensible as long as the included file contains only
bool/tristate configs. However, it makes the code unreadable, and people
tend to forget the fact that the file is included from the choice
block. Commit 10e5e6c24963 ("usb: gadget: move choice ... endchoice to
legacy/Kconfig") got rid of the only usecase.
Going forward, you can only use 'config', 'comment', and 'if' inside
'choice'. This also recursively applies to 'if' blocks inside 'choice'.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2020-04-24 05:49:29 +00:00
|
|
|
| stmt_list comment_stmt
|
|
|
|
| stmt_list config_stmt
|
|
|
|
| stmt_list if_stmt
|
2005-11-09 05:34:53 +00:00
|
|
|
| stmt_list menu_stmt
|
kconfig: allow only 'config', 'comment', and 'if' inside 'choice'
The code block surrounded by 'if' ... 'endif' is reduced into if_stmt,
which is accepted in the 'choice' context. Therefore, you can write any
statements within a choice block by wrapping 'if y' ... 'end'.
For example, you can create a menu inside a choice, like follows:
---------------->8----------------
choice
prompt "choice"
config A
bool "A"
config B
bool "B"
if y
menu "strange menu"
config C
bool "C"
endmenu
endif
endchoice
---------------->8----------------
I want to change such a weird structure into a syntax error.
In fact, the USB gadget Kconfig had used nested 'choice' for no good
reason until commit df8df5e4bc37 ("usb: get rid of 'choice' for
legacy gadget drivers") killed it.
I think the 'source' inside 'choice' is on the fence. It is at least
gramatically sensible as long as the included file contains only
bool/tristate configs. However, it makes the code unreadable, and people
tend to forget the fact that the file is included from the choice
block. Commit 10e5e6c24963 ("usb: gadget: move choice ... endchoice to
legacy/Kconfig") got rid of the only usecase.
Going forward, you can only use 'config', 'comment', and 'if' inside
'choice'. This also recursively applies to 'if' blocks inside 'choice'.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2020-04-24 05:49:29 +00:00
|
|
|
| stmt_list menuconfig_stmt
|
|
|
|
| stmt_list source_stmt
|
2005-11-09 05:34:53 +00:00
|
|
|
| stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
|
|
|
|
| stmt_list error T_EOL { zconf_error("invalid statement"); }
|
2005-04-16 22:20:36 +00:00
|
|
|
;
|
|
|
|
|
kconfig: allow only 'config', 'comment', and 'if' inside 'choice'
The code block surrounded by 'if' ... 'endif' is reduced into if_stmt,
which is accepted in the 'choice' context. Therefore, you can write any
statements within a choice block by wrapping 'if y' ... 'end'.
For example, you can create a menu inside a choice, like follows:
---------------->8----------------
choice
prompt "choice"
config A
bool "A"
config B
bool "B"
if y
menu "strange menu"
config C
bool "C"
endmenu
endif
endchoice
---------------->8----------------
I want to change such a weird structure into a syntax error.
In fact, the USB gadget Kconfig had used nested 'choice' for no good
reason until commit df8df5e4bc37 ("usb: get rid of 'choice' for
legacy gadget drivers") killed it.
I think the 'source' inside 'choice' is on the fence. It is at least
gramatically sensible as long as the included file contains only
bool/tristate configs. However, it makes the code unreadable, and people
tend to forget the fact that the file is included from the choice
block. Commit 10e5e6c24963 ("usb: gadget: move choice ... endchoice to
legacy/Kconfig") got rid of the only usecase.
Going forward, you can only use 'config', 'comment', and 'if' inside
'choice'. This also recursively applies to 'if' blocks inside 'choice'.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2020-04-24 05:49:29 +00:00
|
|
|
stmt_list_in_choice:
|
|
|
|
/* empty */
|
|
|
|
| stmt_list_in_choice comment_stmt
|
|
|
|
| stmt_list_in_choice config_stmt
|
|
|
|
| stmt_list_in_choice if_stmt_in_choice
|
|
|
|
| stmt_list_in_choice error T_EOL { zconf_error("invalid statement"); }
|
2005-11-09 05:34:53 +00:00
|
|
|
;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* config/menuconfig entry */
|
|
|
|
|
kconfig: Don't leak symbol names during parsing
Prior to this fix, zconf.y did not free symbol names from zconf.l in
these contexts:
- After T_CONFIG ('config LEAKED')
- After T_MENUCONFIG ('menuconfig LEAKED')
- After T_SELECT ('select LEAKED')
- After T_IMPLY ('imply LEAKED')
- After T_DEFAULT in a choice ('default LEAKED')
All of these come in the form of T_WORD tokens, which always have their
associated string allocated on the heap in zconf.l and need to be freed.
Fix by introducing a new nonterminal 'nonconst_symbol' which takes a
T_WORD, fetches the symbol, and then frees the T_WORD string. The
already existing 'symbol' nonterminal works the same way but also
accepts T_WORD_QUOTE, corresponding to a constant symbol. T_WORD_QUOTE
should not be accepted in any of the contexts above, so the 'symbol'
nonterminal can't be reused here.
Fetching the symbol in 'nonconst_symbol' also removes a bunch of
sym_lookup() calls from actions.
Summary from Valgrind on 'menuconfig' (ARCH=x86) before the fix:
LEAK SUMMARY:
definitely lost: 711,571 bytes in 37,756 blocks
...
Summary after the fix:
LEAK SUMMARY:
definitely lost: 387,504 bytes in 15,545 blocks
...
Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-08 17:11:18 +00:00
|
|
|
config_entry_start: T_CONFIG nonconst_symbol T_EOL
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
kconfig: Don't leak symbol names during parsing
Prior to this fix, zconf.y did not free symbol names from zconf.l in
these contexts:
- After T_CONFIG ('config LEAKED')
- After T_MENUCONFIG ('menuconfig LEAKED')
- After T_SELECT ('select LEAKED')
- After T_IMPLY ('imply LEAKED')
- After T_DEFAULT in a choice ('default LEAKED')
All of these come in the form of T_WORD tokens, which always have their
associated string allocated on the heap in zconf.l and need to be freed.
Fix by introducing a new nonterminal 'nonconst_symbol' which takes a
T_WORD, fetches the symbol, and then frees the T_WORD string. The
already existing 'symbol' nonterminal works the same way but also
accepts T_WORD_QUOTE, corresponding to a constant symbol. T_WORD_QUOTE
should not be accepted in any of the contexts above, so the 'symbol'
nonterminal can't be reused here.
Fetching the symbol in 'nonconst_symbol' also removes a bunch of
sym_lookup() calls from actions.
Summary from Valgrind on 'menuconfig' (ARCH=x86) before the fix:
LEAK SUMMARY:
definitely lost: 711,571 bytes in 37,756 blocks
...
Summary after the fix:
LEAK SUMMARY:
definitely lost: 387,504 bytes in 15,545 blocks
...
Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-08 17:11:18 +00:00
|
|
|
menu_add_entry($2);
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:config %s\n", cur_filename, cur_lineno, $2->name);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
config_stmt: config_entry_start config_option_list
|
|
|
|
{
|
2024-06-11 17:55:13 +00:00
|
|
|
if (current_choice) {
|
2024-05-04 18:33:32 +00:00
|
|
|
if (!current_entry->prompt) {
|
|
|
|
fprintf(stderr, "%s:%d: error: choice member must have a prompt\n",
|
|
|
|
current_entry->filename, current_entry->lineno);
|
|
|
|
yynerrs++;
|
|
|
|
}
|
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 12:54:14 +00:00
|
|
|
|
|
|
|
if (current_entry->sym->type != S_BOOLEAN) {
|
|
|
|
fprintf(stderr, "%s:%d: error: choice member must be bool\n",
|
|
|
|
current_entry->filename, current_entry->lineno);
|
|
|
|
yynerrs++;
|
|
|
|
}
|
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 10:35:21 +00:00
|
|
|
|
2024-09-25 11:25:31 +00:00
|
|
|
/*
|
|
|
|
* If the same symbol appears twice in a choice block, the list
|
|
|
|
* node would be added twice, leading to a broken linked list.
|
|
|
|
* list_empty() ensures that this symbol has not yet added.
|
|
|
|
*/
|
|
|
|
if (list_empty(¤t_entry->sym->choice_link))
|
|
|
|
list_add_tail(¤t_entry->sym->choice_link,
|
|
|
|
¤t_choice->choice_members);
|
2024-05-04 18:33:32 +00:00
|
|
|
}
|
|
|
|
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
kconfig: Don't leak symbol names during parsing
Prior to this fix, zconf.y did not free symbol names from zconf.l in
these contexts:
- After T_CONFIG ('config LEAKED')
- After T_MENUCONFIG ('menuconfig LEAKED')
- After T_SELECT ('select LEAKED')
- After T_IMPLY ('imply LEAKED')
- After T_DEFAULT in a choice ('default LEAKED')
All of these come in the form of T_WORD tokens, which always have their
associated string allocated on the heap in zconf.l and need to be freed.
Fix by introducing a new nonterminal 'nonconst_symbol' which takes a
T_WORD, fetches the symbol, and then frees the T_WORD string. The
already existing 'symbol' nonterminal works the same way but also
accepts T_WORD_QUOTE, corresponding to a constant symbol. T_WORD_QUOTE
should not be accepted in any of the contexts above, so the 'symbol'
nonterminal can't be reused here.
Fetching the symbol in 'nonconst_symbol' also removes a bunch of
sym_lookup() calls from actions.
Summary from Valgrind on 'menuconfig' (ARCH=x86) before the fix:
LEAK SUMMARY:
definitely lost: 711,571 bytes in 37,756 blocks
...
Summary after the fix:
LEAK SUMMARY:
definitely lost: 387,504 bytes in 15,545 blocks
...
Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-08 17:11:18 +00:00
|
|
|
menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
kconfig: Don't leak symbol names during parsing
Prior to this fix, zconf.y did not free symbol names from zconf.l in
these contexts:
- After T_CONFIG ('config LEAKED')
- After T_MENUCONFIG ('menuconfig LEAKED')
- After T_SELECT ('select LEAKED')
- After T_IMPLY ('imply LEAKED')
- After T_DEFAULT in a choice ('default LEAKED')
All of these come in the form of T_WORD tokens, which always have their
associated string allocated on the heap in zconf.l and need to be freed.
Fix by introducing a new nonterminal 'nonconst_symbol' which takes a
T_WORD, fetches the symbol, and then frees the T_WORD string. The
already existing 'symbol' nonterminal works the same way but also
accepts T_WORD_QUOTE, corresponding to a constant symbol. T_WORD_QUOTE
should not be accepted in any of the contexts above, so the 'symbol'
nonterminal can't be reused here.
Fetching the symbol in 'nonconst_symbol' also removes a bunch of
sym_lookup() calls from actions.
Summary from Valgrind on 'menuconfig' (ARCH=x86) before the fix:
LEAK SUMMARY:
definitely lost: 711,571 bytes in 37,756 blocks
...
Summary after the fix:
LEAK SUMMARY:
definitely lost: 387,504 bytes in 15,545 blocks
...
Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-08 17:11:18 +00:00
|
|
|
menu_add_entry($2);
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", cur_filename, cur_lineno, $2->name);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
menuconfig_stmt: menuconfig_entry_start config_option_list
|
|
|
|
{
|
|
|
|
if (current_entry->prompt)
|
|
|
|
current_entry->prompt->type = P_MENU;
|
|
|
|
else
|
2024-09-29 17:32:38 +00:00
|
|
|
zconf_error("menuconfig statement without prompt");
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
config_option_list:
|
|
|
|
/* empty */
|
|
|
|
| config_option_list config_option
|
|
|
|
| config_option_list depends
|
|
|
|
| config_option_list help
|
|
|
|
;
|
|
|
|
|
2018-12-11 11:00:59 +00:00
|
|
|
config_option: type prompt_stmt_opt T_EOL
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2018-12-11 11:00:59 +00:00
|
|
|
menu_set_type($1);
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:type(%u)\n", cur_filename, cur_lineno, $1);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2019-12-17 04:14:19 +00:00
|
|
|
config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
menu_add_prompt(P_PROMPT, $2, $3);
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2018-12-11 11:00:59 +00:00
|
|
|
config_option: default expr if_expr T_EOL
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
menu_add_expr(P_DEFAULT, $2, $3);
|
2018-12-11 11:00:59 +00:00
|
|
|
if ($1 != S_UNKNOWN)
|
|
|
|
menu_set_type($1);
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:default(%u)\n", cur_filename, cur_lineno,
|
2018-12-11 11:00:59 +00:00
|
|
|
$1);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
kconfig: Don't leak symbol names during parsing
Prior to this fix, zconf.y did not free symbol names from zconf.l in
these contexts:
- After T_CONFIG ('config LEAKED')
- After T_MENUCONFIG ('menuconfig LEAKED')
- After T_SELECT ('select LEAKED')
- After T_IMPLY ('imply LEAKED')
- After T_DEFAULT in a choice ('default LEAKED')
All of these come in the form of T_WORD tokens, which always have their
associated string allocated on the heap in zconf.l and need to be freed.
Fix by introducing a new nonterminal 'nonconst_symbol' which takes a
T_WORD, fetches the symbol, and then frees the T_WORD string. The
already existing 'symbol' nonterminal works the same way but also
accepts T_WORD_QUOTE, corresponding to a constant symbol. T_WORD_QUOTE
should not be accepted in any of the contexts above, so the 'symbol'
nonterminal can't be reused here.
Fetching the symbol in 'nonconst_symbol' also removes a bunch of
sym_lookup() calls from actions.
Summary from Valgrind on 'menuconfig' (ARCH=x86) before the fix:
LEAK SUMMARY:
definitely lost: 711,571 bytes in 37,756 blocks
...
Summary after the fix:
LEAK SUMMARY:
definitely lost: 387,504 bytes in 15,545 blocks
...
Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-08 17:11:18 +00:00
|
|
|
config_option: T_SELECT nonconst_symbol if_expr T_EOL
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
kconfig: Don't leak symbol names during parsing
Prior to this fix, zconf.y did not free symbol names from zconf.l in
these contexts:
- After T_CONFIG ('config LEAKED')
- After T_MENUCONFIG ('menuconfig LEAKED')
- After T_SELECT ('select LEAKED')
- After T_IMPLY ('imply LEAKED')
- After T_DEFAULT in a choice ('default LEAKED')
All of these come in the form of T_WORD tokens, which always have their
associated string allocated on the heap in zconf.l and need to be freed.
Fix by introducing a new nonterminal 'nonconst_symbol' which takes a
T_WORD, fetches the symbol, and then frees the T_WORD string. The
already existing 'symbol' nonterminal works the same way but also
accepts T_WORD_QUOTE, corresponding to a constant symbol. T_WORD_QUOTE
should not be accepted in any of the contexts above, so the 'symbol'
nonterminal can't be reused here.
Fetching the symbol in 'nonconst_symbol' also removes a bunch of
sym_lookup() calls from actions.
Summary from Valgrind on 'menuconfig' (ARCH=x86) before the fix:
LEAK SUMMARY:
definitely lost: 711,571 bytes in 37,756 blocks
...
Summary after the fix:
LEAK SUMMARY:
definitely lost: 387,504 bytes in 15,545 blocks
...
Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-08 17:11:18 +00:00
|
|
|
menu_add_symbol(P_SELECT, $2, $3);
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:select\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
kconfig: Don't leak symbol names during parsing
Prior to this fix, zconf.y did not free symbol names from zconf.l in
these contexts:
- After T_CONFIG ('config LEAKED')
- After T_MENUCONFIG ('menuconfig LEAKED')
- After T_SELECT ('select LEAKED')
- After T_IMPLY ('imply LEAKED')
- After T_DEFAULT in a choice ('default LEAKED')
All of these come in the form of T_WORD tokens, which always have their
associated string allocated on the heap in zconf.l and need to be freed.
Fix by introducing a new nonterminal 'nonconst_symbol' which takes a
T_WORD, fetches the symbol, and then frees the T_WORD string. The
already existing 'symbol' nonterminal works the same way but also
accepts T_WORD_QUOTE, corresponding to a constant symbol. T_WORD_QUOTE
should not be accepted in any of the contexts above, so the 'symbol'
nonterminal can't be reused here.
Fetching the symbol in 'nonconst_symbol' also removes a bunch of
sym_lookup() calls from actions.
Summary from Valgrind on 'menuconfig' (ARCH=x86) before the fix:
LEAK SUMMARY:
definitely lost: 711,571 bytes in 37,756 blocks
...
Summary after the fix:
LEAK SUMMARY:
definitely lost: 387,504 bytes in 15,545 blocks
...
Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-08 17:11:18 +00:00
|
|
|
config_option: T_IMPLY nonconst_symbol if_expr T_EOL
|
2016-11-11 05:10:05 +00:00
|
|
|
{
|
kconfig: Don't leak symbol names during parsing
Prior to this fix, zconf.y did not free symbol names from zconf.l in
these contexts:
- After T_CONFIG ('config LEAKED')
- After T_MENUCONFIG ('menuconfig LEAKED')
- After T_SELECT ('select LEAKED')
- After T_IMPLY ('imply LEAKED')
- After T_DEFAULT in a choice ('default LEAKED')
All of these come in the form of T_WORD tokens, which always have their
associated string allocated on the heap in zconf.l and need to be freed.
Fix by introducing a new nonterminal 'nonconst_symbol' which takes a
T_WORD, fetches the symbol, and then frees the T_WORD string. The
already existing 'symbol' nonterminal works the same way but also
accepts T_WORD_QUOTE, corresponding to a constant symbol. T_WORD_QUOTE
should not be accepted in any of the contexts above, so the 'symbol'
nonterminal can't be reused here.
Fetching the symbol in 'nonconst_symbol' also removes a bunch of
sym_lookup() calls from actions.
Summary from Valgrind on 'menuconfig' (ARCH=x86) before the fix:
LEAK SUMMARY:
definitely lost: 711,571 bytes in 37,756 blocks
...
Summary after the fix:
LEAK SUMMARY:
definitely lost: 387,504 bytes in 15,545 blocks
...
Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-08 17:11:18 +00:00
|
|
|
menu_add_symbol(P_IMPLY, $2, $3);
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:imply\n", cur_filename, cur_lineno);
|
2016-11-11 05:10:05 +00:00
|
|
|
};
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
config_option: T_RANGE symbol symbol if_expr T_EOL
|
|
|
|
{
|
|
|
|
menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:range\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2021-03-13 19:48:36 +00:00
|
|
|
config_option: T_MODULES T_EOL
|
2018-12-11 11:01:00 +00:00
|
|
|
{
|
2021-03-13 19:48:36 +00:00
|
|
|
if (modules_sym)
|
|
|
|
zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'",
|
|
|
|
current_entry->sym->name, modules_sym->name);
|
|
|
|
modules_sym = current_entry->sym;
|
2018-12-11 11:01:00 +00:00
|
|
|
};
|
2006-06-09 05:12:44 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* choice entry */
|
|
|
|
|
2024-03-03 04:00:35 +00:00
|
|
|
choice: T_CHOICE T_EOL
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2024-04-22 16:10:54 +00:00
|
|
|
struct symbol *sym = sym_lookup(NULL, 0);
|
2024-04-27 09:16:38 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
menu_add_entry(sym);
|
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 12:54:14 +00:00
|
|
|
menu_set_type(S_BOOLEAN);
|
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 10:35:21 +00:00
|
|
|
INIT_LIST_HEAD(¤t_entry->choice_members);
|
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 12:54:14 +00:00
|
|
|
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:choice\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
choice_entry: choice choice_option_list
|
|
|
|
{
|
2024-03-10 13:45:15 +00:00
|
|
|
if (!current_entry->prompt) {
|
|
|
|
fprintf(stderr, "%s:%d: error: choice must have a prompt\n",
|
|
|
|
current_entry->filename, current_entry->lineno);
|
|
|
|
yynerrs++;
|
|
|
|
}
|
|
|
|
|
2005-11-09 05:34:53 +00:00
|
|
|
$$ = menu_add_menu();
|
2024-05-04 18:33:32 +00:00
|
|
|
|
2024-06-11 17:55:13 +00:00
|
|
|
current_choice = current_entry;
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
choice_end: end
|
|
|
|
{
|
2024-06-11 17:55:13 +00:00
|
|
|
current_choice = NULL;
|
2024-05-04 18:33:32 +00:00
|
|
|
|
2018-12-11 11:01:06 +00:00
|
|
|
if (zconf_endtoken($1, "choice")) {
|
2005-04-16 22:20:36 +00:00
|
|
|
menu_end_menu();
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:endchoice\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
kconfig: allow only 'config', 'comment', and 'if' inside 'choice'
The code block surrounded by 'if' ... 'endif' is reduced into if_stmt,
which is accepted in the 'choice' context. Therefore, you can write any
statements within a choice block by wrapping 'if y' ... 'end'.
For example, you can create a menu inside a choice, like follows:
---------------->8----------------
choice
prompt "choice"
config A
bool "A"
config B
bool "B"
if y
menu "strange menu"
config C
bool "C"
endmenu
endif
endchoice
---------------->8----------------
I want to change such a weird structure into a syntax error.
In fact, the USB gadget Kconfig had used nested 'choice' for no good
reason until commit df8df5e4bc37 ("usb: get rid of 'choice' for
legacy gadget drivers") killed it.
I think the 'source' inside 'choice' is on the fence. It is at least
gramatically sensible as long as the included file contains only
bool/tristate configs. However, it makes the code unreadable, and people
tend to forget the fact that the file is included from the choice
block. Commit 10e5e6c24963 ("usb: gadget: move choice ... endchoice to
legacy/Kconfig") got rid of the only usecase.
Going forward, you can only use 'config', 'comment', and 'if' inside
'choice'. This also recursively applies to 'if' blocks inside 'choice'.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2020-04-24 05:49:29 +00:00
|
|
|
choice_stmt: choice_entry stmt_list_in_choice choice_end
|
2005-11-09 05:34:53 +00:00
|
|
|
;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
choice_option_list:
|
|
|
|
/* empty */
|
|
|
|
| choice_option_list choice_option
|
|
|
|
| choice_option_list depends
|
|
|
|
| choice_option_list help
|
|
|
|
;
|
|
|
|
|
2019-12-17 04:14:19 +00:00
|
|
|
choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
menu_add_prompt(P_PROMPT, $2, $3);
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
kconfig: Don't leak symbol names during parsing
Prior to this fix, zconf.y did not free symbol names from zconf.l in
these contexts:
- After T_CONFIG ('config LEAKED')
- After T_MENUCONFIG ('menuconfig LEAKED')
- After T_SELECT ('select LEAKED')
- After T_IMPLY ('imply LEAKED')
- After T_DEFAULT in a choice ('default LEAKED')
All of these come in the form of T_WORD tokens, which always have their
associated string allocated on the heap in zconf.l and need to be freed.
Fix by introducing a new nonterminal 'nonconst_symbol' which takes a
T_WORD, fetches the symbol, and then frees the T_WORD string. The
already existing 'symbol' nonterminal works the same way but also
accepts T_WORD_QUOTE, corresponding to a constant symbol. T_WORD_QUOTE
should not be accepted in any of the contexts above, so the 'symbol'
nonterminal can't be reused here.
Fetching the symbol in 'nonconst_symbol' also removes a bunch of
sym_lookup() calls from actions.
Summary from Valgrind on 'menuconfig' (ARCH=x86) before the fix:
LEAK SUMMARY:
definitely lost: 711,571 bytes in 37,756 blocks
...
Summary after the fix:
LEAK SUMMARY:
definitely lost: 387,504 bytes in 15,545 blocks
...
Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-08 17:11:18 +00:00
|
|
|
choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2018-12-11 11:00:59 +00:00
|
|
|
menu_add_symbol(P_DEFAULT, $2, $3);
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:default\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2018-12-11 11:00:59 +00:00
|
|
|
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 12:54:14 +00:00
|
|
|
T_BOOL { $$ = S_BOOLEAN; }
|
|
|
|
| T_TRISTATE { $$ = S_TRISTATE; }
|
2018-12-11 11:00:59 +00:00
|
|
|
| T_INT { $$ = S_INT; }
|
|
|
|
| T_HEX { $$ = S_HEX; }
|
|
|
|
| T_STRING { $$ = S_STRING; }
|
|
|
|
|
|
|
|
default:
|
|
|
|
T_DEFAULT { $$ = S_UNKNOWN; }
|
|
|
|
| T_DEF_BOOL { $$ = S_BOOLEAN; }
|
|
|
|
| T_DEF_TRISTATE { $$ = S_TRISTATE; }
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* if entry */
|
|
|
|
|
2018-06-21 13:30:54 +00:00
|
|
|
if_entry: T_IF expr T_EOL
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:if\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
menu_add_entry(NULL);
|
|
|
|
menu_add_dep($2);
|
2005-11-09 05:34:53 +00:00
|
|
|
$$ = menu_add_menu();
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if_end: end
|
|
|
|
{
|
2018-12-11 11:01:06 +00:00
|
|
|
if (zconf_endtoken($1, "if")) {
|
2005-04-16 22:20:36 +00:00
|
|
|
menu_end_menu();
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:endif\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-12-11 11:00:54 +00:00
|
|
|
if_stmt: if_entry stmt_list if_end
|
2005-04-16 22:20:36 +00:00
|
|
|
;
|
|
|
|
|
kconfig: allow only 'config', 'comment', and 'if' inside 'choice'
The code block surrounded by 'if' ... 'endif' is reduced into if_stmt,
which is accepted in the 'choice' context. Therefore, you can write any
statements within a choice block by wrapping 'if y' ... 'end'.
For example, you can create a menu inside a choice, like follows:
---------------->8----------------
choice
prompt "choice"
config A
bool "A"
config B
bool "B"
if y
menu "strange menu"
config C
bool "C"
endmenu
endif
endchoice
---------------->8----------------
I want to change such a weird structure into a syntax error.
In fact, the USB gadget Kconfig had used nested 'choice' for no good
reason until commit df8df5e4bc37 ("usb: get rid of 'choice' for
legacy gadget drivers") killed it.
I think the 'source' inside 'choice' is on the fence. It is at least
gramatically sensible as long as the included file contains only
bool/tristate configs. However, it makes the code unreadable, and people
tend to forget the fact that the file is included from the choice
block. Commit 10e5e6c24963 ("usb: gadget: move choice ... endchoice to
legacy/Kconfig") got rid of the only usecase.
Going forward, you can only use 'config', 'comment', and 'if' inside
'choice'. This also recursively applies to 'if' blocks inside 'choice'.
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2020-04-24 05:49:29 +00:00
|
|
|
if_stmt_in_choice: if_entry stmt_list_in_choice if_end
|
|
|
|
;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* menu entry */
|
|
|
|
|
2019-12-17 04:14:19 +00:00
|
|
|
menu: T_MENU T_WORD_QUOTE T_EOL
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
menu_add_entry(NULL);
|
2005-07-28 15:56:25 +00:00
|
|
|
menu_add_prompt(P_MENU, $2, NULL);
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:menu\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2018-12-11 11:00:56 +00:00
|
|
|
menu_entry: menu menu_option_list
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2005-11-09 05:34:53 +00:00
|
|
|
$$ = menu_add_menu();
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
menu_end: end
|
|
|
|
{
|
2018-12-11 11:01:06 +00:00
|
|
|
if (zconf_endtoken($1, "menu")) {
|
2005-04-16 22:20:36 +00:00
|
|
|
menu_end_menu();
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:endmenu\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-12-11 11:00:55 +00:00
|
|
|
menu_stmt: menu_entry stmt_list menu_end
|
2005-04-16 22:20:36 +00:00
|
|
|
;
|
|
|
|
|
2018-12-11 11:00:56 +00:00
|
|
|
menu_option_list:
|
|
|
|
/* empty */
|
|
|
|
| menu_option_list visible
|
|
|
|
| menu_option_list depends
|
|
|
|
;
|
|
|
|
|
2019-12-17 04:14:19 +00:00
|
|
|
source_stmt: T_SOURCE T_WORD_QUOTE T_EOL
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:source %s\n", cur_filename, cur_lineno, $2);
|
2005-11-09 05:34:53 +00:00
|
|
|
zconf_nextfile($2);
|
2017-10-08 17:11:19 +00:00
|
|
|
free($2);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* comment entry */
|
|
|
|
|
2019-12-17 04:14:19 +00:00
|
|
|
comment: T_COMMENT T_WORD_QUOTE T_EOL
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
menu_add_entry(NULL);
|
2005-07-28 15:56:25 +00:00
|
|
|
menu_add_prompt(P_COMMENT, $2, NULL);
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:comment\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2018-12-11 11:00:57 +00:00
|
|
|
comment_stmt: comment comment_option_list
|
|
|
|
;
|
|
|
|
|
|
|
|
comment_option_list:
|
|
|
|
/* empty */
|
|
|
|
| comment_option_list depends
|
2017-10-08 22:14:48 +00:00
|
|
|
;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* help option */
|
|
|
|
|
|
|
|
help_start: T_HELP T_EOL
|
|
|
|
{
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:help\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
zconf_starthelp();
|
|
|
|
};
|
|
|
|
|
|
|
|
help: help_start T_HELPTEXT
|
|
|
|
{
|
2018-01-12 06:47:47 +00:00
|
|
|
if (current_entry->help) {
|
|
|
|
free(current_entry->help);
|
2024-09-29 17:32:38 +00:00
|
|
|
zconf_error("'%s' defined with more than one help text",
|
|
|
|
current_entry->sym->name ?: "<choice>");
|
2018-01-12 06:47:47 +00:00
|
|
|
}
|
2018-01-31 09:34:30 +00:00
|
|
|
|
|
|
|
/* Is the help text empty or all whitespace? */
|
|
|
|
if ($2[strspn($2, " \f\n\r\t\v")] == '\0')
|
2024-09-29 17:32:38 +00:00
|
|
|
zconf_error("'%s' defined with blank help text",
|
|
|
|
current_entry->sym->name ?: "<choice>");
|
2018-01-31 09:34:30 +00:00
|
|
|
|
2007-07-20 22:00:36 +00:00
|
|
|
current_entry->help = $2;
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* depends option */
|
|
|
|
|
|
|
|
depends: T_DEPENDS T_ON expr T_EOL
|
|
|
|
{
|
|
|
|
menu_add_dep($3);
|
2024-02-02 15:58:08 +00:00
|
|
|
printd(DEBUG_PARSE, "%s:%d:depends on\n", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2010-11-06 21:30:23 +00:00
|
|
|
/* visibility option */
|
2018-12-11 11:00:46 +00:00
|
|
|
visible: T_VISIBLE if_expr T_EOL
|
2010-11-06 21:30:23 +00:00
|
|
|
{
|
|
|
|
menu_add_visibility($2);
|
|
|
|
};
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* prompt statement */
|
|
|
|
|
|
|
|
prompt_stmt_opt:
|
|
|
|
/* empty */
|
2019-12-17 04:14:19 +00:00
|
|
|
| T_WORD_QUOTE if_expr
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2005-07-28 15:56:25 +00:00
|
|
|
menu_add_prompt(P_PROMPT, $1, $2);
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
2018-12-11 11:01:06 +00:00
|
|
|
end: T_ENDMENU T_EOL { $$ = "menu"; }
|
|
|
|
| T_ENDCHOICE T_EOL { $$ = "choice"; }
|
|
|
|
| T_ENDIF T_EOL { $$ = "if"; }
|
2005-04-16 22:20:36 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
if_expr: /* empty */ { $$ = NULL; }
|
|
|
|
| T_IF expr { $$ = $2; }
|
|
|
|
;
|
|
|
|
|
|
|
|
expr: symbol { $$ = expr_alloc_symbol($1); }
|
2015-06-15 12:00:21 +00:00
|
|
|
| symbol T_LESS symbol { $$ = expr_alloc_comp(E_LTH, $1, $3); }
|
|
|
|
| symbol T_LESS_EQUAL symbol { $$ = expr_alloc_comp(E_LEQ, $1, $3); }
|
|
|
|
| symbol T_GREATER symbol { $$ = expr_alloc_comp(E_GTH, $1, $3); }
|
|
|
|
| symbol T_GREATER_EQUAL symbol { $$ = expr_alloc_comp(E_GEQ, $1, $3); }
|
2005-04-16 22:20:36 +00:00
|
|
|
| symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
|
|
|
|
| symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
|
|
|
|
| T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; }
|
|
|
|
| T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); }
|
|
|
|
| expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); }
|
|
|
|
| expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
|
|
|
|
;
|
|
|
|
|
kconfig: Don't leak symbol names during parsing
Prior to this fix, zconf.y did not free symbol names from zconf.l in
these contexts:
- After T_CONFIG ('config LEAKED')
- After T_MENUCONFIG ('menuconfig LEAKED')
- After T_SELECT ('select LEAKED')
- After T_IMPLY ('imply LEAKED')
- After T_DEFAULT in a choice ('default LEAKED')
All of these come in the form of T_WORD tokens, which always have their
associated string allocated on the heap in zconf.l and need to be freed.
Fix by introducing a new nonterminal 'nonconst_symbol' which takes a
T_WORD, fetches the symbol, and then frees the T_WORD string. The
already existing 'symbol' nonterminal works the same way but also
accepts T_WORD_QUOTE, corresponding to a constant symbol. T_WORD_QUOTE
should not be accepted in any of the contexts above, so the 'symbol'
nonterminal can't be reused here.
Fetching the symbol in 'nonconst_symbol' also removes a bunch of
sym_lookup() calls from actions.
Summary from Valgrind on 'menuconfig' (ARCH=x86) before the fix:
LEAK SUMMARY:
definitely lost: 711,571 bytes in 37,756 blocks
...
Summary after the fix:
LEAK SUMMARY:
definitely lost: 387,504 bytes in 15,545 blocks
...
Signed-off-by: Ulf Magnusson <ulfalizer@gmail.com>
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-10-08 17:11:18 +00:00
|
|
|
/* For symbol definitions, selects, etc., where quotes are not accepted */
|
|
|
|
nonconst_symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); };
|
|
|
|
|
|
|
|
symbol: nonconst_symbol
|
2008-02-29 04:11:50 +00:00
|
|
|
| T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
|
2005-04-16 22:20:36 +00:00
|
|
|
;
|
|
|
|
|
kconfig: support user-defined function and recursively expanded variable
Now, we got a basic ability to test compiler capability in Kconfig.
config CC_HAS_STACKPROTECTOR
def_bool $(shell,($(CC) -Werror -fstack-protector -E -x c /dev/null -o /dev/null 2>/dev/null) && echo y || echo n)
This works, but it is ugly to repeat this long boilerplate.
We want to describe like this:
config CC_HAS_STACKPROTECTOR
bool
default $(cc-option,-fstack-protector)
It is straight-forward to add a new function, but I do not like to
hard-code specialized functions like that. Hence, here is another
feature, user-defined function. This works as a textual shorthand
with parameterization.
A user-defined function is defined by using the = operator, and can
be referenced in the same way as built-in functions. A user-defined
function in Make is referenced like $(call my-func,arg1,arg2), but I
omitted the 'call' to make the syntax shorter.
The definition of a user-defined function contains $(1), $(2), etc.
in its body to reference the parameters. It is grammatically valid
to pass more or fewer arguments when calling it. We already exploit
this feature in our makefiles; scripts/Kbuild.include defines cc-option
which takes two arguments at most, but most of the callers pass only
one argument.
By the way, a variable is supported as a subset of this feature since
a variable is "a user-defined function with zero argument". In this
context, I mean "variable" as recursively expanded variable. I will
add a different flavored variable in the next commit.
The code above can be written as follows:
[Example Code]
success = $(shell,($(1)) >/dev/null 2>&1 && echo y || echo n)
cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)
config CC_HAS_STACKPROTECTOR
def_bool $(cc-option,-fstack-protector)
[Result]
$ make -s alldefconfig && tail -n 1 .config
CONFIG_CC_HAS_STACKPROTECTOR=y
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2018-05-28 09:21:49 +00:00
|
|
|
/* assignment statement */
|
|
|
|
|
2018-12-11 11:01:02 +00:00
|
|
|
assignment_stmt: T_WORD assign_op assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); }
|
2018-12-11 11:01:01 +00:00
|
|
|
|
|
|
|
assign_op:
|
|
|
|
T_EQUAL { $$ = VAR_RECURSIVE; }
|
|
|
|
| T_COLON_EQUAL { $$ = VAR_SIMPLE; }
|
|
|
|
| T_PLUS_EQUAL { $$ = VAR_APPEND; }
|
|
|
|
;
|
kconfig: support user-defined function and recursively expanded variable
Now, we got a basic ability to test compiler capability in Kconfig.
config CC_HAS_STACKPROTECTOR
def_bool $(shell,($(CC) -Werror -fstack-protector -E -x c /dev/null -o /dev/null 2>/dev/null) && echo y || echo n)
This works, but it is ugly to repeat this long boilerplate.
We want to describe like this:
config CC_HAS_STACKPROTECTOR
bool
default $(cc-option,-fstack-protector)
It is straight-forward to add a new function, but I do not like to
hard-code specialized functions like that. Hence, here is another
feature, user-defined function. This works as a textual shorthand
with parameterization.
A user-defined function is defined by using the = operator, and can
be referenced in the same way as built-in functions. A user-defined
function in Make is referenced like $(call my-func,arg1,arg2), but I
omitted the 'call' to make the syntax shorter.
The definition of a user-defined function contains $(1), $(2), etc.
in its body to reference the parameters. It is grammatically valid
to pass more or fewer arguments when calling it. We already exploit
this feature in our makefiles; scripts/Kbuild.include defines cc-option
which takes two arguments at most, but most of the callers pass only
one argument.
By the way, a variable is supported as a subset of this feature since
a variable is "a user-defined function with zero argument". In this
context, I mean "variable" as recursively expanded variable. I will
add a different flavored variable in the next commit.
The code above can be written as follows:
[Example Code]
success = $(shell,($(1)) >/dev/null 2>&1 && echo y || echo n)
cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)
config CC_HAS_STACKPROTECTOR
def_bool $(cc-option,-fstack-protector)
[Result]
$ make -s alldefconfig && tail -n 1 .config
CONFIG_CC_HAS_STACKPROTECTOR=y
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2018-05-28 09:21:49 +00:00
|
|
|
|
|
|
|
assign_val:
|
|
|
|
/* empty */ { $$ = xstrdup(""); };
|
|
|
|
| T_ASSIGN_VAL
|
|
|
|
;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
%%
|
|
|
|
|
2024-05-04 18:33:33 +00:00
|
|
|
/**
|
|
|
|
* choice_check_sanity - check sanity of a choice member
|
|
|
|
*
|
|
|
|
* @menu: menu of the choice member
|
|
|
|
*
|
|
|
|
* Return: -1 if an error is found, 0 otherwise.
|
|
|
|
*/
|
2024-07-07 15:38:05 +00:00
|
|
|
static int choice_check_sanity(const struct menu *menu)
|
2024-05-04 18:33:33 +00:00
|
|
|
{
|
|
|
|
struct property *prop;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
for (prop = menu->sym->prop; prop; prop = prop->next) {
|
|
|
|
if (prop->type == P_DEFAULT) {
|
|
|
|
fprintf(stderr, "%s:%d: error: %s",
|
|
|
|
prop->filename, prop->lineno,
|
|
|
|
"defaults for choice values not supported\n");
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prop->menu != menu && prop->type == P_PROMPT &&
|
|
|
|
prop->menu->parent != menu->parent) {
|
|
|
|
fprintf(stderr, "%s:%d: error: %s",
|
|
|
|
prop->filename, prop->lineno,
|
|
|
|
"choice value has a prompt outside its choice group\n");
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
void conf_parse(const char *name)
|
|
|
|
{
|
2024-02-11 12:41:04 +00:00
|
|
|
struct menu *menu;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2024-02-02 15:58:04 +00:00
|
|
|
autoconf_cmd = str_new();
|
|
|
|
|
2024-02-02 15:58:05 +00:00
|
|
|
str_printf(&autoconf_cmd, "\ndeps_config := \\\n");
|
2024-02-02 15:58:04 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
zconf_initscan(name);
|
|
|
|
|
2009-11-25 10:28:43 +00:00
|
|
|
_menu_init();
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2005-11-09 05:34:53 +00:00
|
|
|
if (getenv("ZCONF_DEBUG"))
|
2018-01-11 15:50:50 +00:00
|
|
|
yydebug = 1;
|
|
|
|
yyparse();
|
kconfig: support user-defined function and recursively expanded variable
Now, we got a basic ability to test compiler capability in Kconfig.
config CC_HAS_STACKPROTECTOR
def_bool $(shell,($(CC) -Werror -fstack-protector -E -x c /dev/null -o /dev/null 2>/dev/null) && echo y || echo n)
This works, but it is ugly to repeat this long boilerplate.
We want to describe like this:
config CC_HAS_STACKPROTECTOR
bool
default $(cc-option,-fstack-protector)
It is straight-forward to add a new function, but I do not like to
hard-code specialized functions like that. Hence, here is another
feature, user-defined function. This works as a textual shorthand
with parameterization.
A user-defined function is defined by using the = operator, and can
be referenced in the same way as built-in functions. A user-defined
function in Make is referenced like $(call my-func,arg1,arg2), but I
omitted the 'call' to make the syntax shorter.
The definition of a user-defined function contains $(1), $(2), etc.
in its body to reference the parameters. It is grammatically valid
to pass more or fewer arguments when calling it. We already exploit
this feature in our makefiles; scripts/Kbuild.include defines cc-option
which takes two arguments at most, but most of the callers pass only
one argument.
By the way, a variable is supported as a subset of this feature since
a variable is "a user-defined function with zero argument". In this
context, I mean "variable" as recursively expanded variable. I will
add a different flavored variable in the next commit.
The code above can be written as follows:
[Example Code]
success = $(shell,($(1)) >/dev/null 2>&1 && echo y || echo n)
cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)
config CC_HAS_STACKPROTECTOR
def_bool $(cc-option,-fstack-protector)
[Result]
$ make -s alldefconfig && tail -n 1 .config
CONFIG_CC_HAS_STACKPROTECTOR=y
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2018-05-28 09:21:49 +00:00
|
|
|
|
2024-02-02 15:58:05 +00:00
|
|
|
str_printf(&autoconf_cmd,
|
|
|
|
"\n"
|
|
|
|
"$(autoconfig): $(deps_config)\n"
|
|
|
|
"$(deps_config): ;\n");
|
|
|
|
|
|
|
|
env_write_dep(&autoconf_cmd);
|
|
|
|
|
kconfig: support user-defined function and recursively expanded variable
Now, we got a basic ability to test compiler capability in Kconfig.
config CC_HAS_STACKPROTECTOR
def_bool $(shell,($(CC) -Werror -fstack-protector -E -x c /dev/null -o /dev/null 2>/dev/null) && echo y || echo n)
This works, but it is ugly to repeat this long boilerplate.
We want to describe like this:
config CC_HAS_STACKPROTECTOR
bool
default $(cc-option,-fstack-protector)
It is straight-forward to add a new function, but I do not like to
hard-code specialized functions like that. Hence, here is another
feature, user-defined function. This works as a textual shorthand
with parameterization.
A user-defined function is defined by using the = operator, and can
be referenced in the same way as built-in functions. A user-defined
function in Make is referenced like $(call my-func,arg1,arg2), but I
omitted the 'call' to make the syntax shorter.
The definition of a user-defined function contains $(1), $(2), etc.
in its body to reference the parameters. It is grammatically valid
to pass more or fewer arguments when calling it. We already exploit
this feature in our makefiles; scripts/Kbuild.include defines cc-option
which takes two arguments at most, but most of the callers pass only
one argument.
By the way, a variable is supported as a subset of this feature since
a variable is "a user-defined function with zero argument". In this
context, I mean "variable" as recursively expanded variable. I will
add a different flavored variable in the next commit.
The code above can be written as follows:
[Example Code]
success = $(shell,($(1)) >/dev/null 2>&1 && echo y || echo n)
cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)
config CC_HAS_STACKPROTECTOR
def_bool $(cc-option,-fstack-protector)
[Result]
$ make -s alldefconfig && tail -n 1 .config
CONFIG_CC_HAS_STACKPROTECTOR=y
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2018-05-28 09:21:49 +00:00
|
|
|
/* Variables are expanded in the parse phase. We can free them here. */
|
|
|
|
variable_all_del();
|
|
|
|
|
2018-01-11 15:50:50 +00:00
|
|
|
if (yynerrs)
|
2005-04-16 22:20:36 +00:00
|
|
|
exit(1);
|
2013-09-03 15:07:18 +00:00
|
|
|
if (!modules_sym)
|
2024-02-02 15:58:03 +00:00
|
|
|
modules_sym = &symbol_no;
|
2010-09-10 01:17:26 +00:00
|
|
|
|
2018-05-28 09:21:42 +00:00
|
|
|
if (!menu_has_prompt(&rootmenu)) {
|
|
|
|
current_entry = &rootmenu;
|
2018-05-28 09:21:44 +00:00
|
|
|
menu_add_prompt(P_MENU, "Main menu", NULL);
|
2018-05-28 09:21:42 +00:00
|
|
|
}
|
2010-09-10 01:17:26 +00:00
|
|
|
|
2024-03-23 08:51:01 +00:00
|
|
|
menu_finalize();
|
2024-02-11 12:41:04 +00:00
|
|
|
|
2024-04-21 09:02:52 +00:00
|
|
|
menu_for_each_entry(menu) {
|
2024-05-04 18:33:33 +00:00
|
|
|
struct menu *child;
|
|
|
|
|
2024-02-11 12:41:04 +00:00
|
|
|
if (menu->sym && sym_check_deps(menu->sym))
|
2018-01-11 15:50:50 +00:00
|
|
|
yynerrs++;
|
2024-05-04 18:33:33 +00:00
|
|
|
|
|
|
|
if (menu->sym && sym_is_choice(menu->sym)) {
|
|
|
|
menu_for_each_sub_entry(child, menu)
|
|
|
|
if (child->sym && choice_check_sanity(child))
|
|
|
|
yynerrs++;
|
|
|
|
}
|
2014-06-10 10:08:13 +00:00
|
|
|
}
|
2024-02-11 12:41:04 +00:00
|
|
|
|
2018-01-11 15:50:50 +00:00
|
|
|
if (yynerrs)
|
2007-05-06 07:20:10 +00:00
|
|
|
exit(1);
|
2021-04-10 06:57:22 +00:00
|
|
|
conf_set_changed(true);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2018-12-11 11:01:06 +00:00
|
|
|
static bool zconf_endtoken(const char *tokenname,
|
|
|
|
const char *expected_tokenname)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2018-12-11 11:01:06 +00:00
|
|
|
if (strcmp(tokenname, expected_tokenname)) {
|
2005-11-09 05:34:53 +00:00
|
|
|
zconf_error("unexpected '%s' within %s block",
|
2018-12-11 11:01:06 +00:00
|
|
|
tokenname, expected_tokenname);
|
2018-01-11 15:50:50 +00:00
|
|
|
yynerrs++;
|
2005-04-16 22:20:36 +00:00
|
|
|
return false;
|
|
|
|
}
|
2024-02-02 15:58:09 +00:00
|
|
|
if (strcmp(current_menu->filename, cur_filename)) {
|
2005-11-09 05:34:53 +00:00
|
|
|
zconf_error("'%s' in different file than '%s'",
|
2018-12-11 11:01:06 +00:00
|
|
|
tokenname, expected_tokenname);
|
2005-11-09 05:34:53 +00:00
|
|
|
fprintf(stderr, "%s:%d: location of the '%s'\n",
|
2024-02-02 15:58:09 +00:00
|
|
|
current_menu->filename, current_menu->lineno,
|
2018-12-11 11:01:06 +00:00
|
|
|
expected_tokenname);
|
2018-01-11 15:50:50 +00:00
|
|
|
yynerrs++;
|
2005-04-16 22:20:36 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2005-11-09 05:34:53 +00:00
|
|
|
static void zconf_error(const char *err, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
2018-01-11 15:50:50 +00:00
|
|
|
yynerrs++;
|
2024-02-02 15:58:08 +00:00
|
|
|
fprintf(stderr, "%s:%d: ", cur_filename, cur_lineno);
|
2005-04-16 22:20:36 +00:00
|
|
|
va_start(ap, err);
|
|
|
|
vfprintf(stderr, err, ap);
|
|
|
|
va_end(ap);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
|
|
|
|
2018-01-11 15:50:50 +00:00
|
|
|
static void yyerror(const char *err)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2024-02-02 15:58:08 +00:00
|
|
|
fprintf(stderr, "%s:%d: %s\n", cur_filename, cur_lineno, err);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2009-10-15 19:13:36 +00:00
|
|
|
static void print_quoted_string(FILE *out, const char *str)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
const char *p;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
putc('"', out);
|
|
|
|
while ((p = strchr(str, '"'))) {
|
|
|
|
len = p - str;
|
|
|
|
if (len)
|
|
|
|
fprintf(out, "%.*s", len, str);
|
|
|
|
fputs("\\\"", out);
|
|
|
|
str = p + 1;
|
|
|
|
}
|
|
|
|
fputs(str, out);
|
|
|
|
putc('"', out);
|
|
|
|
}
|
|
|
|
|
2024-07-07 15:38:05 +00:00
|
|
|
static void print_symbol(FILE *out, const struct menu *menu)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
struct symbol *sym = menu->sym;
|
|
|
|
struct property *prop;
|
|
|
|
|
|
|
|
if (sym_is_choice(sym))
|
2010-04-14 03:44:20 +00:00
|
|
|
fprintf(out, "\nchoice\n");
|
2005-04-16 22:20:36 +00:00
|
|
|
else
|
2010-04-14 03:44:20 +00:00
|
|
|
fprintf(out, "\nconfig %s\n", sym->name);
|
2005-04-16 22:20:36 +00:00
|
|
|
switch (sym->type) {
|
|
|
|
case S_BOOLEAN:
|
2017-12-15 15:38:02 +00:00
|
|
|
fputs(" bool\n", out);
|
2005-04-16 22:20:36 +00:00
|
|
|
break;
|
|
|
|
case S_TRISTATE:
|
|
|
|
fputs(" tristate\n", out);
|
|
|
|
break;
|
|
|
|
case S_STRING:
|
|
|
|
fputs(" string\n", out);
|
|
|
|
break;
|
|
|
|
case S_INT:
|
|
|
|
fputs(" integer\n", out);
|
|
|
|
break;
|
|
|
|
case S_HEX:
|
|
|
|
fputs(" hex\n", out);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fputs(" ???\n", out);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
for (prop = sym->prop; prop; prop = prop->next) {
|
|
|
|
if (prop->menu != menu)
|
|
|
|
continue;
|
|
|
|
switch (prop->type) {
|
|
|
|
case P_PROMPT:
|
|
|
|
fputs(" prompt ", out);
|
|
|
|
print_quoted_string(out, prop->text);
|
|
|
|
if (!expr_is_yes(prop->visible.expr)) {
|
|
|
|
fputs(" if ", out);
|
|
|
|
expr_fprint(prop->visible.expr, out);
|
|
|
|
}
|
|
|
|
fputc('\n', out);
|
|
|
|
break;
|
|
|
|
case P_DEFAULT:
|
|
|
|
fputs( " default ", out);
|
|
|
|
expr_fprint(prop->expr, out);
|
|
|
|
if (!expr_is_yes(prop->visible.expr)) {
|
|
|
|
fputs(" if ", out);
|
|
|
|
expr_fprint(prop->visible.expr, out);
|
|
|
|
}
|
|
|
|
fputc('\n', out);
|
|
|
|
break;
|
2010-04-14 03:44:20 +00:00
|
|
|
case P_SELECT:
|
|
|
|
fputs( " select ", out);
|
|
|
|
expr_fprint(prop->expr, out);
|
|
|
|
fputc('\n', out);
|
|
|
|
break;
|
2016-11-11 05:10:05 +00:00
|
|
|
case P_IMPLY:
|
|
|
|
fputs( " imply ", out);
|
|
|
|
expr_fprint(prop->expr, out);
|
|
|
|
fputc('\n', out);
|
|
|
|
break;
|
2010-04-14 03:44:20 +00:00
|
|
|
case P_RANGE:
|
|
|
|
fputs( " range ", out);
|
|
|
|
expr_fprint(prop->expr, out);
|
|
|
|
fputc('\n', out);
|
|
|
|
break;
|
|
|
|
case P_MENU:
|
|
|
|
fputs( " menu ", out);
|
|
|
|
print_quoted_string(out, prop->text);
|
|
|
|
fputc('\n', out);
|
|
|
|
break;
|
2005-04-16 22:20:36 +00:00
|
|
|
default:
|
|
|
|
fprintf(out, " unknown prop %d!\n", prop->type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-07-20 22:00:36 +00:00
|
|
|
if (menu->help) {
|
|
|
|
int len = strlen(menu->help);
|
|
|
|
while (menu->help[--len] == '\n')
|
|
|
|
menu->help[len] = 0;
|
|
|
|
fprintf(out, " help\n%s\n", menu->help);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void zconfdump(FILE *out)
|
|
|
|
{
|
|
|
|
struct property *prop;
|
|
|
|
struct symbol *sym;
|
|
|
|
struct menu *menu;
|
|
|
|
|
|
|
|
menu = rootmenu.list;
|
|
|
|
while (menu) {
|
|
|
|
if ((sym = menu->sym))
|
|
|
|
print_symbol(out, menu);
|
|
|
|
else if ((prop = menu->prompt)) {
|
|
|
|
switch (prop->type) {
|
|
|
|
case P_COMMENT:
|
|
|
|
fputs("\ncomment ", out);
|
|
|
|
print_quoted_string(out, prop->text);
|
|
|
|
fputs("\n", out);
|
|
|
|
break;
|
|
|
|
case P_MENU:
|
|
|
|
fputs("\nmenu ", out);
|
|
|
|
print_quoted_string(out, prop->text);
|
|
|
|
fputs("\n", out);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
if (!expr_is_yes(prop->visible.expr)) {
|
|
|
|
fputs(" depends ", out);
|
|
|
|
expr_fprint(prop->visible.expr, out);
|
|
|
|
fputc('\n', out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (menu->list)
|
|
|
|
menu = menu->list;
|
|
|
|
else if (menu->next)
|
|
|
|
menu = menu->next;
|
|
|
|
else while ((menu = menu->parent)) {
|
|
|
|
if (menu->prompt && menu->prompt->type == P_MENU)
|
|
|
|
fputs("\nendmenu\n", out);
|
|
|
|
if (menu->next) {
|
|
|
|
menu = menu->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|