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 df8df5e4bc ("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 10e5e6c249 ("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>
This commit is contained in:
Masahiro Yamada 2020-04-24 14:49:29 +09:00
parent b7546111a4
commit 09d5873e4d

View File

@ -119,20 +119,24 @@ mainmenu_stmt: T_MAINMENU T_WORD_QUOTE T_EOL
stmt_list: stmt_list:
/* empty */ /* empty */
| stmt_list common_stmt | stmt_list assignment_stmt
| stmt_list choice_stmt | stmt_list choice_stmt
| stmt_list comment_stmt
| stmt_list config_stmt
| stmt_list if_stmt
| stmt_list menu_stmt | stmt_list menu_stmt
| stmt_list menuconfig_stmt
| stmt_list source_stmt
| stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
| stmt_list error T_EOL { zconf_error("invalid statement"); } | stmt_list error T_EOL { zconf_error("invalid statement"); }
; ;
common_stmt: stmt_list_in_choice:
if_stmt /* empty */
| comment_stmt | stmt_list_in_choice comment_stmt
| config_stmt | stmt_list_in_choice config_stmt
| menuconfig_stmt | stmt_list_in_choice if_stmt_in_choice
| source_stmt | stmt_list_in_choice error T_EOL { zconf_error("invalid statement"); }
| assignment_stmt
; ;
/* config/menuconfig entry */ /* config/menuconfig entry */
@ -254,7 +258,7 @@ choice_end: end
} }
}; };
choice_stmt: choice_entry choice_block choice_end choice_stmt: choice_entry stmt_list_in_choice choice_end
; ;
choice_option_list: choice_option_list:
@ -305,11 +309,6 @@ default:
| T_DEF_BOOL { $$ = S_BOOLEAN; } | T_DEF_BOOL { $$ = S_BOOLEAN; }
| T_DEF_TRISTATE { $$ = S_TRISTATE; } | T_DEF_TRISTATE { $$ = S_TRISTATE; }
choice_block:
/* empty */
| choice_block common_stmt
;
/* if entry */ /* if entry */
if_entry: T_IF expr T_EOL if_entry: T_IF expr T_EOL
@ -331,6 +330,9 @@ if_end: end
if_stmt: if_entry stmt_list if_end if_stmt: if_entry stmt_list if_end
; ;
if_stmt_in_choice: if_entry stmt_list_in_choice if_end
;
/* menu entry */ /* menu entry */
menu: T_MENU T_WORD_QUOTE T_EOL menu: T_MENU T_WORD_QUOTE T_EOL