diff options
Diffstat (limited to 'scripts/kconfig')
| -rw-r--r-- | scripts/kconfig/Makefile | 16 | ||||
| -rw-r--r-- | scripts/kconfig/expr.c | 27 | ||||
| -rw-r--r-- | scripts/kconfig/expr.h | 5 | ||||
| -rw-r--r-- | scripts/kconfig/gconf.c | 113 | ||||
| -rw-r--r-- | scripts/kconfig/gconf.glade | 26 | ||||
| -rw-r--r-- | scripts/kconfig/lkc.h | 7 | ||||
| -rw-r--r-- | scripts/kconfig/lkc_proto.h | 6 | ||||
| -rw-r--r-- | scripts/kconfig/lxdialog/inputbox.c | 4 | ||||
| -rw-r--r-- | scripts/kconfig/lxdialog/menubox.c | 22 | ||||
| -rw-r--r-- | scripts/kconfig/mconf.c | 34 | ||||
| -rw-r--r-- | scripts/kconfig/menu.c | 28 | ||||
| -rw-r--r-- | scripts/kconfig/nconf.c | 1568 | ||||
| -rw-r--r-- | scripts/kconfig/nconf.gui.c | 617 | ||||
| -rw-r--r-- | scripts/kconfig/nconf.h | 95 | ||||
| -rw-r--r-- | scripts/kconfig/symbol.c | 30 | ||||
| -rw-r--r-- | scripts/kconfig/util.c | 2 | ||||
| -rw-r--r-- | scripts/kconfig/zconf.tab.c_shipped | 25 | ||||
| -rw-r--r-- | scripts/kconfig/zconf.y | 25 | 
18 files changed, 2503 insertions, 147 deletions
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 186c46604d0..7cdae39b8f0 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -23,6 +23,9 @@ menuconfig: $(obj)/mconf  config: $(obj)/conf  	$< $(Kconfig) +nconfig: $(obj)/nconf +	$< $(Kconfig) +  oldconfig: $(obj)/conf  	$< -o $(Kconfig) @@ -120,6 +123,7 @@ endif  # Help text used by make help  help:  	@echo  '  config	  - Update current config utilising a line-oriented program' +	@echo  '  nconfig         - Update current config utilising a ncurses menu based program'  	@echo  '  menuconfig	  - Update current config utilising a menu based program'  	@echo  '  xconfig	  - Update current config utilising a QT based front-end'  	@echo  '  gconfig	  - Update current config utilising a GTK based front-end' @@ -147,6 +151,8 @@ HOST_EXTRACFLAGS += -DLOCALE  # ===========================================================================  # Shared Makefile for the various kconfig executables:  # conf:	  Used for defconfig, oldconfig and related targets +# nconf:  Used for the nconfig target. +#         Utilizes ncurses  # mconf:  Used for the menuconfig target  #         Utilizes the lxdialog package  # qconf:  Used for the xconfig target @@ -159,11 +165,16 @@ lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o  lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o  conf-objs	:= conf.o  zconf.tab.o -mconf-objs	:= mconf.o zconf.tab.o $(lxdialog) +mconf-objs     := mconf.o zconf.tab.o $(lxdialog) +nconf-objs     := nconf.o zconf.tab.o nconf.gui.o  kxgettext-objs	:= kxgettext.o zconf.tab.o  hostprogs-y := conf qconf gconf kxgettext +ifeq ($(MAKECMDGOALS),nconfig) +	hostprogs-y += nconf +endif +  ifeq ($(MAKECMDGOALS),menuconfig)  	hostprogs-y += mconf  endif @@ -187,7 +198,7 @@ endif  clean-files	:= lkc_defs.h qconf.moc .tmp_qtcheck \  		   .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c gconf.glade.h -clean-files     += mconf qconf gconf +clean-files     += mconf qconf gconf nconf  clean-files     += config.pot linux.pot  # Check that we have the required ncurses stuff installed for lxdialog (menuconfig) @@ -212,6 +223,7 @@ HOSTLOADLIBES_gconf	= `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0`  HOSTCFLAGS_gconf.o	= `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \                            -D LKC_DIRECT_LINK +HOSTLOADLIBES_nconf	= -lmenu -lpanel -lncurses  $(obj)/qconf.o: $(obj)/.tmp_qtcheck  ifeq ($(qconf-target),1) diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c index edd3f39a080..d83f2322893 100644 --- a/scripts/kconfig/expr.c +++ b/scripts/kconfig/expr.c @@ -1097,9 +1097,32 @@ void expr_fprint(struct expr *e, FILE *out)  static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)  { -	str_append((struct gstr*)data, str); +	struct gstr *gs = (struct gstr*)data; +	const char *sym_str = NULL; + +	if (sym) +		sym_str = sym_get_string_value(sym); + +	if (gs->max_width) { +		unsigned extra_length = strlen(str); +		const char *last_cr = strrchr(gs->s, '\n'); +		unsigned last_line_length; + +		if (sym_str) +			extra_length += 4 + strlen(sym_str); + +		if (!last_cr) +			last_cr = gs->s; + +		last_line_length = strlen(gs->s) - (last_cr - gs->s); + +		if ((last_line_length + extra_length) > gs->max_width) +			str_append(gs, "\\\n"); +	} + +	str_append(gs, str);  	if (sym) -		str_printf((struct gstr*)data, " [=%s]", sym_get_string_value(sym)); +		str_printf(gs, " [=%s]", sym_str);  }  void expr_gstr_print(struct expr *e, struct gstr *gs) diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h index 6408fefae08..891cd9ce9ba 100644 --- a/scripts/kconfig/expr.h +++ b/scripts/kconfig/expr.h @@ -86,7 +86,7 @@ struct symbol {  	struct expr_value rev_dep;  }; -#define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) +#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)  #define SYMBOL_CONST      0x0001  /* symbol is const */  #define SYMBOL_CHECK      0x0008  /* used during dependency checking */ @@ -108,8 +108,7 @@ struct symbol {  #define SYMBOL_DEF4       0x80000  /* symbol.def[S_DEF_4] is valid */  #define SYMBOL_MAXLENGTH	256 -#define SYMBOL_HASHSIZE		257 -#define SYMBOL_HASHMASK		0xff +#define SYMBOL_HASHSIZE		9973  /* A property represent the config options that can be associated   * with a config "symbol". diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c index 65464366fe3..bef10411837 100644 --- a/scripts/kconfig/gconf.c +++ b/scripts/kconfig/gconf.c @@ -30,13 +30,16 @@ enum {  	SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW  }; +enum { +	OPT_NORMAL, OPT_ALL, OPT_PROMPT +}; +  static gint view_mode = FULL_VIEW;  static gboolean show_name = TRUE;  static gboolean show_range = TRUE;  static gboolean show_value = TRUE; -static gboolean show_all = FALSE; -static gboolean show_debug = FALSE;  static gboolean resizeable = FALSE; +static int opt_mode = OPT_NORMAL;  GtkWidget *main_wnd = NULL;  GtkWidget *tree1_w = NULL;	// left  frame @@ -76,36 +79,7 @@ static void conf_changed(void);  /* Helping/Debugging Functions */ - -const char *dbg_print_stype(int val) -{ -	static char buf[256]; - -	bzero(buf, 256); - -	if (val == S_UNKNOWN) -		strcpy(buf, "unknown"); -	if (val == S_BOOLEAN) -		strcpy(buf, "boolean"); -	if (val == S_TRISTATE) -		strcpy(buf, "tristate"); -	if (val == S_INT) -		strcpy(buf, "int"); -	if (val == S_HEX) -		strcpy(buf, "hex"); -	if (val == S_STRING) -		strcpy(buf, "string"); -	if (val == S_OTHER) -		strcpy(buf, "other"); - -#ifdef DEBUG -	printf("%s", buf); -#endif - -	return buf; -} - -const char *dbg_print_flags(int val) +const char *dbg_sym_flags(int val)  {  	static char buf[256]; @@ -131,40 +105,10 @@ const char *dbg_print_flags(int val)  		strcat(buf, "auto/");  	buf[strlen(buf) - 1] = '\0'; -#ifdef DEBUG -	printf("%s", buf); -#endif - -	return buf; -} - -const char *dbg_print_ptype(int val) -{ -	static char buf[256]; - -	bzero(buf, 256); - -	if (val == P_UNKNOWN) -		strcpy(buf, "unknown"); -	if (val == P_PROMPT) -		strcpy(buf, "prompt"); -	if (val == P_COMMENT) -		strcpy(buf, "comment"); -	if (val == P_MENU) -		strcpy(buf, "menu"); -	if (val == P_DEFAULT) -		strcpy(buf, "default"); -	if (val == P_CHOICE) -		strcpy(buf, "choice"); - -#ifdef DEBUG -	printf("%s", buf); -#endif  	return buf;  } -  void replace_button_icon(GladeXML * xml, GdkDrawable * window,  			 GtkStyle * style, gchar * btn_name, gchar ** xpm)  { @@ -697,20 +641,29 @@ void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data)  void -on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data) +on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data)  { -	show_all = GTK_CHECK_MENU_ITEM(menuitem)->active; +	opt_mode = OPT_NORMAL; +	gtk_tree_store_clear(tree2); +	display_tree(&rootmenu);	/* instead of update_tree to speed-up */ +} + +void +on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data) +{ +	opt_mode = OPT_ALL;  	gtk_tree_store_clear(tree2); -	display_tree(&rootmenu);	// instead of update_tree to speed-up +	display_tree(&rootmenu);	/* instead of update_tree to speed-up */  }  void -on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data) +on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)  { -	show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active; -	update_tree(&rootmenu, NULL); +	opt_mode = OPT_PROMPT; +	gtk_tree_store_clear(tree2); +	display_tree(&rootmenu);	/* instead of update_tree to speed-up */  } @@ -1163,7 +1116,10 @@ static gchar **fill_row(struct menu *menu)  	    g_strdup_printf("%s %s", _(menu_get_prompt(menu)),  			    sym && sym_has_value(sym) ? "(NEW)" : ""); -	if (show_all && !menu_is_visible(menu)) +	if (opt_mode == OPT_ALL && !menu_is_visible(menu)) +		row[COL_COLOR] = g_strdup("DarkGray"); +	else if (opt_mode == OPT_PROMPT && +			menu_has_prompt(menu) && !menu_is_visible(menu))  		row[COL_COLOR] = g_strdup("DarkGray");  	else  		row[COL_COLOR] = g_strdup("Black"); @@ -1386,16 +1342,19 @@ static void update_tree(struct menu *src, GtkTreeIter * dst)  		       menu2 ? menu_get_prompt(menu2) : "nil");  #endif -		if (!menu_is_visible(child1) && !show_all) {	// remove node +		if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) || +		    (opt_mode == OPT_PROMPT && !menu_has_prompt(child1))) { + +			/* remove node */  			if (gtktree_iter_find_node(dst, menu1) != NULL) {  				memcpy(&tmp, child2, sizeof(GtkTreeIter));  				valid = gtk_tree_model_iter_next(model2,  								 child2);  				gtk_tree_store_remove(tree2, &tmp);  				if (!valid) -					return;	// next parent +					return;		/* next parent */  				else -					goto reparse;	// next child +					goto reparse;	/* next child */  			} else  				continue;  		} @@ -1464,17 +1423,19 @@ static void display_tree(struct menu *menu)  		    && (tree == tree2))  			continue; -		if (menu_is_visible(child) || show_all) +		if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) || +		    (opt_mode == OPT_PROMPT && menu_has_prompt(child)) || +		    (opt_mode == OPT_ALL))  			place_node(child, fill_row(child));  #ifdef DEBUG  		printf("%*c%s: ", indent, ' ', menu_get_prompt(child));  		printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : ""); -		dbg_print_ptype(ptype); +		printf("%s", prop_get_type_name(ptype));  		printf(" | ");  		if (sym) { -			dbg_print_stype(sym->type); +			printf("%s", sym_type_name(sym->type));  			printf(" | "); -			dbg_print_flags(sym->flags); +			printf("%s", dbg_sym_flags(sym->flags));  			printf("\n");  		} else  			printf("\n"); diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade index b1c86c19292..d52b0a75d82 100644 --- a/scripts/kconfig/gconf.glade +++ b/scripts/kconfig/gconf.glade @@ -190,26 +190,40 @@  		  </child>  		  <child> -		    <widget class="GtkCheckMenuItem" id="show_all_options1"> +		    <widget class="GtkRadioMenuItem" id="set_option_mode1"> +		      <property name="visible">True</property> +		      <property name="tooltip" translatable="yes">Show normal options</property> +		      <property name="label" translatable="yes">Show normal options</property> +		      <property name="use_underline">True</property> +		      <property name="active">True</property> +		      <signal name="activate" handler="on_set_option_mode1_activate"/> +		    </widget> +		  </child> + +		  <child> +		    <widget class="GtkRadioMenuItem" id="set_option_mode2">  		      <property name="visible">True</property>  		      <property name="tooltip" translatable="yes">Show all options</property>  		      <property name="label" translatable="yes">Show all _options</property>  		      <property name="use_underline">True</property>  		      <property name="active">False</property> -		      <signal name="activate" handler="on_show_all_options1_activate"/> +		      <property name="group">set_option_mode1</property> +		      <signal name="activate" handler="on_set_option_mode2_activate"/>  		    </widget>  		  </child>  		  <child> -		    <widget class="GtkCheckMenuItem" id="show_debug_info1"> +		    <widget class="GtkRadioMenuItem" id="set_option_mode3">  		      <property name="visible">True</property> -		      <property name="tooltip" translatable="yes">Show masked options</property> -		      <property name="label" translatable="yes">Show _debug info</property> +		      <property name="tooltip" translatable="yes">Show all options with prompts</property> +		      <property name="label" translatable="yes">Show all prompt options</property>  		      <property name="use_underline">True</property>  		      <property name="active">False</property> -		      <signal name="activate" handler="on_show_debug_info1_activate"/> +		      <property name="group">set_option_mode1</property> +		      <signal name="activate" handler="on_set_option_mode3_activate"/>  		    </widget>  		  </child> +  		</widget>  	      </child>  	    </widget> diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index f379b0bf8c9..ce6549cdacc 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -84,7 +84,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode);  void kconfig_load(void);  /* menu.c */ -void menu_init(void); +void _menu_init(void);  void menu_warn(struct menu *menu, const char *fmt, ...);  struct menu *menu_add_menu(void);  void menu_end_menu(void); @@ -106,6 +106,11 @@ int file_write_dep(const char *name);  struct gstr {  	size_t len;  	char  *s; +	/* +	* when max_width is not zero long lines in string s (if any) get +	* wrapped not to exceed the max_width value +	*/ +	int max_width;  };  struct gstr str_new(void);  struct gstr str_assign(const char *s); diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index ffeb532b2cf..7cadcad8233 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h @@ -11,13 +11,15 @@ P(conf_set_changed_callback, void,(void (*fn)(void)));  /* menu.c */  P(rootmenu,struct menu,); -P(menu_is_visible,bool,(struct menu *menu)); +P(menu_is_visible, bool, (struct menu *menu)); +P(menu_has_prompt, bool, (struct menu *menu));  P(menu_get_prompt,const char *,(struct menu *menu));  P(menu_get_root_menu,struct menu *,(struct menu *menu));  P(menu_get_parent_menu,struct menu *,(struct menu *menu));  P(menu_has_help,bool,(struct menu *menu));  P(menu_get_help,const char *,(struct menu *menu)); -P(get_symbol_str,void,(struct gstr *r, struct symbol *sym)); +P(get_symbol_str, void, (struct gstr *r, struct symbol *sym)); +P(get_relations_str, struct gstr, (struct symbol **sym_arr));  P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));  /* symbol.c */ diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c index 616c6013818..dd8e587c50e 100644 --- a/scripts/kconfig/lxdialog/inputbox.c +++ b/scripts/kconfig/lxdialog/inputbox.c @@ -180,7 +180,7 @@ do_resize:  		case KEY_LEFT:  			switch (button) {  			case -1: -				button = 1;	/* Indicates "Cancel" button is selected */ +				button = 1;	/* Indicates "Help" button is selected */  				print_buttons(dialog, height, width, 1);  				break;  			case 0: @@ -204,7 +204,7 @@ do_resize:  				print_buttons(dialog, height, width, 0);  				break;  			case 0: -				button = 1;	/* Indicates "Cancel" button is selected */ +				button = 1;	/* Indicates "Help" button is selected */  				print_buttons(dialog, height, width, 1);  				break;  			case 1: diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c index fa9d633f293..1d604738fa1 100644 --- a/scripts/kconfig/lxdialog/menubox.c +++ b/scripts/kconfig/lxdialog/menubox.c @@ -383,6 +383,10 @@ do_resize:  		case 'n':  		case 'm':  		case '/': +		case 'h': +		case '?': +		case 'z': +		case '\n':  			/* save scroll info */  			*s_scroll = scroll;  			delwin(menu); @@ -390,8 +394,10 @@ do_resize:  			item_set(scroll + choice);  			item_set_selected(1);  			switch (key) { +			case 'h': +			case '?': +				return 2;  			case 's': -				return 3;  			case 'y':  				return 3;  			case 'n': @@ -402,18 +408,12 @@ do_resize:  				return 6;  			case '/':  				return 7; +			case 'z': +				return 8; +			case '\n': +				return button;  			}  			return 0; -		case 'h': -		case '?': -			button = 2; -		case '\n': -			*s_scroll = scroll; -			delwin(menu); -			delwin(dialog); -			item_set(scroll + choice); -			item_set_selected(1); -			return button;  		case 'e':  		case 'x':  			key = KEY_ESC; diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 8413cf38ed2..2c83d3234d3 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -67,13 +67,15 @@ static const char mconf_readme[] = N_(  "             there is a delayed response which you may find annoying.\n"  "\n"  "   Also, the <TAB> and cursor keys will cycle between <Select>,\n" -"   <Exit> and <Help>\n" +"   <Exit> and <Help>.\n"  "\n"  "o  To get help with an item, use the cursor keys to highlight <Help>\n" -"   and Press <ENTER>.\n" +"   and press <ENTER>.\n"  "\n"  "   Shortcut: Press <H> or <?>.\n"  "\n" +"o  To show hidden options, press <Z>.\n" +"\n"  "\n"  "Radiolists  (Choice lists)\n"  "-----------\n" @@ -272,6 +274,7 @@ static int indent;  static struct menu *current_menu;  static int child_count;  static int single_menu_mode; +static int show_all_options;  static void conf(struct menu *menu);  static void conf_choice(struct menu *menu); @@ -282,19 +285,6 @@ static void show_textbox(const char *title, const char *text, int r, int c);  static void show_helptext(const char *title, const char *text);  static void show_help(struct menu *menu); -static struct gstr get_relations_str(struct symbol **sym_arr) -{ -	struct symbol *sym; -	struct gstr res = str_new(); -	int i; - -	for (i = 0; sym_arr && (sym = sym_arr[i]); i++) -		get_symbol_str(&res, sym); -	if (!i) -		str_append(&res, _("No matches found.\n")); -	return res; -} -  static char filename[PATH_MAX+1];  static void set_config_filename(const char *config_filename)  { @@ -359,8 +349,16 @@ static void build_conf(struct menu *menu)  	int type, tmp, doint = 2;  	tristate val;  	char ch; +	bool visible; -	if (!menu_is_visible(menu)) +	/* +	 * note: menu_is_visible() has side effect that it will +	 * recalc the value of the symbol. +	 */ +	visible = menu_is_visible(menu); +	if (show_all_options && !menu_has_prompt(menu)) +		return; +	else if (!show_all_options && !visible)  		return;  	sym = menu->sym; @@ -619,6 +617,9 @@ static void conf(struct menu *menu)  		case 7:  			search_conf();  			break; +		case 8: +			show_all_options = !show_all_options; +			break;  		}  	}  } @@ -638,6 +639,7 @@ static void show_help(struct menu *menu)  {  	struct gstr help = str_new(); +	help.max_width = getmaxx(stdscr) - 10;  	menu_get_ext_help(menu, &help);  	show_helptext(_(menu_get_prompt(menu)), str_get(&help)); diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index 059a2465c57..203632cc30b 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -38,7 +38,7 @@ static void prop_warn(struct property *prop, const char *fmt, ...)  	va_end(ap);  } -void menu_init(void) +void _menu_init(void)  {  	current_entry = current_menu = &rootmenu;  	last_entry_ptr = &rootmenu.list; @@ -197,7 +197,7 @@ static void sym_check_prop(struct symbol *sym)  			if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&  			    prop->expr->type != E_SYMBOL)  				prop_warn(prop, -				    "default for config symbol '%'" +				    "default for config symbol '%s'"  				    " must be a single symbol", sym->name);  			break;  		case P_SELECT: @@ -390,6 +390,13 @@ void menu_finalize(struct menu *parent)  	}  } +bool menu_has_prompt(struct menu *menu) +{ +	if (!menu->prompt) +		return false; +	return true; +} +  bool menu_is_visible(struct menu *menu)  {  	struct menu *child; @@ -398,6 +405,7 @@ bool menu_is_visible(struct menu *menu)  	if (!menu->prompt)  		return false; +  	sym = menu->sym;  	if (sym) {  		sym_calc_value(sym); @@ -407,12 +415,14 @@ bool menu_is_visible(struct menu *menu)  	if (visible != no)  		return true; +  	if (!sym || sym_get_tristate_value(menu->sym) == no)  		return false;  	for (child = menu->list; child; child = child->next)  		if (menu_is_visible(child))  			return true; +  	return false;  } @@ -515,6 +525,20 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)  	str_append(r, "\n\n");  } +struct gstr get_relations_str(struct symbol **sym_arr) +{ +	struct symbol *sym; +	struct gstr res = str_new(); +	int i; + +	for (i = 0; sym_arr && (sym = sym_arr[i]); i++) +		get_symbol_str(&res, sym); +	if (!i) +		str_append(&res, _("No matches found.\n")); +	return res; +} + +  void menu_get_ext_help(struct menu *menu, struct gstr *help)  {  	struct symbol *sym = menu->sym; diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c new file mode 100644 index 00000000000..762caf80ce3 --- /dev/null +++ b/scripts/kconfig/nconf.c @@ -0,0 +1,1568 @@ +/* + * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com? + * Released under the terms of the GNU GPL v2.0. + * + * Derived from menuconfig. + * + */ +#define LKC_DIRECT_LINK +#include "lkc.h" +#include "nconf.h" + +static const char nconf_readme[] = N_( +"Overview\n" +"--------\n" +"Some kernel features may be built directly into the kernel.\n" +"Some may be made into loadable runtime modules.  Some features\n" +"may be completely removed altogether.  There are also certain\n" +"kernel parameters which are not really features, but must be\n" +"entered in as decimal or hexadecimal numbers or possibly text.\n" +"\n" +"Menu items beginning with following braces represent features that\n" +"  [ ] can be built in or removed\n" +"  < > can be built in, modularized or removed\n" +"  { } can be built in or modularized (selected by other feature)\n" +"  - - are selected by other feature,\n" +"  XXX cannot be selected. use Symbol Info to find out why,\n" +"while *, M or whitespace inside braces means to build in, build as\n" +"a module or to exclude the feature respectively.\n" +"\n" +"To change any of these features, highlight it with the cursor\n" +"keys and press <Y> to build it in, <M> to make it a module or\n" +"<N> to removed it.  You may also press the <Space Bar> to cycle\n" +"through the available options (ie. Y->N->M->Y).\n" +"\n" +"Some additional keyboard hints:\n" +"\n" +"Menus\n" +"----------\n" +"o  Use the Up/Down arrow keys (cursor keys) to highlight the item\n" +"   you wish to change use <Enter> or <Space>. Goto submenu by \n" +"   pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n" +"   Submenus are designated by \"--->\".\n" +"\n" +"   Shortcut: Press the option's highlighted letter (hotkey).\n" +"             Pressing a hotkey more than once will sequence\n" +"             through all visible items which use that hotkey.\n" +"\n" +"   You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n" +"   unseen options into view.\n" +"\n" +"o  To exit a menu use the just press <ESC> <F5> <F8> or <left-arrow>.\n" +"\n" +"o  To get help with an item, press <F1>\n" +"   Shortcut: Press <h> or <?>.\n" +"\n" +"\n" +"Radiolists  (Choice lists)\n" +"-----------\n" +"o  Use the cursor keys to select the option you wish to set and press\n" +"   <S> or the <SPACE BAR>.\n" +"\n" +"   Shortcut: Press the first letter of the option you wish to set then\n" +"             press <S> or <SPACE BAR>.\n" +"\n" +"o  To see available help for the item, press <F1>\n" +"   Shortcut: Press <H> or <?>.\n" +"\n" +"\n" +"Data Entry\n" +"-----------\n" +"o  Enter the requested information and press <ENTER>\n" +"   If you are entering hexadecimal values, it is not necessary to\n" +"   add the '0x' prefix to the entry.\n" +"\n" +"o  For help, press <F1>.\n" +"\n" +"\n" +"Text Box    (Help Window)\n" +"--------\n" +"o  Use the cursor keys to scroll up/down/left/right.  The VI editor\n" +"   keys h,j,k,l function here as do <SPACE BAR> for those\n" +"   who are familiar with less and lynx.\n" +"\n" +"o  Press <Enter>, <F1>, <F5>, <F7> or <Esc> to exit.\n" +"\n" +"\n" +"Alternate Configuration Files\n" +"-----------------------------\n" +"nconfig supports the use of alternate configuration files for\n" +"those who, for various reasons, find it necessary to switch\n" +"between different kernel configurations.\n" +"\n" +"At the end of the main menu you will find two options.  One is\n" +"for saving the current configuration to a file of your choosing.\n" +"The other option is for loading a previously saved alternate\n" +"configuration.\n" +"\n" +"Even if you don't use alternate configuration files, but you\n" +"find during a nconfig session that you have completely messed\n" +"up your settings, you may use the \"Load Alternate...\" option to\n" +"restore your previously saved settings from \".config\" without\n" +"restarting nconfig.\n" +"\n" +"Other information\n" +"-----------------\n" +"If you use nconfig in an XTERM window make sure you have your\n" +"$TERM variable set to point to a xterm definition which supports color.\n" +"Otherwise, nconfig will look rather bad.  nconfig will not\n" +"display correctly in a RXVT window because rxvt displays only one\n" +"intensity of color, bright.\n" +"\n" +"nconfig will display larger menus on screens or xterms which are\n" +"set to display more than the standard 25 row by 80 column geometry.\n" +"In order for this to work, the \"stty size\" command must be able to\n" +"display the screen's current row and column geometry.  I STRONGLY\n" +"RECOMMEND that you make sure you do NOT have the shell variables\n" +"LINES and COLUMNS exported into your environment.  Some distributions\n" +"export those variables via /etc/profile.  Some ncurses programs can\n" +"become confused when those variables (LINES & COLUMNS) don't reflect\n" +"the true screen size.\n" +"\n" +"Optional personality available\n" +"------------------------------\n" +"If you prefer to have all of the kernel options listed in a single\n" +"menu, rather than the default multimenu hierarchy, run the nconfig\n" +"with NCONFIG_MODE environment variable set to single_menu. Example:\n" +"\n" +"make NCONFIG_MODE=single_menu nconfig\n" +"\n" +"<Enter> will then unroll the appropriate category, or enfold it if it\n" +"is already unrolled.\n" +"\n" +"Note that this mode can eventually be a little more CPU expensive\n" +"(especially with a larger number of unrolled categories) than the\n" +"default mode.\n" +"\n"), +menu_no_f_instructions[] = N_( +" You do not have function keys support. Please follow the\n" +" following instructions:\n" +" Arrow keys navigate the menu.\n" +" <Enter> or <right-arrow> selects submenus --->.\n" +" Capital Letters are hotkeys.\n" +" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n" +" Pressing SpaceBar toggles between the above options\n" +" Press <Esc> or <left-arrow> to go back one menu, \n" +" <?> or <h> for Help, </> for Search.\n" +" <1> is interchangable with <F1>, <2> with <F2>, etc.\n" +" Legend: [*] built-in  [ ] excluded  <M> module  < > module capable.\n" +" <Esc> always leaves the current window\n"), +menu_instructions[] = N_( +" Arrow keys navigate the menu.\n" +" <Enter> or <right-arrow> selects submenus --->.\n" +" Capital Letters are hotkeys.\n" +" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n" +" Pressing SpaceBar toggles between the above options\n" +" Press <Esc>, <F3> or <left-arrow> to go back one menu, \n" +" <?>, <F1> or <h> for Help, </> for Search.\n" +" <1> is interchangable with <F1>, <2> with <F2>, etc.\n" +" Legend: [*] built-in  [ ] excluded  <M> module  < > module capable.\n" +" <Esc> always leaves the current window\n"), +radiolist_instructions[] = N_( +" Use the arrow keys to navigate this window or\n" +" press the hotkey of the item you wish to select\n" +" followed by the <SPACE BAR>.\n" +" Press <?>, <F1> or <h> for additional information about this option.\n"), +inputbox_instructions_int[] = N_( +"Please enter a decimal value.\n" +"Fractions will not be accepted.\n" +"Press <RETURN> to accept, <ESC> to cancel."), +inputbox_instructions_hex[] = N_( +"Please enter a hexadecimal value.\n" +"Press <RETURN> to accept, <ESC> to cancel."), +inputbox_instructions_string[] = N_( +"Please enter a string value.\n" +"Press <RETURN> to accept, <ESC> to cancel."), +setmod_text[] = N_( +"This feature depends on another which\n" +"has been configured as a module.\n" +"As a result, this feature will be built as a module."), +nohelp_text[] = N_( +"There is no help available for this kernel option.\n"), +load_config_text[] = N_( +"Enter the name of the configuration file you wish to load.\n" +"Accept the name shown to restore the configuration you\n" +"last retrieved.  Leave blank to abort."), +load_config_help[] = N_( +"\n" +"For various reasons, one may wish to keep several different kernel\n" +"configurations available on a single machine.\n" +"\n" +"If you have saved a previous configuration in a file other than the\n" +"kernel's default, entering the name of the file here will allow you\n" +"to modify that configuration.\n" +"\n" +"If you are uncertain, then you have probably never used alternate\n" +"configuration files.  You should therefor leave this blank to abort.\n"), +save_config_text[] = N_( +"Enter a filename to which this configuration should be saved\n" +"as an alternate.  Leave blank to abort."), +save_config_help[] = N_( +"\n" +"For various reasons, one may wish to keep different kernel\n" +"configurations available on a single machine.\n" +"\n" +"Entering a file name here will allow you to later retrieve, modify\n" +"and use the current configuration as an alternate to whatever\n" +"configuration options you have selected at that time.\n" +"\n" +"If you are uncertain what all this means then you should probably\n" +"leave this blank.\n"), +search_help[] = N_( +"\n" +"Search for CONFIG_ symbols and display their relations.\n" +"Regular expressions are allowed.\n" +"Example: search for \"^FOO\"\n" +"Result:\n" +"-----------------------------------------------------------------\n" +"Symbol: FOO [ = m]\n" +"Prompt: Foo bus is used to drive the bar HW\n" +"Defined at drivers/pci/Kconfig:47\n" +"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" +"Location:\n" +"  -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" +"    -> PCI support (PCI [ = y])\n" +"      -> PCI access mode (<choice> [ = y])\n" +"Selects: LIBCRC32\n" +"Selected by: BAR\n" +"-----------------------------------------------------------------\n" +"o The line 'Prompt:' shows the text used in the menu structure for\n" +"  this CONFIG_ symbol\n" +"o The 'Defined at' line tell at what file / line number the symbol\n" +"  is defined\n" +"o The 'Depends on:' line tell what symbols needs to be defined for\n" +"  this symbol to be visible in the menu (selectable)\n" +"o The 'Location:' lines tell where in the menu structure this symbol\n" +"  is located\n" +"    A location followed by a [ = y] indicate that this is a selectable\n" +"    menu item - and current value is displayed inside brackets.\n" +"o The 'Selects:' line tell what symbol will be automatically\n" +"  selected if this symbol is selected (y or m)\n" +"o The 'Selected by' line tell what symbol has selected this symbol\n" +"\n" +"Only relevant lines are shown.\n" +"\n\n" +"Search examples:\n" +"Examples: USB   = > find all CONFIG_ symbols containing USB\n" +"          ^USB => find all CONFIG_ symbols starting with USB\n" +"          USB$ => find all CONFIG_ symbols ending with USB\n" +"\n"); + +struct mitem { +	char str[256]; +	char tag; +	void *usrptr; +	int is_hot; +	int is_visible; +}; + +#define MAX_MENU_ITEMS 4096 +static int show_all_items; +static int indent; +static struct menu *current_menu; +static int child_count; +static int single_menu_mode; +/* the window in which all information appears */ +static WINDOW *main_window; +/* the largest size of the menu window */ +static int mwin_max_lines; +static int mwin_max_cols; +/* the window in which we show option buttons */ +static MENU *curses_menu; +static ITEM *curses_menu_items[MAX_MENU_ITEMS]; +static struct mitem k_menu_items[MAX_MENU_ITEMS]; +static int items_num; +static int global_exit; +/* the currently selected button */ +const char *current_instructions = menu_instructions; +/* this array is used to implement hot keys. it is updated in item_make and + * resetted in clean_items. It would be better to use a hash, but lets keep it + * simple... */ +#define MAX_SAME_KEY MAX_MENU_ITEMS +struct { +	int count; +	int ptrs[MAX_MENU_ITEMS]; +} hotkeys[1<<(sizeof(char)*8)]; + +static void conf(struct menu *menu); +static void conf_choice(struct menu *menu); +static void conf_string(struct menu *menu); +static void conf_load(void); +static void conf_save(void); +static void show_help(struct menu *menu); +static int do_exit(void); +static void setup_windows(void); + +typedef void (*function_key_handler_t)(int *key, struct menu *menu); +static void handle_f1(int *key, struct menu *current_item); +static void handle_f2(int *key, struct menu *current_item); +static void handle_f3(int *key, struct menu *current_item); +static void handle_f4(int *key, struct menu *current_item); +static void handle_f5(int *key, struct menu *current_item); +static void handle_f6(int *key, struct menu *current_item); +static void handle_f7(int *key, struct menu *current_item); +static void handle_f8(int *key, struct menu *current_item); + +struct function_keys { +	const char *key_str; +	const char *func; +	function_key key; +	function_key_handler_t handler; +}; + +static const int function_keys_num = 8; +struct function_keys function_keys[] = { +	{ +		.key_str = "F1", +		.func = "Help", +		.key = F_HELP, +		.handler = handle_f1, +	}, +	{ +		.key_str = "F2", +		.func = "Symbol Info", +		.key = F_SYMBOL, +		.handler = handle_f2, +	}, +	{ +		.key_str = "F3", +		.func = "Instructions", +		.key = F_INSTS, +		.handler = handle_f3, +	}, +	{ +		.key_str = "F4", +		.func = "Config", +		.key = F_CONF, +		.handler = handle_f4, +	}, +	{ +		.key_str = "F5", +		.func = "Back", +		.key = F_BACK, +		.handler = handle_f5, +	}, +	{ +		.key_str = "F6", +		.func = "Save", +		.key = F_SAVE, +		.handler = handle_f6, +	}, +	{ +		.key_str = "F7", +		.func = "Load", +		.key = F_LOAD, +		.handler = handle_f7, +	}, +	{ +		.key_str = "F8", +		.func = "Exit", +		.key = F_EXIT, +		.handler = handle_f8, +	}, +}; + +static void print_function_line(void) +{ +	int i; +	int offset = 1; +	const int skip = 1; + +	for (i = 0; i < function_keys_num; i++) { +		wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]); +		mvwprintw(main_window, LINES-3, offset, +				"%s", +				function_keys[i].key_str); +		wattrset(main_window, attributes[FUNCTION_TEXT]); +		offset += strlen(function_keys[i].key_str); +		mvwprintw(main_window, LINES-3, +				offset, "%s", +				function_keys[i].func); +		offset += strlen(function_keys[i].func) + skip; +	} +	wattrset(main_window, attributes[NORMAL]); +} + +/* help */ +static void handle_f1(int *key, struct menu *current_item) +{ +	show_scroll_win(main_window, +			_("README"), _(nconf_readme)); +	return; +} + +/* symbole help */ +static void handle_f2(int *key, struct menu *current_item) +{ +	show_help(current_item); +	return; +} + +/* instructions */ +static void handle_f3(int *key, struct menu *current_item) +{ +	show_scroll_win(main_window, +			_("Instructions"), +			_(current_instructions)); +	return; +} + +/* config */ +static void handle_f4(int *key, struct menu *current_item) +{ +	int res = btn_dialog(main_window, +			_("Show all symbols?"), +			2, +			"   <Show All>   ", +			"<Don't show all>"); +	if (res == 0) +		show_all_items = 1; +	else if (res == 1) +		show_all_items = 0; + +	return; +} + +/* back */ +static void handle_f5(int *key, struct menu *current_item) +{ +	*key = KEY_LEFT; +	return; +} + +/* save */ +static void handle_f6(int *key, struct menu *current_item) +{ +	conf_save(); +	return; +} + +/* load */ +static void handle_f7(int *key, struct menu *current_item) +{ +	conf_load(); +	return; +} + +/* exit */ +static void handle_f8(int *key, struct menu *current_item) +{ +	do_exit(); +	return; +} + +/* return != 0 to indicate the key was handles */ +static int process_special_keys(int *key, struct menu *menu) +{ +	int i; + +	if (*key == KEY_RESIZE) { +		setup_windows(); +		return 1; +	} + +	for (i = 0; i < function_keys_num; i++) { +		if (*key == KEY_F(function_keys[i].key) || +		    *key == '0' + function_keys[i].key){ +			function_keys[i].handler(key, menu); +			return 1; +		} +	} + +	return 0; +} + +static void clean_items(void) +{ +	int i; +	for (i = 0; curses_menu_items[i]; i++) +		free_item(curses_menu_items[i]); +	bzero(curses_menu_items, sizeof(curses_menu_items)); +	bzero(k_menu_items, sizeof(k_menu_items)); +	bzero(hotkeys, sizeof(hotkeys)); +	items_num = 0; +} + +/* return the index of the next hot item, or -1 if no such item exists */ +static int get_next_hot(int c) +{ +	static int hot_index; +	static int hot_char; + +	if (c < 0 || c > 255 || hotkeys[c].count <= 0) +		return -1; + +	if (hot_char == c) { +		hot_index = (hot_index+1)%hotkeys[c].count; +		return hotkeys[c].ptrs[hot_index]; +	} else { +		hot_char = c; +		hot_index = 0; +		return hotkeys[c].ptrs[0]; +	} +} + +/* can the char c be a hot key? no, if c is a common shortcut used elsewhere */ +static int canbhot(char c) +{ +	c = tolower(c); +	return isalnum(c) && c != 'y' && c != 'm' && c != 'h' && +		c != 'n' && c != '?'; +} + +/* check if str already contains a hot key. */ +static int is_hot(int index) +{ +	return k_menu_items[index].is_hot; +} + +/* find the first possible hot key, and mark it. + * index is the index of the item in the menu + * return 0 on success*/ +static int make_hot(char *dest, int len, const char *org, int index) +{ +	int position = -1; +	int i; +	int tmp; +	int c; +	int org_len = strlen(org); + +	if (org == NULL || is_hot(index)) +		return 1; + +	/* make sure not to make hot keys out of markers. +	 * find where to start looking for a hot key +	 */ +	i = 0; +	/* skip white space */ +	while (i < org_len && org[i] == ' ') +		i++; +	if (i == org_len) +		return -1; +	/* if encountering '(' or '<' or '[', find the match and look from there +	 **/ +	if (org[i] == '[' || org[i] == '<' || org[i] == '(') { +		i++; +		for (; i < org_len; i++) +			if (org[i] == ']' || org[i] == '>' || org[i] == ')') +				break; +	} +	if (i == org_len) +		return -1; +	for (; i < org_len; i++) { +		if (canbhot(org[i]) && org[i-1] != '<' && org[i-1] != '(') { +			position = i; +			break; +		} +	} +	if (position == -1) +		return 1; + +	/* ok, char at org[position] should be a hot key to this item */ +	c = tolower(org[position]); +	tmp = hotkeys[c].count; +	hotkeys[c].ptrs[tmp] = index; +	hotkeys[c].count++; +	/* +	   snprintf(dest, len, "%.*s(%c)%s", position, org, org[position], +	   &org[position+1]); +	   */ +	/* make org[position] uppercase, and all leading letter small case */ +	strncpy(dest, org, len); +	for (i = 0; i < position; i++) +		dest[i] = tolower(dest[i]); +	dest[position] = toupper(dest[position]); +	k_menu_items[index].is_hot = 1; +	return 0; +} + +/* Make a new item. Add a hotkey mark in the first possible letter. + * As ncurses does not allow any attributes inside menue item, we mark the + * hot key as the first capitalized letter in the string */ +static void item_make(struct menu *menu, char tag, const char *fmt, ...) +{ +	va_list ap; +	char tmp_str[256]; + +	if (items_num > MAX_MENU_ITEMS-1) +		return; + +	bzero(&k_menu_items[items_num], sizeof(k_menu_items[0])); +	k_menu_items[items_num].tag = tag; +	k_menu_items[items_num].usrptr = menu; +	if (menu != NULL) +		k_menu_items[items_num].is_visible = +			menu_is_visible(menu); +	else +		k_menu_items[items_num].is_visible = 1; + +	va_start(ap, fmt); +	vsnprintf(tmp_str, sizeof(tmp_str), fmt, ap); +	if (!k_menu_items[items_num].is_visible) +		memcpy(tmp_str, "XXX", 3); +	va_end(ap); +	if (make_hot( +		k_menu_items[items_num].str, +		sizeof(k_menu_items[items_num].str), tmp_str, items_num) != 0) +		strncpy(k_menu_items[items_num].str, +			tmp_str, +			sizeof(k_menu_items[items_num].str)); + +	curses_menu_items[items_num] = new_item( +			k_menu_items[items_num].str, +			k_menu_items[items_num].str); +	set_item_userptr(curses_menu_items[items_num], +			&k_menu_items[items_num]); +	/* +	if (!k_menu_items[items_num].is_visible) +		item_opts_off(curses_menu_items[items_num], O_SELECTABLE); +	*/ + +	items_num++; +	curses_menu_items[items_num] = NULL; +} + +/* very hackish. adds a string to the last item added */ +static void item_add_str(const char *fmt, ...) +{ +	va_list ap; +	int index = items_num-1; +	char new_str[256]; +	char tmp_str[256]; + +	if (index < 0) +		return; + +	va_start(ap, fmt); +	vsnprintf(new_str, sizeof(new_str), fmt, ap); +	va_end(ap); +	snprintf(tmp_str, sizeof(tmp_str), "%s%s", +			k_menu_items[index].str, new_str); +	if (make_hot(k_menu_items[index].str, +			sizeof(k_menu_items[index].str), tmp_str, index) != 0) +		strncpy(k_menu_items[index].str, +			tmp_str, +			sizeof(k_menu_items[index].str)); + +	free_item(curses_menu_items[index]); +	curses_menu_items[index] = new_item( +			k_menu_items[index].str, +			k_menu_items[index].str); +	set_item_userptr(curses_menu_items[index], +			&k_menu_items[index]); +} + +/* get the tag of the currently selected item */ +static char item_tag(void) +{ +	ITEM *cur; +	struct mitem *mcur; + +	cur = current_item(curses_menu); +	if (cur == NULL) +		return 0; +	mcur = (struct mitem *) item_userptr(cur); +	return mcur->tag; +} + +static int curses_item_index(void) +{ +	return  item_index(current_item(curses_menu)); +} + +static void *item_data(void) +{ +	ITEM *cur; +	struct mitem *mcur; + +	cur = current_item(curses_menu); +	mcur = (struct mitem *) item_userptr(cur); +	return mcur->usrptr; + +} + +static int item_is_tag(char tag) +{ +	return item_tag() == tag; +} + +static char filename[PATH_MAX+1]; +static char menu_backtitle[PATH_MAX+128]; +static const char *set_config_filename(const char *config_filename) +{ +	int size; +	struct symbol *sym; + +	sym = sym_lookup("KERNELVERSION", 0); +	sym_calc_value(sym); +	size = snprintf(menu_backtitle, sizeof(menu_backtitle), +			_("%s - Linux Kernel v%s Configuration"), +			config_filename, sym_get_string_value(sym)); +	if (size >= sizeof(menu_backtitle)) +		menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; + +	size = snprintf(filename, sizeof(filename), "%s", config_filename); +	if (size >= sizeof(filename)) +		filename[sizeof(filename)-1] = '\0'; +	return menu_backtitle; +} + +/* command = 0 is supress, 1 is restore */ +static void supress_stdout(int command) +{ +	static FILE *org_stdout; +	static FILE *org_stderr; + +	if (command == 0) { +		org_stdout = stdout; +		org_stderr = stderr; +		stdout = fopen("/dev/null", "a"); +		stderr = fopen("/dev/null", "a"); +	} else { +		fclose(stdout); +		fclose(stderr); +		stdout = org_stdout; +		stderr = org_stderr; +	} +} + +/* return = 0 means we are successful. + * -1 means go on doing what you were doing + */ +static int do_exit(void) +{ +	int res; +	if (!conf_get_changed()) { +		global_exit = 1; +		return 0; +	} +	res = btn_dialog(main_window, +			_("Do you wish to save your " +				"new kernel configuration?\n" +				"<ESC> to cancel and resume nconfig."), +			2, +			"   <save>   ", +			"<don't save>"); +	if (res == KEY_EXIT) { +		global_exit = 0; +		return -1; +	} + +	/* if we got here, the user really wants to exit */ +	switch (res) { +	case 0: +		supress_stdout(0); +		res = conf_write(filename); +		supress_stdout(1); +		if (res) +			btn_dialog( +				main_window, +				_("Error during writing of the kernel " +				  "configuration.\n" +				  "Your kernel configuration " +				  "changes were NOT saved."), +				  1, +				  "<OK>"); +		else { +			char buf[1024]; +			snprintf(buf, 1024, +				_("Configuration written to %s\n" +				  "End of Linux kernel configuration.\n" +				  "Execute 'make' to build the kernel or try" +				  " 'make help'."), filename); +			btn_dialog( +				main_window, +				buf, +				1, +				"<OK>"); +		} +		break; +	default: +		btn_dialog( +			main_window, +			_("Your kernel configuration changes were NOT saved."), +			1, +			"<OK>"); +		break; +	} +	global_exit = 1; +	return 0; +} + + +static void search_conf(void) +{ +	struct symbol **sym_arr; +	struct gstr res; +	char dialog_input_result[100]; +	char *dialog_input; +	int dres; +again: +	dres = dialog_inputbox(main_window, +			_("Search Configuration Parameter"), +			_("Enter CONFIG_ (sub)string to search for " +				"(with or without \"CONFIG\")"), +			"", dialog_input_result, 99); +	switch (dres) { +	case 0: +		break; +	case 1: +		show_scroll_win(main_window, +				_("Search Configuration"), search_help); +		goto again; +	default: +		return; +	} + +	/* strip CONFIG_ if necessary */ +	dialog_input = dialog_input_result; +	if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0) +		dialog_input += 7; + +	sym_arr = sym_re_search(dialog_input); +	res = get_relations_str(sym_arr); +	free(sym_arr); +	show_scroll_win(main_window, +			_("Search Results"), str_get(&res)); +	str_free(&res); +} + + +static void build_conf(struct menu *menu) +{ +	struct symbol *sym; +	struct property *prop; +	struct menu *child; +	int type, tmp, doint = 2; +	tristate val; +	char ch; + +	if (!menu || (!show_all_items && !menu_is_visible(menu))) +		return; + +	sym = menu->sym; +	prop = menu->prompt; +	if (!sym) { +		if (prop && menu != current_menu) { +			const char *prompt = menu_get_prompt(menu); +			enum prop_type ptype; +			ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; +			switch (ptype) { +			case P_MENU: +				child_count++; +				prompt = _(prompt); +				if (single_menu_mode) { +					item_make(menu, 'm', +						"%s%*c%s", +						menu->data ? "-->" : "++>", +						indent + 1, ' ', prompt); +				} else +					item_make(menu, 'm', +						"   %*c%s  --->", +						indent + 1, +						' ', prompt); + +				if (single_menu_mode && menu->data) +					goto conf_childs; +				return; +			case P_COMMENT: +				if (prompt) { +					child_count++; +					item_make(menu, ':', +						"   %*c*** %s ***", +						indent + 1, ' ', +						_(prompt)); +				} +				break; +			default: +				if (prompt) { +					child_count++; +					item_make(menu, ':', "---%*c%s", +						indent + 1, ' ', +						_(prompt)); +				} +			} +		} else +			doint = 0; +		goto conf_childs; +	} + +	type = sym_get_type(sym); +	if (sym_is_choice(sym)) { +		struct symbol *def_sym = sym_get_choice_value(sym); +		struct menu *def_menu = NULL; + +		child_count++; +		for (child = menu->list; child; child = child->next) { +			if (menu_is_visible(child) && child->sym == def_sym) +				def_menu = child; +		} + +		val = sym_get_tristate_value(sym); +		if (sym_is_changable(sym)) { +			switch (type) { +			case S_BOOLEAN: +				item_make(menu, 't', "[%c]", +						val == no ? ' ' : '*'); +				break; +			case S_TRISTATE: +				switch (val) { +				case yes: +					ch = '*'; +					break; +				case mod: +					ch = 'M'; +					break; +				default: +					ch = ' '; +					break; +				} +				item_make(menu, 't', "<%c>", ch); +				break; +			} +		} else { +			item_make(menu, def_menu ? 't' : ':', "   "); +		} + +		item_add_str("%*c%s", indent + 1, +				' ', _(menu_get_prompt(menu))); +		if (val == yes) { +			if (def_menu) { +				item_add_str(" (%s)", +					_(menu_get_prompt(def_menu))); +				item_add_str("  --->"); +				if (def_menu->list) { +					indent += 2; +					build_conf(def_menu); +					indent -= 2; +				} +			} +			return; +		} +	} else { +		if (menu == current_menu) { +			item_make(menu, ':', +				"---%*c%s", indent + 1, +				' ', _(menu_get_prompt(menu))); +			goto conf_childs; +		} +		child_count++; +		val = sym_get_tristate_value(sym); +		if (sym_is_choice_value(sym) && val == yes) { +			item_make(menu, ':', "   "); +		} else { +			switch (type) { +			case S_BOOLEAN: +				if (sym_is_changable(sym)) +					item_make(menu, 't', "[%c]", +						val == no ? ' ' : '*'); +				else +					item_make(menu, 't', "-%c-", +						val == no ? ' ' : '*'); +				break; +			case S_TRISTATE: +				switch (val) { +				case yes: +					ch = '*'; +					break; +				case mod: +					ch = 'M'; +					break; +				default: +					ch = ' '; +					break; +				} +				if (sym_is_changable(sym)) { +					if (sym->rev_dep.tri == mod) +						item_make(menu, +							't', "{%c}", ch); +					else +						item_make(menu, +							't', "<%c>", ch); +				} else +					item_make(menu, 't', "-%c-", ch); +				break; +			default: +				tmp = 2 + strlen(sym_get_string_value(sym)); +				item_make(menu, 's', "    (%s)", +						sym_get_string_value(sym)); +				tmp = indent - tmp + 4; +				if (tmp < 0) +					tmp = 0; +				item_add_str("%*c%s%s", tmp, ' ', +						_(menu_get_prompt(menu)), +						(sym_has_value(sym) || +						 !sym_is_changable(sym)) ? "" : +						_(" (NEW)")); +				goto conf_childs; +			} +		} +		item_add_str("%*c%s%s", indent + 1, ' ', +				_(menu_get_prompt(menu)), +				(sym_has_value(sym) || !sym_is_changable(sym)) ? +				"" : _(" (NEW)")); +		if (menu->prompt && menu->prompt->type == P_MENU) { +			item_add_str("  --->"); +			return; +		} +	} + +conf_childs: +	indent += doint; +	for (child = menu->list; child; child = child->next) +		build_conf(child); +	indent -= doint; +} + +static void reset_menu(void) +{ +	unpost_menu(curses_menu); +	clean_items(); +} + +/* adjust the menu to show this item. + * prefer not to scroll the menu if possible*/ +static void center_item(int selected_index, int *last_top_row) +{ +	int toprow; +	int maxy, maxx; + +	scale_menu(curses_menu, &maxy, &maxx); +	set_top_row(curses_menu, *last_top_row); +	toprow = top_row(curses_menu); +	if (selected_index >= toprow && selected_index < toprow+maxy) { +		/* we can only move the selected item. no need to scroll */ +		set_current_item(curses_menu, +				curses_menu_items[selected_index]); +	} else { +		toprow = max(selected_index-maxy/2, 0); +		if (toprow >= item_count(curses_menu)-maxy) +			toprow = item_count(curses_menu)-mwin_max_lines; +		set_top_row(curses_menu, toprow); +		set_current_item(curses_menu, +				curses_menu_items[selected_index]); +	} +	*last_top_row = toprow; +	post_menu(curses_menu); +	refresh_all_windows(main_window); +} + +/* this function assumes reset_menu has been called before */ +static void show_menu(const char *prompt, const char *instructions, +		int selected_index, int *last_top_row) +{ +	int maxx, maxy; +	WINDOW *menu_window; + +	current_instructions = instructions; + +	clear(); +	wattrset(main_window, attributes[NORMAL]); +	print_in_middle(stdscr, 1, 0, COLS, +			menu_backtitle, +			attributes[MAIN_HEADING]); + +	wattrset(main_window, attributes[MAIN_MENU_BOX]); +	box(main_window, 0, 0); +	wattrset(main_window, attributes[MAIN_MENU_HEADING]); +	mvwprintw(main_window, 0, 3, " %s ", prompt); +	wattrset(main_window, attributes[NORMAL]); + +	set_menu_items(curses_menu, curses_menu_items); + +	/* position the menu at the middle of the screen */ +	scale_menu(curses_menu, &maxy, &maxx); +	maxx = min(maxx, mwin_max_cols-2); +	maxy = mwin_max_lines-2; +	menu_window = derwin(main_window, +			maxy, +			maxx, +			2, +			(mwin_max_cols-maxx)/2); +	keypad(menu_window, TRUE); +	set_menu_win(curses_menu, menu_window); +	set_menu_sub(curses_menu, menu_window); + +	/* must reassert this after changing items, otherwise returns to a +	 * default of 16 +	 */ +	set_menu_format(curses_menu, maxy, 1); +	center_item(selected_index, last_top_row); +	set_menu_format(curses_menu, maxy, 1); + +	print_function_line(); + +	/* Post the menu */ +	post_menu(curses_menu); +	refresh_all_windows(main_window); +} + + +static void conf(struct menu *menu) +{ +	char pattern[256]; +	struct menu *submenu = 0; +	const char *prompt = menu_get_prompt(menu); +	struct symbol *sym; +	struct menu *active_menu = NULL; +	int res; +	int current_index = 0; +	int last_top_row = 0; + +	bzero(pattern, sizeof(pattern)); + +	while (!global_exit) { +		reset_menu(); +		current_menu = menu; +		build_conf(menu); +		if (!child_count) +			break; + +		show_menu(prompt ? _(prompt) : _("Main Menu"), +				_(menu_instructions), +				current_index, &last_top_row); +		keypad((menu_win(curses_menu)), TRUE); +		while (!global_exit && (res = wgetch(menu_win(curses_menu)))) { +			if (process_special_keys(&res, +						(struct menu *) item_data())) +				break; +			switch (res) { +			case KEY_DOWN: +				menu_driver(curses_menu, REQ_DOWN_ITEM); +				break; +			case KEY_UP: +				menu_driver(curses_menu, REQ_UP_ITEM); +				break; +			case KEY_NPAGE: +				menu_driver(curses_menu, REQ_SCR_DPAGE); +				break; +			case KEY_PPAGE: +				menu_driver(curses_menu, REQ_SCR_UPAGE); +				break; +			case KEY_HOME: +				menu_driver(curses_menu, REQ_FIRST_ITEM); +				break; +			case KEY_END: +				menu_driver(curses_menu, REQ_LAST_ITEM); +				break; +			case 'h': +			case '?': +				show_help((struct menu *) item_data()); +				break; +			} +			if (res == 10 || res == 27 || +				res == 32 || res == 'n' || res == 'y' || +				res == KEY_LEFT || res == KEY_RIGHT || +				res == 'm' || res == '/') +				break; +			else if (canbhot(res)) { +				/* check for hot keys: */ +				int tmp = get_next_hot(res); +				if (tmp != -1) +					center_item(tmp, &last_top_row); +			} +			refresh_all_windows(main_window); +		} + +		refresh_all_windows(main_window); +		/* if ESC  or left*/ +		if (res == 27 || (menu != &rootmenu && res == KEY_LEFT)) +			break; + +		/* remember location in the menu */ +		last_top_row = top_row(curses_menu); +		current_index = curses_item_index(); + +		if (!item_tag()) +			continue; + +		submenu = (struct menu *) item_data(); +		active_menu = (struct menu *)item_data(); +		if (!submenu || !menu_is_visible(submenu)) +			continue; +		if (submenu) +			sym = submenu->sym; +		else +			sym = NULL; + +		switch (res) { +		case ' ': +			if (item_is_tag('t')) +				sym_toggle_tristate_value(sym); +			else if (item_is_tag('m')) +				conf(submenu); +			break; +		case KEY_RIGHT: +		case 10: /* ENTER WAS PRESSED */ +			switch (item_tag()) { +			case 'm': +				if (single_menu_mode) +					submenu->data = +						(void *) (long) !submenu->data; +				else +					conf(submenu); +				break; +			case 't': +				if (sym_is_choice(sym) && +				    sym_get_tristate_value(sym) == yes) +					conf_choice(submenu); +				else if (submenu->prompt && +					 submenu->prompt->type == P_MENU) +					conf(submenu); +				else if (res == 10) +					sym_toggle_tristate_value(sym); +				break; +			case 's': +				conf_string(submenu); +				break; +			} +			break; +		case 'y': +			if (item_is_tag('t')) { +				if (sym_set_tristate_value(sym, yes)) +					break; +				if (sym_set_tristate_value(sym, mod)) +					btn_dialog(main_window, setmod_text, 0); +			} +			break; +		case 'n': +			if (item_is_tag('t')) +				sym_set_tristate_value(sym, no); +			break; +		case 'm': +			if (item_is_tag('t')) +				sym_set_tristate_value(sym, mod); +			break; +		case '/': +			search_conf(); +			break; +		} +	} +} + +static void show_help(struct menu *menu) +{ +	struct gstr help = str_new(); + +	if (menu && menu->sym && menu_has_help(menu)) { +		if (menu->sym->name) { +			str_printf(&help, "CONFIG_%s:\n\n", menu->sym->name); +			str_append(&help, _(menu_get_help(menu))); +			str_append(&help, "\n"); +			get_symbol_str(&help, menu->sym); +		} +	} else { +		str_append(&help, nohelp_text); +	} +	show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help)); +	str_free(&help); +} + +static void conf_choice(struct menu *menu) +{ +	const char *prompt = _(menu_get_prompt(menu)); +	struct menu *child = 0; +	struct symbol *active; +	int selected_index = 0; +	int last_top_row = 0; +	int res, i = 0; + +	active = sym_get_choice_value(menu->sym); +	/* this is mostly duplicated from the conf() function. */ +	while (!global_exit) { +		reset_menu(); + +		for (i = 0, child = menu->list; child; child = child->next) { +			if (!show_all_items && !menu_is_visible(child)) +				continue; + +			if (child->sym == sym_get_choice_value(menu->sym)) +				item_make(child, ':', "<X> %s", +						_(menu_get_prompt(child))); +			else +				item_make(child, ':', "    %s", +						_(menu_get_prompt(child))); +			if (child->sym == active){ +				last_top_row = top_row(curses_menu); +				selected_index = i; +			} +			i++; +		} +		show_menu(prompt ? _(prompt) : _("Choice Menu"), +				_(radiolist_instructions), +				selected_index, +				&last_top_row); +		while (!global_exit && (res = wgetch(menu_win(curses_menu)))) { +			if (process_special_keys( +						&res, +						(struct menu *) item_data())) +				break; +			switch (res) { +			case KEY_DOWN: +				menu_driver(curses_menu, REQ_DOWN_ITEM); +				break; +			case KEY_UP: +				menu_driver(curses_menu, REQ_UP_ITEM); +				break; +			case KEY_NPAGE: +				menu_driver(curses_menu, REQ_SCR_DPAGE); +				break; +			case KEY_PPAGE: +				menu_driver(curses_menu, REQ_SCR_UPAGE); +				break; +			case KEY_HOME: +				menu_driver(curses_menu, REQ_FIRST_ITEM); +				break; +			case KEY_END: +				menu_driver(curses_menu, REQ_LAST_ITEM); +				break; +			case 'h': +			case '?': +				show_help((struct menu *) item_data()); +				break; +			} +			if (res == 10 || res == 27 || res == ' ' || +				res == KEY_LEFT) +				break; +			else if (canbhot(res)) { +				/* check for hot keys: */ +				int tmp = get_next_hot(res); +				if (tmp != -1) +					center_item(tmp, &last_top_row); +			} +			refresh_all_windows(main_window); +		} +		/* if ESC or left */ +		if (res == 27 || res == KEY_LEFT) +			break; + +		child = item_data(); +		if (!child || !menu_is_visible(child)) +			continue; +		switch (res) { +		case ' ': +		case  10: +		case KEY_RIGHT: +			sym_set_tristate_value(child->sym, yes); +			return; +		case 'h': +		case '?': +			show_help(child); +			active = child->sym; +			break; +		case KEY_EXIT: +			return; +		} +	} +} + +static void conf_string(struct menu *menu) +{ +	const char *prompt = menu_get_prompt(menu); +	char dialog_input_result[256]; + +	while (1) { +		int res; +		const char *heading; + +		switch (sym_get_type(menu->sym)) { +		case S_INT: +			heading = _(inputbox_instructions_int); +			break; +		case S_HEX: +			heading = _(inputbox_instructions_hex); +			break; +		case S_STRING: +			heading = _(inputbox_instructions_string); +			break; +		default: +			heading = _("Internal nconf error!"); +		} +		res = dialog_inputbox(main_window, +				prompt ? _(prompt) : _("Main Menu"), +				heading, +				sym_get_string_value(menu->sym), +				dialog_input_result, +				sizeof(dialog_input_result)); +		switch (res) { +		case 0: +			if (sym_set_string_value(menu->sym, +						dialog_input_result)) +				return; +			btn_dialog(main_window, +				_("You have made an invalid entry."), 0); +			break; +		case 1: +			show_help(menu); +			break; +		case KEY_EXIT: +			return; +		} +	} +} + +static void conf_load(void) +{ +	char dialog_input_result[256]; +	while (1) { +		int res; +		res = dialog_inputbox(main_window, +				NULL, load_config_text, +				filename, +				dialog_input_result, +				sizeof(dialog_input_result)); +		switch (res) { +		case 0: +			if (!dialog_input_result[0]) +				return; +			if (!conf_read(dialog_input_result)) { +				set_config_filename(dialog_input_result); +				sym_set_change_count(1); +				return; +			} +			btn_dialog(main_window, _("File does not exist!"), 0); +			break; +		case 1: +			show_scroll_win(main_window, +					_("Load Alternate Configuration"), +					load_config_help); +			break; +		case KEY_EXIT: +			return; +		} +	} +} + +static void conf_save(void) +{ +	char dialog_input_result[256]; +	while (1) { +		int res; +		res = dialog_inputbox(main_window, +				NULL, save_config_text, +				filename, +				dialog_input_result, +				sizeof(dialog_input_result)); +		switch (res) { +		case 0: +			if (!dialog_input_result[0]) +				return; +			supress_stdout(0); +			res = conf_write(dialog_input_result); +			supress_stdout(1); +			if (!res) { +				char buf[1024]; +				sprintf(buf, "%s %s", +					_("configuration file saved to: "), +					dialog_input_result); +				btn_dialog(main_window, +					   buf, 1, "<OK>"); +				set_config_filename(dialog_input_result); +				return; +			} +			btn_dialog(main_window, _("Can't create file! " +				"Probably a nonexistent directory."), +				1, "<OK>"); +			break; +		case 1: +			show_scroll_win(main_window, +				_("Save Alternate Configuration"), +				save_config_help); +			break; +		case KEY_EXIT: +			return; +		} +	} +} + +void setup_windows(void) +{ +	if (main_window != NULL) +		delwin(main_window); + +	/* set up the menu and menu window */ +	main_window = newwin(LINES-2, COLS-2, 2, 1); +	keypad(main_window, TRUE); +	mwin_max_lines = LINES-6; +	mwin_max_cols = COLS-6; + +	/* panels order is from bottom to top */ +	new_panel(main_window); +} + +int main(int ac, char **av) +{ +	char *mode; + +	setlocale(LC_ALL, ""); +	bindtextdomain(PACKAGE, LOCALEDIR); +	textdomain(PACKAGE); + +	conf_parse(av[1]); +	conf_read(NULL); + +	mode = getenv("NCONFIG_MODE"); +	if (mode) { +		if (!strcasecmp(mode, "single_menu")) +			single_menu_mode = 1; +	} + +	/* Initialize curses */ +	initscr(); +	/* set color theme */ +	set_colors(); + +	cbreak(); +	noecho(); +	keypad(stdscr, TRUE); +	curs_set(0); + +	if (COLS < 75 || LINES < 20) { +		endwin(); +		printf("Your terminal should have at " +			"least 20 lines and 75 columns\n"); +		return 1; +	} + +	notimeout(stdscr, FALSE); +	ESCDELAY = 1; + +	/* set btns menu */ +	curses_menu = new_menu(curses_menu_items); +	menu_opts_off(curses_menu, O_SHOWDESC); +	menu_opts_off(curses_menu, O_SHOWMATCH); +	menu_opts_on(curses_menu, O_ONEVALUE); +	menu_opts_on(curses_menu, O_NONCYCLIC); +	set_menu_mark(curses_menu, " "); +	set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]); +	set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]); +	set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]); + +	set_config_filename(conf_get_configname()); +	setup_windows(); + +	/* check for KEY_FUNC(1) */ +	if (has_key(KEY_F(1)) == FALSE) { +		show_scroll_win(main_window, +				_("Instructions"), +				_(menu_no_f_instructions)); +	} + + + +	/* do the work */ +	while (!global_exit) { +		conf(&rootmenu); +		if (!global_exit && do_exit() == 0) +			break; +	} +	/* ok, we are done */ +	unpost_menu(curses_menu); +	free_menu(curses_menu); +	delwin(main_window); +	clear(); +	refresh(); +	endwin(); +	return 0; +} + diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c new file mode 100644 index 00000000000..115edb437fb --- /dev/null +++ b/scripts/kconfig/nconf.gui.c @@ -0,0 +1,617 @@ +/* + * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com? + * Released under the terms of the GNU GPL v2.0. + * + * Derived from menuconfig. + * + */ +#include "nconf.h" + +/* a list of all the different widgets we use */ +attributes_t attributes[ATTR_MAX+1] = {0}; + +/* available colors: +   COLOR_BLACK   0 +   COLOR_RED     1 +   COLOR_GREEN   2 +   COLOR_YELLOW  3 +   COLOR_BLUE    4 +   COLOR_MAGENTA 5 +   COLOR_CYAN    6 +   COLOR_WHITE   7 +   */ +static void set_normal_colors(void) +{ +	init_pair(NORMAL, -1, -1); +	init_pair(MAIN_HEADING, COLOR_MAGENTA, -1); + +	/* FORE is for the selected item */ +	init_pair(MAIN_MENU_FORE, -1, -1); +	/* BACK for all the rest */ +	init_pair(MAIN_MENU_BACK, -1, -1); +	init_pair(MAIN_MENU_GREY, -1, -1); +	init_pair(MAIN_MENU_HEADING, COLOR_GREEN, -1); +	init_pair(MAIN_MENU_BOX, COLOR_YELLOW, -1); + +	init_pair(SCROLLWIN_TEXT, -1, -1); +	init_pair(SCROLLWIN_HEADING, COLOR_GREEN, -1); +	init_pair(SCROLLWIN_BOX, COLOR_YELLOW, -1); + +	init_pair(DIALOG_TEXT, -1, -1); +	init_pair(DIALOG_BOX, COLOR_YELLOW, -1); +	init_pair(DIALOG_MENU_BACK, COLOR_YELLOW, -1); +	init_pair(DIALOG_MENU_FORE, COLOR_RED, -1); + +	init_pair(INPUT_BOX, COLOR_YELLOW, -1); +	init_pair(INPUT_HEADING, COLOR_GREEN, -1); +	init_pair(INPUT_TEXT, -1, -1); +	init_pair(INPUT_FIELD, -1, -1); + +	init_pair(FUNCTION_HIGHLIGHT, -1, -1); +	init_pair(FUNCTION_TEXT, COLOR_BLUE, -1); +} + +/* available attributes: +   A_NORMAL        Normal display (no highlight) +   A_STANDOUT      Best highlighting mode of the terminal. +   A_UNDERLINE     Underlining +   A_REVERSE       Reverse video +   A_BLINK         Blinking +   A_DIM           Half bright +   A_BOLD          Extra bright or bold +   A_PROTECT       Protected mode +   A_INVIS         Invisible or blank mode +   A_ALTCHARSET    Alternate character set +   A_CHARTEXT      Bit-mask to extract a character +   COLOR_PAIR(n)   Color-pair number n +   */ +static void normal_color_theme(void) +{ +	/* automatically add color... */ +#define mkattr(name, attr) do { \ +attributes[name] = attr | COLOR_PAIR(name); } while (0) +	mkattr(NORMAL, NORMAL); +	mkattr(MAIN_HEADING, A_BOLD | A_UNDERLINE); + +	mkattr(MAIN_MENU_FORE, A_REVERSE); +	mkattr(MAIN_MENU_BACK, A_NORMAL); +	mkattr(MAIN_MENU_GREY, A_NORMAL); +	mkattr(MAIN_MENU_HEADING, A_BOLD); +	mkattr(MAIN_MENU_BOX, A_NORMAL); + +	mkattr(SCROLLWIN_TEXT, A_NORMAL); +	mkattr(SCROLLWIN_HEADING, A_BOLD); +	mkattr(SCROLLWIN_BOX, A_BOLD); + +	mkattr(DIALOG_TEXT, A_BOLD); +	mkattr(DIALOG_BOX, A_BOLD); +	mkattr(DIALOG_MENU_FORE, A_STANDOUT); +	mkattr(DIALOG_MENU_BACK, A_NORMAL); + +	mkattr(INPUT_BOX, A_NORMAL); +	mkattr(INPUT_HEADING, A_BOLD); +	mkattr(INPUT_TEXT, A_NORMAL); +	mkattr(INPUT_FIELD, A_UNDERLINE); + +	mkattr(FUNCTION_HIGHLIGHT, A_BOLD); +	mkattr(FUNCTION_TEXT, A_REVERSE); +} + +static void no_colors_theme(void) +{ +	/* automatically add highlight, no color */ +#define mkattrn(name, attr) { attributes[name] = attr; } + +	mkattrn(NORMAL, NORMAL); +	mkattrn(MAIN_HEADING, A_BOLD | A_UNDERLINE); + +	mkattrn(MAIN_MENU_FORE, A_STANDOUT); +	mkattrn(MAIN_MENU_BACK, A_NORMAL); +	mkattrn(MAIN_MENU_GREY, A_NORMAL); +	mkattrn(MAIN_MENU_HEADING, A_BOLD); +	mkattrn(MAIN_MENU_BOX, A_NORMAL); + +	mkattrn(SCROLLWIN_TEXT, A_NORMAL); +	mkattrn(SCROLLWIN_HEADING, A_BOLD); +	mkattrn(SCROLLWIN_BOX, A_BOLD); + +	mkattrn(DIALOG_TEXT, A_NORMAL); +	mkattrn(DIALOG_BOX, A_BOLD); +	mkattrn(DIALOG_MENU_FORE, A_STANDOUT); +	mkattrn(DIALOG_MENU_BACK, A_NORMAL); + +	mkattrn(INPUT_BOX, A_BOLD); +	mkattrn(INPUT_HEADING, A_BOLD); +	mkattrn(INPUT_TEXT, A_NORMAL); +	mkattrn(INPUT_FIELD, A_UNDERLINE); + +	mkattrn(FUNCTION_HIGHLIGHT, A_BOLD); +	mkattrn(FUNCTION_TEXT, A_REVERSE); +} + +void set_colors() +{ +	start_color(); +	use_default_colors(); +	set_normal_colors(); +	if (has_colors()) { +		normal_color_theme(); +	} else { +		/* give deafults */ +		no_colors_theme(); +	} +} + + +/* this changes the windows attributes !!! */ +void print_in_middle(WINDOW *win, +		int starty, +		int startx, +		int width, +		const char *string, +		chtype color) +{      int length, x, y; +	float temp; + + +	if (win == NULL) +		win = stdscr; +	getyx(win, y, x); +	if (startx != 0) +		x = startx; +	if (starty != 0) +		y = starty; +	if (width == 0) +		width = 80; + +	length = strlen(string); +	temp = (width - length) / 2; +	x = startx + (int)temp; +	wattrset(win, color); +	mvwprintw(win, y, x, "%s", string); +	refresh(); +} + +int get_line_no(const char *text) +{ +	int i; +	int total = 1; + +	if (!text) +		return 0; + +	for (i = 0; text[i] != '\0'; i++) +		if (text[i] == '\n') +			total++; +	return total; +} + +const char *get_line(const char *text, int line_no) +{ +	int i; +	int lines = 0; + +	if (!text) +		return 0; + +	for (i = 0; text[i] != '\0' && lines < line_no; i++) +		if (text[i] == '\n') +			lines++; +	return text+i; +} + +int get_line_length(const char *line) +{ +	int res = 0; +	while (*line != '\0' && *line != '\n') { +		line++; +		res++; +	} +	return res; +} + +/* print all lines to the window. */ +void fill_window(WINDOW *win, const char *text) +{ +	int x, y; +	int total_lines = get_line_no(text); +	int i; + +	getmaxyx(win, y, x); +	/* do not go over end of line */ +	total_lines = min(total_lines, y); +	for (i = 0; i < total_lines; i++) { +		char tmp[x+10]; +		const char *line = get_line(text, i); +		int len = get_line_length(line); +		strncpy(tmp, line, min(len, x)); +		tmp[len] = '\0'; +		mvwprintw(win, i, 0, tmp); +	} +} + +/* get the message, and buttons. + * each button must be a char* + * return the selected button + * + * this dialog is used for 2 different things: + * 1) show a text box, no buttons. + * 2) show a dialog, with horizontal buttons + */ +int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...) +{ +	va_list ap; +	char *btn; +	int btns_width = 0; +	int msg_lines = 0; +	int msg_width = 0; +	int total_width; +	int win_rows = 0; +	WINDOW *win; +	WINDOW *msg_win; +	WINDOW *menu_win; +	MENU *menu; +	ITEM *btns[btn_num+1]; +	int i, x, y; +	int res = -1; + + +	va_start(ap, btn_num); +	for (i = 0; i < btn_num; i++) { +		btn = va_arg(ap, char *); +		btns[i] = new_item(btn, ""); +		btns_width += strlen(btn)+1; +	} +	va_end(ap); +	btns[btn_num] = NULL; + +	/* find the widest line of msg: */ +	msg_lines = get_line_no(msg); +	for (i = 0; i < msg_lines; i++) { +		const char *line = get_line(msg, i); +		int len = get_line_length(line); +		if (msg_width < len) +			msg_width = len; +	} + +	total_width = max(msg_width, btns_width); +	/* place dialog in middle of screen */ +	y = (LINES-(msg_lines+4))/2; +	x = (COLS-(total_width+4))/2; + + +	/* create the windows */ +	if (btn_num > 0) +		win_rows = msg_lines+4; +	else +		win_rows = msg_lines+2; + +	win = newwin(win_rows, total_width+4, y, x); +	keypad(win, TRUE); +	menu_win = derwin(win, 1, btns_width, win_rows-2, +			1+(total_width+2-btns_width)/2); +	menu = new_menu(btns); +	msg_win = derwin(win, win_rows-2, msg_width, 1, +			1+(total_width+2-msg_width)/2); + +	set_menu_fore(menu, attributes[DIALOG_MENU_FORE]); +	set_menu_back(menu, attributes[DIALOG_MENU_BACK]); + +	wattrset(win, attributes[DIALOG_BOX]); +	box(win, 0, 0); + +	/* print message */ +	wattrset(msg_win, attributes[DIALOG_TEXT]); +	fill_window(msg_win, msg); + +	set_menu_win(menu, win); +	set_menu_sub(menu, menu_win); +	set_menu_format(menu, 1, btn_num); +	menu_opts_off(menu, O_SHOWDESC); +	menu_opts_off(menu, O_SHOWMATCH); +	menu_opts_on(menu, O_ONEVALUE); +	menu_opts_on(menu, O_NONCYCLIC); +	set_menu_mark(menu, ""); +	post_menu(menu); + + +	touchwin(win); +	refresh_all_windows(main_window); +	while ((res = wgetch(win))) { +		switch (res) { +		case KEY_LEFT: +			menu_driver(menu, REQ_LEFT_ITEM); +			break; +		case KEY_RIGHT: +			menu_driver(menu, REQ_RIGHT_ITEM); +			break; +		case 10: /* ENTER */ +		case 27: /* ESCAPE */ +		case ' ': +		case KEY_F(F_BACK): +		case KEY_F(F_EXIT): +			break; +		} +		touchwin(win); +		refresh_all_windows(main_window); + +		if (res == 10 || res == ' ') { +			res = item_index(current_item(menu)); +			break; +		} else if (res == 27 || res == KEY_F(F_BACK) || +				res == KEY_F(F_EXIT)) { +			res = KEY_EXIT; +			break; +		} +	} + +	unpost_menu(menu); +	free_menu(menu); +	for (i = 0; i < btn_num; i++) +		free_item(btns[i]); + +	delwin(win); +	return res; +} + +int dialog_inputbox(WINDOW *main_window, +		const char *title, const char *prompt, +		const char *init, char *result, int result_len) +{ +	int prompt_lines = 0; +	int prompt_width = 0; +	WINDOW *win; +	WINDOW *prompt_win; +	WINDOW *form_win; +	PANEL *panel; +	int i, x, y; +	int res = -1; +	int cursor_position = strlen(init); + + +	/* find the widest line of msg: */ +	prompt_lines = get_line_no(prompt); +	for (i = 0; i < prompt_lines; i++) { +		const char *line = get_line(prompt, i); +		int len = get_line_length(line); +		prompt_width = max(prompt_width, len); +	} + +	if (title) +		prompt_width = max(prompt_width, strlen(title)); + +	/* place dialog in middle of screen */ +	y = (LINES-(prompt_lines+4))/2; +	x = (COLS-(prompt_width+4))/2; + +	strncpy(result, init, result_len); + +	/* create the windows */ +	win = newwin(prompt_lines+6, prompt_width+7, y, x); +	prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2); +	form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2); +	keypad(form_win, TRUE); + +	wattrset(form_win, attributes[INPUT_FIELD]); + +	wattrset(win, attributes[INPUT_BOX]); +	box(win, 0, 0); +	wattrset(win, attributes[INPUT_HEADING]); +	if (title) +		mvwprintw(win, 0, 3, "%s", title); + +	/* print message */ +	wattrset(prompt_win, attributes[INPUT_TEXT]); +	fill_window(prompt_win, prompt); + +	mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); +	mvwprintw(form_win, 0, 0, "%s", result); + +	/* create panels */ +	panel = new_panel(win); + +	/* show the cursor */ +	curs_set(1); + +	touchwin(win); +	refresh_all_windows(main_window); +	while ((res = wgetch(form_win))) { +		int len = strlen(result); +		switch (res) { +		case 10: /* ENTER */ +		case 27: /* ESCAPE */ +		case KEY_F(F_HELP): +		case KEY_F(F_EXIT): +		case KEY_F(F_BACK): +			break; +		case 127: +		case KEY_BACKSPACE: +			if (cursor_position > 0) { +				memmove(&result[cursor_position-1], +						&result[cursor_position], +						len-cursor_position+1); +				cursor_position--; +			} +			break; +		case KEY_DC: +			if (cursor_position >= 0 && cursor_position < len) { +				memmove(&result[cursor_position], +						&result[cursor_position+1], +						len-cursor_position+1); +			} +			break; +		case KEY_UP: +		case KEY_RIGHT: +			if (cursor_position < len && +			    cursor_position < min(result_len, prompt_width)) +				cursor_position++; +			break; +		case KEY_DOWN: +		case KEY_LEFT: +			if (cursor_position > 0) +				cursor_position--; +			break; +		default: +			if ((isgraph(res) || isspace(res)) && +					len-2 < result_len) { +				/* insert the char at the proper position */ +				memmove(&result[cursor_position+1], +						&result[cursor_position], +						len+1); +				result[cursor_position] = res; +				cursor_position++; +			} else { +				mvprintw(0, 0, "unknow key: %d\n", res); +			} +			break; +		} +		wmove(form_win, 0, 0); +		wclrtoeol(form_win); +		mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); +		mvwprintw(form_win, 0, 0, "%s", result); +		wmove(form_win, 0, cursor_position); +		touchwin(win); +		refresh_all_windows(main_window); + +		if (res == 10) { +			res = 0; +			break; +		} else if (res == 27 || res == KEY_F(F_BACK) || +				res == KEY_F(F_EXIT)) { +			res = KEY_EXIT; +			break; +		} else if (res == KEY_F(F_HELP)) { +			res = 1; +			break; +		} +	} + +	/* hide the cursor */ +	curs_set(0); +	del_panel(panel); +	delwin(prompt_win); +	delwin(form_win); +	delwin(win); +	return res; +} + +/* refresh all windows in the correct order */ +void refresh_all_windows(WINDOW *main_window) +{ +	update_panels(); +	touchwin(main_window); +	refresh(); +} + +/* layman's scrollable window... */ +void show_scroll_win(WINDOW *main_window, +		const char *title, +		const char *text) +{ +	int res; +	int total_lines = get_line_no(text); +	int x, y; +	int start_x = 0, start_y = 0; +	int text_lines = 0, text_cols = 0; +	int total_cols = 0; +	int win_cols = 0; +	int win_lines = 0; +	int i = 0; +	WINDOW *win; +	WINDOW *pad; +	PANEL *panel; + +	/* find the widest line of msg: */ +	total_lines = get_line_no(text); +	for (i = 0; i < total_lines; i++) { +		const char *line = get_line(text, i); +		int len = get_line_length(line); +		total_cols = max(total_cols, len+2); +	} + +	/* create the pad */ +	pad = newpad(total_lines+10, total_cols+10); +	wattrset(pad, attributes[SCROLLWIN_TEXT]); +	fill_window(pad, text); + +	win_lines = min(total_lines+4, LINES-2); +	win_cols = min(total_cols+2, COLS-2); +	text_lines = max(win_lines-4, 0); +	text_cols = max(win_cols-2, 0); + +	/* place window in middle of screen */ +	y = (LINES-win_lines)/2; +	x = (COLS-win_cols)/2; + +	win = newwin(win_lines, win_cols, y, x); +	keypad(win, TRUE); +	/* show the help in the help window, and show the help panel */ +	wattrset(win, attributes[SCROLLWIN_BOX]); +	box(win, 0, 0); +	wattrset(win, attributes[SCROLLWIN_HEADING]); +	mvwprintw(win, 0, 3, " %s ", title); +	panel = new_panel(win); + +	/* handle scrolling */ +	do { + +		copywin(pad, win, start_y, start_x, 2, 2, text_lines, +				text_cols, 0); +		print_in_middle(win, +				text_lines+2, +				0, +				text_cols, +				"<OK>", +				attributes[DIALOG_MENU_FORE]); +		wrefresh(win); + +		res = wgetch(win); +		switch (res) { +		case KEY_NPAGE: +		case ' ': +			start_y += text_lines-2; +			break; +		case KEY_PPAGE: +			start_y -= text_lines+2; +			break; +		case KEY_HOME: +			start_y = 0; +			break; +		case KEY_END: +			start_y = total_lines-text_lines; +			break; +		case KEY_DOWN: +		case 'j': +			start_y++; +			break; +		case KEY_UP: +		case 'k': +			start_y--; +			break; +		case KEY_LEFT: +		case 'h': +			start_x--; +			break; +		case KEY_RIGHT: +		case 'l': +			start_x++; +			break; +		} +		if (res == 10 || res == 27 || res == 'q' +		    || res == KEY_F(F_BACK) || res == KEY_F(F_EXIT)) { +			break; +		} +		if (start_y < 0) +			start_y = 0; +		if (start_y >= total_lines-text_lines) +			start_y = total_lines-text_lines; +		if (start_x < 0) +			start_x = 0; +		if (start_x >= total_cols-text_cols) +			start_x = total_cols-text_cols; +	} while (res); + +	del_panel(panel); +	delwin(win); +	refresh_all_windows(main_window); +} diff --git a/scripts/kconfig/nconf.h b/scripts/kconfig/nconf.h new file mode 100644 index 00000000000..fb429666600 --- /dev/null +++ b/scripts/kconfig/nconf.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com? + * Released under the terms of the GNU GPL v2.0. + * + * Derived from menuconfig. + * + */ + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <locale.h> +#include <curses.h> +#include <menu.h> +#include <panel.h> +#include <form.h> + +#include <stdio.h> +#include <time.h> +#include <sys/time.h> + +#include "ncurses.h" + +#define max(a, b) ({\ +		typeof(a) _a = a;\ +		typeof(b) _b = b;\ +		_a > _b ? _a : _b; }) + +#define min(a, b) ({\ +		typeof(a) _a = a;\ +		typeof(b) _b = b;\ +		_a < _b ? _a : _b; }) + +typedef enum { +	NORMAL = 1, +	MAIN_HEADING, +	MAIN_MENU_BOX, +	MAIN_MENU_FORE, +	MAIN_MENU_BACK, +	MAIN_MENU_GREY, +	MAIN_MENU_HEADING, +	SCROLLWIN_TEXT, +	SCROLLWIN_HEADING, +	SCROLLWIN_BOX, +	DIALOG_TEXT, +	DIALOG_MENU_FORE, +	DIALOG_MENU_BACK, +	DIALOG_BOX, +	INPUT_BOX, +	INPUT_HEADING, +	INPUT_TEXT, +	INPUT_FIELD, +	FUNCTION_TEXT, +	FUNCTION_HIGHLIGHT, +	ATTR_MAX +} attributes_t; +extern attributes_t attributes[]; + +typedef enum { +	F_HELP = 1, +	F_SYMBOL = 2, +	F_INSTS = 3, +	F_CONF = 4, +	F_BACK = 5, +	F_SAVE = 6, +	F_LOAD = 7, +	F_EXIT = 8 +} function_key; + +void set_colors(void); + +/* this changes the windows attributes !!! */ +void print_in_middle(WINDOW *win, +		int starty, +		int startx, +		int width, +		const char *string, +		chtype color); +int get_line_length(const char *line); +int get_line_no(const char *text); +const char *get_line(const char *text, int line_no); +void fill_window(WINDOW *win, const char *text); +int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...); +int dialog_inputbox(WINDOW *main_window, +		const char *title, const char *prompt, +		const char *init, char *result, int result_len); +void refresh_all_windows(WINDOW *main_window); +void show_scroll_win(WINDOW *main_window, +		const char *title, +		const char *text); diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 6c8fbbb66eb..2e7a048e0cf 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -651,12 +651,20 @@ bool sym_is_changable(struct symbol *sym)  	return sym->visible > sym->rev_dep.tri;  } +static unsigned strhash(const char *s) +{ +	/* fnv32 hash */ +	unsigned hash = 2166136261U; +	for (; *s; s++) +		hash = (hash ^ *s) * 0x01000193; +	return hash; +} +  struct symbol *sym_lookup(const char *name, int flags)  {  	struct symbol *symbol; -	const char *ptr;  	char *new_name; -	int hash = 0; +	int hash;  	if (name) {  		if (name[0] && !name[1]) { @@ -666,12 +674,11 @@ struct symbol *sym_lookup(const char *name, int flags)  			case 'n': return &symbol_no;  			}  		} -		for (ptr = name; *ptr; ptr++) -			hash += *ptr; -		hash &= 0xff; +		hash = strhash(name) % SYMBOL_HASHSIZE;  		for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { -			if (!strcmp(symbol->name, name) && +			if (symbol->name && +			    !strcmp(symbol->name, name) &&  			    (flags ? symbol->flags & flags  				   : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))  				return symbol; @@ -679,7 +686,7 @@ struct symbol *sym_lookup(const char *name, int flags)  		new_name = strdup(name);  	} else {  		new_name = NULL; -		hash = 256; +		hash = 0;  	}  	symbol = malloc(sizeof(*symbol)); @@ -697,7 +704,6 @@ struct symbol *sym_lookup(const char *name, int flags)  struct symbol *sym_find(const char *name)  {  	struct symbol *symbol = NULL; -	const char *ptr;  	int hash = 0;  	if (!name) @@ -710,12 +716,11 @@ struct symbol *sym_find(const char *name)  		case 'n': return &symbol_no;  		}  	} -	for (ptr = name; *ptr; ptr++) -		hash += *ptr; -	hash &= 0xff; +	hash = strhash(name) % SYMBOL_HASHSIZE;  	for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { -		if (!strcmp(symbol->name, name) && +		if (symbol->name && +		    !strcmp(symbol->name, name) &&  		    !(symbol->flags & SYMBOL_CONST))  				break;  	} @@ -750,6 +755,7 @@ struct symbol **sym_re_search(const char *pattern)  				return NULL;  			}  		} +		sym_calc_value(sym);  		sym_arr[cnt++] = sym;  	}  	if (sym_arr) diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c index 25d1ec4ca28..78b5c04e736 100644 --- a/scripts/kconfig/util.c +++ b/scripts/kconfig/util.c @@ -78,6 +78,7 @@ struct gstr str_new(void)  	struct gstr gs;  	gs.s = malloc(sizeof(char) * 64);  	gs.len = 64; +	gs.max_width = 0;  	strcpy(gs.s, "\0");  	return gs;  } @@ -88,6 +89,7 @@ struct gstr str_assign(const char *s)  	struct gstr gs;  	gs.s = strdup(s);  	gs.len = strlen(s) + 1; +	gs.max_width = 0;  	return gs;  } diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped index 6e9dcd59aa8..32a9eefd842 100644 --- a/scripts/kconfig/zconf.tab.c_shipped +++ b/scripts/kconfig/zconf.tab.c_shipped @@ -104,7 +104,7 @@ static void zconf_error(const char *err, ...);  static void zconferror(const char *err);  static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); -struct symbol *symbol_hash[257]; +struct symbol *symbol_hash[SYMBOL_HASHSIZE];  static struct menu *current_menu, *current_entry; @@ -2220,7 +2220,7 @@ void conf_parse(const char *name)  	zconf_initscan(name);  	sym_init(); -	menu_init(); +	_menu_init();  	modules_sym = sym_lookup(NULL, 0);  	modules_sym->type = S_BOOLEAN;  	modules_sym->flags |= SYMBOL_AUTO; @@ -2336,9 +2336,9 @@ static void print_symbol(FILE *out, struct menu *menu)  	struct property *prop;  	if (sym_is_choice(sym)) -		fprintf(out, "choice\n"); +		fprintf(out, "\nchoice\n");  	else -		fprintf(out, "config %s\n", sym->name); +		fprintf(out, "\nconfig %s\n", sym->name);  	switch (sym->type) {  	case S_BOOLEAN:  		fputs("  boolean\n", out); @@ -2384,6 +2384,21 @@ static void print_symbol(FILE *out, struct menu *menu)  		case P_CHOICE:  			fputs("  #choice value\n", out);  			break; +		case P_SELECT: +			fputs( "  select ", out); +			expr_fprint(prop->expr, out); +			fputc('\n', out); +			break; +		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;  		default:  			fprintf(out, "  unknown prop %d!\n", prop->type);  			break; @@ -2395,7 +2410,6 @@ static void print_symbol(FILE *out, struct menu *menu)  			menu->help[len] = 0;  		fprintf(out, "  help\n%s\n", menu->help);  	} -	fputc('\n', out);  }  void zconfdump(FILE *out) @@ -2428,7 +2442,6 @@ void zconfdump(FILE *out)  				expr_fprint(prop->visible.expr, out);  				fputc('\n', out);  			} -			fputs("\n", out);  		}  		if (menu->list) diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y index 8c43491f8cc..23dfd3baa7a 100644 --- a/scripts/kconfig/zconf.y +++ b/scripts/kconfig/zconf.y @@ -27,7 +27,7 @@ static void zconf_error(const char *err, ...);  static void zconferror(const char *err);  static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); -struct symbol *symbol_hash[257]; +struct symbol *symbol_hash[SYMBOL_HASHSIZE];  static struct menu *current_menu, *current_entry; @@ -475,7 +475,7 @@ void conf_parse(const char *name)  	zconf_initscan(name);  	sym_init(); -	menu_init(); +	_menu_init();  	modules_sym = sym_lookup(NULL, 0);  	modules_sym->type = S_BOOLEAN;  	modules_sym->flags |= SYMBOL_AUTO; @@ -591,9 +591,9 @@ static void print_symbol(FILE *out, struct menu *menu)  	struct property *prop;  	if (sym_is_choice(sym)) -		fprintf(out, "choice\n"); +		fprintf(out, "\nchoice\n");  	else -		fprintf(out, "config %s\n", sym->name); +		fprintf(out, "\nconfig %s\n", sym->name);  	switch (sym->type) {  	case S_BOOLEAN:  		fputs("  boolean\n", out); @@ -639,6 +639,21 @@ static void print_symbol(FILE *out, struct menu *menu)  		case P_CHOICE:  			fputs("  #choice value\n", out);  			break; +		case P_SELECT: +			fputs( "  select ", out); +			expr_fprint(prop->expr, out); +			fputc('\n', out); +			break; +		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;  		default:  			fprintf(out, "  unknown prop %d!\n", prop->type);  			break; @@ -650,7 +665,6 @@ static void print_symbol(FILE *out, struct menu *menu)  			menu->help[len] = 0;  		fprintf(out, "  help\n%s\n", menu->help);  	} -	fputc('\n', out);  }  void zconfdump(FILE *out) @@ -683,7 +697,6 @@ void zconfdump(FILE *out)  				expr_fprint(prop->visible.expr, out);  				fputc('\n', out);  			} -			fputs("\n", out);  		}  		if (menu->list)  |