2005-04-17 02:20:36 +04:00
/*
* Copyright ( C ) 2002 Roman Zippel < zippel @ linux - m68k . org >
* Released under the terms of the GNU GPL v2 .0 .
*/
2011-06-02 00:06:22 +04:00
# include <ctype.h>
2011-06-02 00:00:46 +04:00
# include <stdarg.h>
2005-04-17 02:20:36 +04:00
# include <stdlib.h>
# include <string.h>
# include "lkc.h"
2011-08-04 05:52:07 +04:00
static const char nohelp_text [ ] = " There is no help available for this option. " ;
2009-07-12 12:11:44 +04:00
2005-04-17 02:20:36 +04:00
struct menu rootmenu ;
static struct menu * * last_entry_ptr ;
struct file * file_list ;
struct file * current_file ;
2008-01-14 06:50:54 +03:00
void menu_warn ( struct menu * menu , const char * fmt , . . . )
2005-04-17 02:20:36 +04:00
{
va_list ap ;
va_start ( ap , fmt ) ;
fprintf ( stderr , " %s:%d:warning: " , menu - > file - > name , menu - > lineno ) ;
vfprintf ( stderr , fmt , ap ) ;
fprintf ( stderr , " \n " ) ;
va_end ( ap ) ;
}
static void prop_warn ( struct property * prop , const char * fmt , . . . )
{
va_list ap ;
va_start ( ap , fmt ) ;
fprintf ( stderr , " %s:%d:warning: " , prop - > file - > name , prop - > lineno ) ;
vfprintf ( stderr , fmt , ap ) ;
fprintf ( stderr , " \n " ) ;
va_end ( ap ) ;
}
2009-11-25 13:28:43 +03:00
void _menu_init ( void )
2005-04-17 02:20:36 +04:00
{
current_entry = current_menu = & rootmenu ;
last_entry_ptr = & rootmenu . list ;
}
void menu_add_entry ( struct symbol * sym )
{
struct menu * menu ;
2012-11-06 18:32:08 +04:00
menu = xmalloc ( sizeof ( * menu ) ) ;
2005-04-17 02:20:36 +04:00
memset ( menu , 0 , sizeof ( * menu ) ) ;
menu - > sym = sym ;
menu - > parent = current_menu ;
menu - > file = current_file ;
menu - > lineno = zconf_lineno ( ) ;
* last_entry_ptr = menu ;
last_entry_ptr = & menu - > next ;
current_entry = menu ;
2010-08-01 01:35:29 +04:00
if ( sym )
menu_add_symbol ( P_SYMBOL , sym , NULL ) ;
2005-04-17 02:20:36 +04:00
}
void menu_end_entry ( void )
{
}
2005-11-09 08:34:53 +03:00
struct menu * menu_add_menu ( void )
2005-04-17 02:20:36 +04:00
{
2005-11-09 08:34:53 +03:00
menu_end_entry ( ) ;
2005-04-17 02:20:36 +04:00
last_entry_ptr = & current_entry - > list ;
2005-11-09 08:34:53 +03:00
return current_menu = current_entry ;
2005-04-17 02:20:36 +04:00
}
void menu_end_menu ( void )
{
last_entry_ptr = & current_menu - > next ;
current_menu = current_menu - > parent ;
}
2009-09-18 23:49:23 +04:00
static struct expr * menu_check_dep ( struct expr * e )
2005-04-17 02:20:36 +04:00
{
if ( ! e )
return e ;
switch ( e - > type ) {
case E_NOT :
e - > left . expr = menu_check_dep ( e - > left . expr ) ;
break ;
case E_OR :
case E_AND :
e - > left . expr = menu_check_dep ( e - > left . expr ) ;
e - > right . expr = menu_check_dep ( e - > right . expr ) ;
break ;
case E_SYMBOL :
/* change 'm' into 'm' && MODULES */
if ( e - > left . sym = = & symbol_mod )
return expr_alloc_and ( e , expr_alloc_symbol ( modules_sym ) ) ;
break ;
default :
break ;
}
return e ;
}
void menu_add_dep ( struct expr * dep )
{
current_entry - > dep = expr_alloc_and ( current_entry - > dep , menu_check_dep ( dep ) ) ;
}
void menu_set_type ( int type )
{
struct symbol * sym = current_entry - > sym ;
if ( sym - > type = = type )
return ;
if ( sym - > type = = S_UNKNOWN ) {
sym - > type = type ;
return ;
}
2013-10-03 20:32:02 +04:00
menu_warn ( current_entry ,
" ignoring type redefinition of '%s' from '%s' to '%s' " ,
sym - > name ? sym - > name : " <choice> " ,
sym_type_name ( sym - > type ) , sym_type_name ( type ) ) ;
2005-04-17 02:20:36 +04:00
}
struct property * menu_add_prop ( enum prop_type type , char * prompt , struct expr * expr , struct expr * dep )
{
struct property * prop = prop_alloc ( type , current_entry - > sym ) ;
prop - > menu = current_entry ;
prop - > expr = expr ;
prop - > visible . expr = menu_check_dep ( dep ) ;
if ( prompt ) {
2006-06-09 09:12:48 +04:00
if ( isspace ( * prompt ) ) {
prop_warn ( prop , " leading whitespace ignored " ) ;
while ( isspace ( * prompt ) )
prompt + + ;
}
2010-09-05 00:05:15 +04:00
if ( current_entry - > prompt & & current_entry ! = & rootmenu )
2006-06-09 09:12:48 +04:00
prop_warn ( prop , " prompt redefined " ) ;
2010-12-09 11:11:38 +03:00
/* Apply all upper menus' visibilities to actual prompts. */
if ( type = = P_PROMPT ) {
struct menu * menu = current_entry ;
while ( ( menu = menu - > parent ) ! = NULL ) {
2013-05-21 12:54:11 +04:00
struct expr * dup_expr ;
2010-12-09 11:11:38 +03:00
if ( ! menu - > visibility )
continue ;
2013-05-21 12:54:11 +04:00
/*
* Do not add a reference to the
* menu ' s visibility expression but
* use a copy of it . Otherwise the
* expression reduction functions
* will modify expressions that have
* multiple references which can
* cause unwanted side effects .
*/
dup_expr = expr_copy ( menu - > visibility ) ;
2010-12-09 11:11:38 +03:00
prop - > visible . expr
= expr_alloc_and ( prop - > visible . expr ,
2013-05-21 12:54:11 +04:00
dup_expr ) ;
2010-12-09 11:11:38 +03:00
}
}
2005-04-17 02:20:36 +04:00
current_entry - > prompt = prop ;
}
2006-06-09 09:12:48 +04:00
prop - > text = prompt ;
2005-04-17 02:20:36 +04:00
return prop ;
}
2005-07-28 19:56:25 +04:00
struct property * menu_add_prompt ( enum prop_type type , char * prompt , struct expr * dep )
2005-04-17 02:20:36 +04:00
{
2005-07-28 19:56:25 +04:00
return menu_add_prop ( type , prompt , NULL , dep ) ;
2005-04-17 02:20:36 +04:00
}
2010-11-07 00:30:23 +03:00
void menu_add_visibility ( struct expr * expr )
{
current_entry - > visibility = expr_alloc_and ( current_entry - > visibility ,
expr ) ;
}
2005-04-17 02:20:36 +04:00
void menu_add_expr ( enum prop_type type , struct expr * expr , struct expr * dep )
{
menu_add_prop ( type , NULL , expr , dep ) ;
}
void menu_add_symbol ( enum prop_type type , struct symbol * sym , struct expr * dep )
{
menu_add_prop ( type , NULL , expr_alloc_symbol ( sym ) , dep ) ;
}
2006-06-09 09:12:44 +04:00
void menu_add_option ( int token , char * arg )
{
2006-06-09 09:12:45 +04:00
switch ( token ) {
case T_OPT_MODULES :
2013-09-04 00:22:26 +04:00
if ( modules_sym )
zconf_error ( " symbol '%s' redefines option 'modules' "
" already defined by symbol '%s' " ,
current_entry - > sym - > name ,
modules_sym - > name
) ;
2013-09-03 19:07:18 +04:00
modules_sym = current_entry - > sym ;
2006-06-09 09:12:45 +04:00
break ;
case T_OPT_DEFCONFIG_LIST :
if ( ! sym_defconfig_list )
sym_defconfig_list = current_entry - > sym ;
else if ( sym_defconfig_list ! = current_entry - > sym )
zconf_error ( " trying to redefine defconfig symbol " ) ;
break ;
2008-01-14 06:50:54 +03:00
case T_OPT_ENV :
prop_add_env ( arg ) ;
break ;
2006-06-09 09:12:45 +04:00
}
2006-06-09 09:12:44 +04:00
}
2010-12-05 09:29:25 +03:00
static int menu_validate_number ( struct symbol * sym , struct symbol * sym2 )
2005-11-09 08:34:49 +03:00
{
return sym2 - > type = = S_INT | | sym2 - > type = = S_HEX | |
( sym2 - > type = = S_UNKNOWN & & sym_string_valid ( sym , sym2 - > name ) ) ;
}
2009-09-18 23:49:23 +04:00
static void sym_check_prop ( struct symbol * sym )
2005-04-17 02:20:36 +04:00
{
struct property * prop ;
struct symbol * sym2 ;
for ( prop = sym - > prop ; prop ; prop = prop - > next ) {
switch ( prop - > type ) {
case P_DEFAULT :
if ( ( sym - > type = = S_STRING | | sym - > type = = S_INT | | sym - > type = = S_HEX ) & &
prop - > expr - > type ! = E_SYMBOL )
prop_warn ( prop ,
2010-04-14 07:44:05 +04:00
" default for config symbol '%s' "
2005-04-17 02:20:36 +04:00
" must be a single symbol " , sym - > name ) ;
2010-12-05 09:29:25 +03:00
if ( prop - > expr - > type ! = E_SYMBOL )
break ;
sym2 = prop_get_symbol ( prop ) ;
if ( sym - > type = = S_HEX | | sym - > type = = S_INT ) {
if ( ! menu_validate_number ( sym , sym2 ) )
prop_warn ( prop ,
" '%s': number is invalid " ,
sym - > name ) ;
}
2005-04-17 02:20:36 +04:00
break ;
case P_SELECT :
sym2 = prop_get_symbol ( prop ) ;
if ( sym - > type ! = S_BOOLEAN & & sym - > type ! = S_TRISTATE )
prop_warn ( prop ,
" config symbol '%s' uses select, but is "
" not boolean or tristate " , sym - > name ) ;
2008-02-02 23:09:57 +03:00
else if ( sym2 - > type ! = S_UNKNOWN & &
sym2 - > type ! = S_BOOLEAN & &
sym2 - > type ! = S_TRISTATE )
2005-04-17 02:20:36 +04:00
prop_warn ( prop ,
" '%s' has wrong type. 'select' only "
" accept arguments of boolean and "
" tristate type " , sym2 - > name ) ;
break ;
case P_RANGE :
if ( sym - > type ! = S_INT & & sym - > type ! = S_HEX )
prop_warn ( prop , " range is only allowed "
" for int or hex symbols " ) ;
2010-12-05 09:29:25 +03:00
if ( ! menu_validate_number ( sym , prop - > expr - > left . sym ) | |
! menu_validate_number ( sym , prop - > expr - > right . sym ) )
2005-04-17 02:20:36 +04:00
prop_warn ( prop , " range is invalid " ) ;
break ;
default :
;
}
}
}
void menu_finalize ( struct menu * parent )
{
struct menu * menu , * last_menu ;
struct symbol * sym ;
struct property * prop ;
struct expr * parentdep , * basedep , * dep , * dep2 , * * ep ;
sym = parent - > sym ;
if ( parent - > list ) {
if ( sym & & sym_is_choice ( sym ) ) {
2008-02-29 07:11:50 +03:00
if ( sym - > type = = S_UNKNOWN ) {
/* find the first choice value to find out choice type */
current_entry = parent ;
for ( menu = parent - > list ; menu ; menu = menu - > next ) {
if ( menu - > sym & & menu - > sym - > type ! = S_UNKNOWN ) {
2008-01-24 14:54:23 +03:00
menu_set_type ( menu - > sym - > type ) ;
2008-02-29 07:11:50 +03:00
break ;
}
2005-04-17 02:20:36 +04:00
}
}
2008-02-29 07:11:50 +03:00
/* set the type of the remaining choice values */
for ( menu = parent - > list ; menu ; menu = menu - > next ) {
current_entry = menu ;
if ( menu - > sym & & menu - > sym - > type = = S_UNKNOWN )
menu_set_type ( sym - > type ) ;
}
2005-04-17 02:20:36 +04:00
parentdep = expr_alloc_symbol ( sym ) ;
} else if ( parent - > prompt )
parentdep = parent - > prompt - > visible . expr ;
else
parentdep = parent - > dep ;
for ( menu = parent - > list ; menu ; menu = menu - > next ) {
basedep = expr_transform ( menu - > dep ) ;
2007-10-20 08:25:45 +04:00
basedep = expr_alloc_and ( expr_copy ( parentdep ) , basedep ) ;
2005-04-17 02:20:36 +04:00
basedep = expr_eliminate_dups ( basedep ) ;
menu - > dep = basedep ;
if ( menu - > sym )
prop = menu - > sym - > prop ;
else
prop = menu - > prompt ;
for ( ; prop ; prop = prop - > next ) {
if ( prop - > menu ! = menu )
continue ;
dep = expr_transform ( prop - > visible . expr ) ;
dep = expr_alloc_and ( expr_copy ( basedep ) , dep ) ;
dep = expr_eliminate_dups ( dep ) ;
if ( menu - > sym & & menu - > sym - > type ! = S_TRISTATE )
dep = expr_trans_bool ( dep ) ;
prop - > visible . expr = dep ;
if ( prop - > type = = P_SELECT ) {
struct symbol * es = prop_get_symbol ( prop ) ;
es - > rev_dep . expr = expr_alloc_or ( es - > rev_dep . expr ,
expr_alloc_and ( expr_alloc_symbol ( menu - > sym ) , expr_copy ( dep ) ) ) ;
}
}
}
for ( menu = parent - > list ; menu ; menu = menu - > next )
menu_finalize ( menu ) ;
} else if ( sym ) {
basedep = parent - > prompt ? parent - > prompt - > visible . expr : NULL ;
basedep = expr_trans_compare ( basedep , E_UNEQUAL , & symbol_no ) ;
basedep = expr_eliminate_dups ( expr_transform ( basedep ) ) ;
last_menu = NULL ;
for ( menu = parent - > next ; menu ; menu = menu - > next ) {
dep = menu - > prompt ? menu - > prompt - > visible . expr : menu - > dep ;
if ( ! expr_contains_symbol ( dep , sym ) )
break ;
if ( expr_depends_symbol ( dep , sym ) )
goto next ;
dep = expr_trans_compare ( dep , E_UNEQUAL , & symbol_no ) ;
dep = expr_eliminate_dups ( expr_transform ( dep ) ) ;
dep2 = expr_copy ( basedep ) ;
expr_eliminate_eq ( & dep , & dep2 ) ;
expr_free ( dep ) ;
if ( ! expr_is_yes ( dep2 ) ) {
expr_free ( dep2 ) ;
break ;
}
expr_free ( dep2 ) ;
next :
menu_finalize ( menu ) ;
menu - > parent = parent ;
last_menu = menu ;
}
if ( last_menu ) {
parent - > list = parent - > next ;
parent - > next = last_menu - > next ;
last_menu - > next = NULL ;
}
2010-09-27 00:22:03 +04:00
2011-06-08 09:42:11 +04:00
sym - > dir_dep . expr = expr_alloc_or ( sym - > dir_dep . expr , parent - > dep ) ;
2005-04-17 02:20:36 +04:00
}
for ( menu = parent - > list ; menu ; menu = menu - > next ) {
2008-02-29 07:11:50 +03:00
if ( sym & & sym_is_choice ( sym ) & &
menu - > sym & & ! sym_is_choice_value ( menu - > sym ) ) {
current_entry = menu ;
2005-04-17 02:20:36 +04:00
menu - > sym - > flags | = SYMBOL_CHOICEVAL ;
if ( ! menu - > prompt )
menu_warn ( menu , " choice value must have a prompt " ) ;
for ( prop = menu - > sym - > prop ; prop ; prop = prop - > next ) {
if ( prop - > type = = P_DEFAULT )
prop_warn ( prop , " defaults for choice "
2008-02-29 07:11:50 +03:00
" values not supported " ) ;
if ( prop - > menu = = menu )
continue ;
if ( prop - > type = = P_PROMPT & &
prop - > menu - > parent - > sym ! = sym )
prop_warn ( prop , " choice value used outside its choice group " ) ;
2005-04-17 02:20:36 +04:00
}
2008-01-24 14:54:23 +03:00
/* Non-tristate choice values of tristate choices must
* depend on the choice being set to Y . The choice
* values ' dependencies were propagated to their
* properties above , so the change here must be re -
2008-02-29 07:11:50 +03:00
* propagated .
*/
2008-01-24 14:54:23 +03:00
if ( sym - > type = = S_TRISTATE & & menu - > sym - > type ! = S_TRISTATE ) {
basedep = expr_alloc_comp ( E_EQUAL , sym , & symbol_yes ) ;
2008-02-29 07:11:50 +03:00
menu - > dep = expr_alloc_and ( basedep , menu - > dep ) ;
2008-01-24 14:54:23 +03:00
for ( prop = menu - > sym - > prop ; prop ; prop = prop - > next ) {
if ( prop - > menu ! = menu )
continue ;
2008-02-29 07:11:50 +03:00
prop - > visible . expr = expr_alloc_and ( expr_copy ( basedep ) ,
prop - > visible . expr ) ;
2008-01-24 14:54:23 +03:00
}
}
2005-04-17 02:20:36 +04:00
menu_add_symbol ( P_CHOICE , sym , NULL ) ;
prop = sym_get_choice_prop ( sym ) ;
for ( ep = & prop - > expr ; * ep ; ep = & ( * ep ) - > left . expr )
;
2008-01-14 06:50:23 +03:00
* ep = expr_alloc_one ( E_LIST , NULL ) ;
2005-04-17 02:20:36 +04:00
( * ep ) - > right . sym = menu - > sym ;
}
if ( menu - > list & & ( ! menu - > prompt | | ! menu - > prompt - > text ) ) {
for ( last_menu = menu - > list ; ; last_menu = last_menu - > next ) {
last_menu - > parent = parent ;
if ( ! last_menu - > next )
break ;
}
last_menu - > next = menu - > next ;
menu - > next = menu - > list ;
menu - > list = NULL ;
}
}
if ( sym & & ! ( sym - > flags & SYMBOL_WARNED ) ) {
if ( sym - > type = = S_UNKNOWN )
2006-06-09 09:12:48 +04:00
menu_warn ( parent , " config symbol defined without type " ) ;
2005-04-17 02:20:36 +04:00
if ( sym_is_choice ( sym ) & & ! parent - > prompt )
2006-06-09 09:12:48 +04:00
menu_warn ( parent , " choice must have a prompt " ) ;
2005-04-17 02:20:36 +04:00
/* Check properties connected to this symbol */
sym_check_prop ( sym ) ;
sym - > flags | = SYMBOL_WARNED ;
}
if ( sym & & ! sym_is_optional ( sym ) & & parent - > prompt ) {
sym - > rev_dep . expr = expr_alloc_or ( sym - > rev_dep . expr ,
expr_alloc_and ( parent - > prompt - > visible . expr ,
expr_alloc_symbol ( & symbol_mod ) ) ) ;
}
}
menuconfig: add support to show hidden options which have prompts
Usage:
Press <Z> to show all config symbols which have prompts.
Quote Tim Bird:
| I've been bitten by this numerous times. I most often
| use ftrace on ARM, but when I go back to x86, I almost
| always go through a sequence of searching for the
| function graph tracer in the menus, then realizing it's
| completely missing until I disable CC_OPTIMIZE_FOR_SIZE.
|
| Is there any way to have the menu item appear, but be
| unsettable unless the SIZE option is disabled? I'm
| not a Kconfig guru...
I myself found this useful too. For example, I need to test
ftrace/tracing and want to be sure all the tracing features are
enabled, so I enter the "Tracers" menu, and press <Z> to
see if there is any config hidden.
I also noticed gconfig and xconfig have a button "Show all options",
but that's a bit too much, and I think normally what we are not
interested in those configs which have no prompt thus can't be
changed by users.
Exmaple:
--- Tracers
-*- Kernel Function Tracer
- - Kernel Function Graph Tracer
[*] Interrupts-off Latency Tracer
- - Preemption-off Latency Tracer
[*] Sysprof Tracer
Here you can see 2 tracers are not selectable, and then can find
out how to make them selectable.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: Michal Marek <mmarek@suse.cz>
2010-04-14 07:46:02 +04:00
bool menu_has_prompt ( struct menu * menu )
{
if ( ! menu - > prompt )
return false ;
return true ;
}
2013-05-19 23:49:34 +04:00
/*
* Determine if a menu is empty .
* A menu is considered empty if it contains no or only
* invisible entries .
*/
bool menu_is_empty ( struct menu * menu )
{
struct menu * child ;
for ( child = menu - > list ; child ; child = child - > next ) {
if ( menu_is_visible ( child ) )
return ( false ) ;
}
return ( true ) ;
}
2005-04-17 02:20:36 +04:00
bool menu_is_visible ( struct menu * menu )
{
struct menu * child ;
struct symbol * sym ;
tristate visible ;
if ( ! menu - > prompt )
return false ;
menuconfig: add support to show hidden options which have prompts
Usage:
Press <Z> to show all config symbols which have prompts.
Quote Tim Bird:
| I've been bitten by this numerous times. I most often
| use ftrace on ARM, but when I go back to x86, I almost
| always go through a sequence of searching for the
| function graph tracer in the menus, then realizing it's
| completely missing until I disable CC_OPTIMIZE_FOR_SIZE.
|
| Is there any way to have the menu item appear, but be
| unsettable unless the SIZE option is disabled? I'm
| not a Kconfig guru...
I myself found this useful too. For example, I need to test
ftrace/tracing and want to be sure all the tracing features are
enabled, so I enter the "Tracers" menu, and press <Z> to
see if there is any config hidden.
I also noticed gconfig and xconfig have a button "Show all options",
but that's a bit too much, and I think normally what we are not
interested in those configs which have no prompt thus can't be
changed by users.
Exmaple:
--- Tracers
-*- Kernel Function Tracer
- - Kernel Function Graph Tracer
[*] Interrupts-off Latency Tracer
- - Preemption-off Latency Tracer
[*] Sysprof Tracer
Here you can see 2 tracers are not selectable, and then can find
out how to make them selectable.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: Michal Marek <mmarek@suse.cz>
2010-04-14 07:46:02 +04:00
2010-11-07 00:30:23 +03:00
if ( menu - > visibility ) {
if ( expr_calc_value ( menu - > visibility ) = = no )
return no ;
}
2005-04-17 02:20:36 +04:00
sym = menu - > sym ;
if ( sym ) {
sym_calc_value ( sym ) ;
visible = menu - > prompt - > visible . tri ;
} else
visible = menu - > prompt - > visible . tri = expr_calc_value ( menu - > prompt - > visible . expr ) ;
if ( visible ! = no )
return true ;
menuconfig: add support to show hidden options which have prompts
Usage:
Press <Z> to show all config symbols which have prompts.
Quote Tim Bird:
| I've been bitten by this numerous times. I most often
| use ftrace on ARM, but when I go back to x86, I almost
| always go through a sequence of searching for the
| function graph tracer in the menus, then realizing it's
| completely missing until I disable CC_OPTIMIZE_FOR_SIZE.
|
| Is there any way to have the menu item appear, but be
| unsettable unless the SIZE option is disabled? I'm
| not a Kconfig guru...
I myself found this useful too. For example, I need to test
ftrace/tracing and want to be sure all the tracing features are
enabled, so I enter the "Tracers" menu, and press <Z> to
see if there is any config hidden.
I also noticed gconfig and xconfig have a button "Show all options",
but that's a bit too much, and I think normally what we are not
interested in those configs which have no prompt thus can't be
changed by users.
Exmaple:
--- Tracers
-*- Kernel Function Tracer
- - Kernel Function Graph Tracer
[*] Interrupts-off Latency Tracer
- - Preemption-off Latency Tracer
[*] Sysprof Tracer
Here you can see 2 tracers are not selectable, and then can find
out how to make them selectable.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: Michal Marek <mmarek@suse.cz>
2010-04-14 07:46:02 +04:00
2005-04-17 02:20:36 +04:00
if ( ! sym | | sym_get_tristate_value ( menu - > sym ) = = no )
return false ;
2010-05-07 09:57:07 +04:00
for ( child = menu - > list ; child ; child = child - > next ) {
if ( menu_is_visible ( child ) ) {
if ( sym )
sym - > flags | = SYMBOL_DEF_USER ;
2005-04-17 02:20:36 +04:00
return true ;
2010-05-07 09:57:07 +04:00
}
}
menuconfig: add support to show hidden options which have prompts
Usage:
Press <Z> to show all config symbols which have prompts.
Quote Tim Bird:
| I've been bitten by this numerous times. I most often
| use ftrace on ARM, but when I go back to x86, I almost
| always go through a sequence of searching for the
| function graph tracer in the menus, then realizing it's
| completely missing until I disable CC_OPTIMIZE_FOR_SIZE.
|
| Is there any way to have the menu item appear, but be
| unsettable unless the SIZE option is disabled? I'm
| not a Kconfig guru...
I myself found this useful too. For example, I need to test
ftrace/tracing and want to be sure all the tracing features are
enabled, so I enter the "Tracers" menu, and press <Z> to
see if there is any config hidden.
I also noticed gconfig and xconfig have a button "Show all options",
but that's a bit too much, and I think normally what we are not
interested in those configs which have no prompt thus can't be
changed by users.
Exmaple:
--- Tracers
-*- Kernel Function Tracer
- - Kernel Function Graph Tracer
[*] Interrupts-off Latency Tracer
- - Preemption-off Latency Tracer
[*] Sysprof Tracer
Here you can see 2 tracers are not selectable, and then can find
out how to make them selectable.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Signed-off-by: Michal Marek <mmarek@suse.cz>
2010-04-14 07:46:02 +04:00
2005-04-17 02:20:36 +04:00
return false ;
}
const char * menu_get_prompt ( struct menu * menu )
{
if ( menu - > prompt )
2008-01-12 01:53:43 +03:00
return menu - > prompt - > text ;
2005-04-17 02:20:36 +04:00
else if ( menu - > sym )
2008-01-12 01:53:43 +03:00
return menu - > sym - > name ;
2005-04-17 02:20:36 +04:00
return NULL ;
}
struct menu * menu_get_root_menu ( struct menu * menu )
{
return & rootmenu ;
}
struct menu * menu_get_parent_menu ( struct menu * menu )
{
enum prop_type type ;
for ( ; menu ! = & rootmenu ; menu = menu - > parent ) {
type = menu - > prompt ? menu - > prompt - > type : 0 ;
if ( type = = P_MENU )
break ;
}
return menu ;
}
2007-07-21 02:00:36 +04:00
bool menu_has_help ( struct menu * menu )
{
return menu - > help ! = NULL ;
}
const char * menu_get_help ( struct menu * menu )
{
if ( menu - > help )
return menu - > help ;
else
return " " ;
}
2009-07-12 12:11:44 +04:00
2012-08-23 22:55:08 +04:00
static void get_prompt_str ( struct gstr * r , struct property * prop ,
2012-10-21 13:27:53 +04:00
struct list_head * head )
2009-07-12 12:11:44 +04:00
{
int i , j ;
2012-08-23 22:55:06 +04:00
struct menu * submenu [ 8 ] , * menu , * location = NULL ;
2012-08-23 22:55:08 +04:00
struct jump_key * jump ;
2009-07-12 12:11:44 +04:00
str_printf ( r , _ ( " Prompt: %s \n " ) , _ ( prop - > text ) ) ;
menu = prop - > menu - > parent ;
2012-08-23 22:55:06 +04:00
for ( i = 0 ; menu ! = & rootmenu & & i < 8 ; menu = menu - > parent ) {
bool accessible = menu_is_visible ( menu ) ;
2009-07-12 12:11:44 +04:00
submenu [ i + + ] = menu ;
2012-08-23 22:55:06 +04:00
if ( location = = NULL & & accessible )
location = menu ;
}
2012-08-23 22:55:08 +04:00
if ( head & & location ) {
2012-11-06 18:32:08 +04:00
jump = xmalloc ( sizeof ( struct jump_key ) ) ;
2012-08-23 22:55:08 +04:00
2012-08-23 22:55:06 +04:00
if ( menu_is_visible ( prop - > menu ) ) {
/*
* There is not enough room to put the hint at the
* beginning of the " Prompt " line . Put the hint on the
* last " Location " line even when it would belong on
* the former .
*/
2012-08-23 22:55:08 +04:00
jump - > target = prop - > menu ;
2012-08-23 22:55:06 +04:00
} else
2012-08-23 22:55:08 +04:00
jump - > target = location ;
2012-10-21 13:27:53 +04:00
if ( list_empty ( head ) )
2012-08-23 22:55:08 +04:00
jump - > index = 0 ;
else
2012-10-21 13:27:53 +04:00
jump - > index = list_entry ( head - > prev , struct jump_key ,
entries ) - > index + 1 ;
2012-08-23 22:55:08 +04:00
2012-10-21 13:27:53 +04:00
list_add_tail ( & jump - > entries , head ) ;
2012-08-23 22:55:08 +04:00
}
2012-08-23 22:55:06 +04:00
2009-07-12 12:11:44 +04:00
if ( i > 0 ) {
str_printf ( r , _ ( " Location: \n " ) ) ;
2012-08-23 22:55:08 +04:00
for ( j = 4 ; - - i > = 0 ; j + = 2 ) {
2009-07-12 12:11:44 +04:00
menu = submenu [ i ] ;
2012-08-23 22:55:08 +04:00
if ( head & & location & & menu = = location )
2013-10-03 20:35:16 +04:00
jump - > offset = strlen ( r - > s ) ;
2012-08-23 22:55:08 +04:00
str_printf ( r , " %*c-> %s " , j , ' ' ,
_ ( menu_get_prompt ( menu ) ) ) ;
2009-07-12 12:11:44 +04:00
if ( menu - > sym ) {
str_printf ( r , " (%s [=%s]) " , menu - > sym - > name ?
menu - > sym - > name : _ ( " <choice> " ) ,
sym_get_string_value ( menu - > sym ) ) ;
}
str_append ( r , " \n " ) ;
}
}
}
2013-05-01 02:28:46 +04:00
/*
2013-10-03 19:28:14 +04:00
* get property of type P_SYMBOL
2013-05-01 02:28:46 +04:00
*/
static struct property * get_symbol_prop ( struct symbol * sym )
{
struct property * prop = NULL ;
for_all_properties ( sym , prop , P_SYMBOL )
break ;
return prop ;
}
2012-08-23 22:55:06 +04:00
/*
2012-08-23 22:55:08 +04:00
* head is optional and may be NULL
2012-08-23 22:55:06 +04:00
*/
2012-10-21 13:27:53 +04:00
void get_symbol_str ( struct gstr * r , struct symbol * sym ,
struct list_head * head )
2009-07-12 12:11:44 +04:00
{
bool hit ;
struct property * prop ;
2010-05-07 09:56:33 +04:00
if ( sym & & sym - > name ) {
2009-07-12 12:11:44 +04:00
str_printf ( r , " Symbol: %s [=%s] \n " , sym - > name ,
sym_get_string_value ( sym ) ) ;
2010-05-07 09:56:33 +04:00
str_printf ( r , " Type : %s \n " , sym_type_name ( sym - > type ) ) ;
2010-05-07 09:56:50 +04:00
if ( sym - > type = = S_INT | | sym - > type = = S_HEX ) {
prop = sym_get_range_prop ( sym ) ;
if ( prop ) {
str_printf ( r , " Range : " ) ;
expr_gstr_print ( prop - > expr , r ) ;
str_append ( r , " \n " ) ;
}
}
2010-05-07 09:56:33 +04:00
}
2009-07-12 12:11:44 +04:00
for_all_prompts ( sym , prop )
2012-08-23 22:55:08 +04:00
get_prompt_str ( r , prop , head ) ;
2013-05-07 17:56:54 +04:00
2013-05-01 02:28:46 +04:00
prop = get_symbol_prop ( sym ) ;
2013-05-07 17:56:54 +04:00
if ( prop ) {
str_printf ( r , _ ( " Defined at %s:%d \n " ) , prop - > menu - > file - > name ,
prop - > menu - > lineno ) ;
if ( ! expr_is_yes ( prop - > visible . expr ) ) {
str_append ( r , _ ( " Depends on: " ) ) ;
expr_gstr_print ( prop - > visible . expr , r ) ;
str_append ( r , " \n " ) ;
}
2013-05-01 02:28:46 +04:00
}
2013-05-07 17:56:54 +04:00
2009-07-12 12:11:44 +04:00
hit = false ;
for_all_properties ( sym , prop , P_SELECT ) {
if ( ! hit ) {
str_append ( r , " Selects: " ) ;
hit = true ;
} else
str_printf ( r , " && " ) ;
expr_gstr_print ( prop - > expr , r ) ;
}
if ( hit )
str_append ( r , " \n " ) ;
if ( sym - > rev_dep . expr ) {
str_append ( r , _ ( " Selected by: " ) ) ;
expr_gstr_print ( sym - > rev_dep . expr , r ) ;
str_append ( r , " \n " ) ;
}
str_append ( r , " \n \n " ) ;
}
2012-10-21 13:27:53 +04:00
struct gstr get_relations_str ( struct symbol * * sym_arr , struct list_head * head )
2009-11-25 13:28:43 +03:00
{
struct symbol * sym ;
struct gstr res = str_new ( ) ;
2012-08-23 22:55:08 +04:00
int i ;
2009-11-25 13:28:43 +03:00
for ( i = 0 ; sym_arr & & ( sym = sym_arr [ i ] ) ; i + + )
2012-08-23 22:55:08 +04:00
get_symbol_str ( & res , sym , head ) ;
2009-11-25 13:28:43 +03:00
if ( ! i )
str_append ( & res , _ ( " No matches found. \n " ) ) ;
return res ;
}
2009-07-12 12:11:44 +04:00
void menu_get_ext_help ( struct menu * menu , struct gstr * help )
{
struct symbol * sym = menu - > sym ;
2011-08-04 05:52:07 +04:00
const char * help_text = nohelp_text ;
2009-07-12 12:11:44 +04:00
if ( menu_has_help ( menu ) ) {
2011-08-02 21:49:52 +04:00
if ( sym - > name )
2010-08-15 07:57:43 +04:00
str_printf ( help , " %s%s: \n \n " , CONFIG_ , sym - > name ) ;
2011-08-04 05:52:07 +04:00
help_text = menu_get_help ( menu ) ;
2009-07-12 12:11:44 +04:00
}
2011-08-04 05:52:07 +04:00
str_printf ( help , " %s \n " , _ ( help_text ) ) ;
2009-07-12 12:11:46 +04:00
if ( sym )
2012-08-23 22:55:08 +04:00
get_symbol_str ( help , sym , NULL ) ;
2009-07-12 12:11:44 +04:00
}