build: scripts/config - update to kconfig-v5.6
Major changes include: - Much more readable reverse dependencies separated in groups - Improved recursive dependency report - More readable .config files: add comments to signal end of menus - More warnings for incorrect Config.in entries, such as a 'choice' default not contained in the 'choice' - Hability to properly display pseudographics with non-latin locales - Recursive dependencies are now treated as errors - this should make it harder for them to creep in. Signed-off-by: Eneas U de Queiroz <cotequeiroz@gmail.com>
This commit is contained in:
		 Eneas U de Queiroz
					Eneas U de Queiroz
				
			
				
					committed by
					
						 Petr Štetiar
						Petr Štetiar
					
				
			
			
				
	
			
			
			 Petr Štetiar
						Petr Štetiar
					
				
			
						parent
						
							8636a17214
						
					
				
				
					commit
					dcf3e63a35
				
			
							
								
								
									
										29
									
								
								scripts/config/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								scripts/config/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,15 +1,14 @@ | |||||||
| *.o | # | ||||||
| conf* | # Generated files | ||||||
| !conf*.c | # | ||||||
| !conf*.h | *.moc | ||||||
| mconf* | *conf-cfg | ||||||
| !mconf*.c |  | ||||||
| !mconf*.h | # | ||||||
| mconf_check | # configuration programs | ||||||
| *.*.c | # | ||||||
| qconf* | conf | ||||||
| qconf*.moc | mconf | ||||||
| !qconf*.cc | nconf | ||||||
| !qconf*.h | qconf | ||||||
| !images*.c | gconf | ||||||
| .tmp_qtcheck |  | ||||||
|   | |||||||
| @@ -1,102 +1,124 @@ | |||||||
|  | # SPDX-License-Identifier: GPL-2.0 | ||||||
| # =========================================================================== | # =========================================================================== | ||||||
| # OpenWrt configuration targets | # OpenWrt configuration targets | ||||||
| # These targets are used from top-level makefile |  | ||||||
|  | .PHONY: clean all | ||||||
|  | all: conf mconf | ||||||
|  | clean: | ||||||
|  | 	rm -f *.o lxdialog/*.o *.moc $(clean-files) conf mconf qconf | ||||||
|  |  | ||||||
|  | clean-files	:= | ||||||
|  |  | ||||||
| # =========================================================================== | # =========================================================================== | ||||||
| # Shared Makefile for the various kconfig executables: | # Variables needed by the upstream Makefile | ||||||
| # conf:	  Used for defconfig, oldconfig and related targets |  | ||||||
| # mconf:  Used for the mconfig target. | # Avoids displaying 'UPD mconf-cfg' in an otherwise quiet make menuconfig | ||||||
| #         Utilizes the lxdialog package | kecho:=true | ||||||
| # qconf:  Used for the xconfig target |  | ||||||
| #         Based on Qt which needs to be installed to compile it | CONFIG_SHELL:=$(SHELL) | ||||||
|  | srctree:=. | ||||||
|  | src:=. | ||||||
|  | obj:=. | ||||||
|  | Q:=$(if $V,,@) | ||||||
|  | cmd = $(cmd_$(1)) | ||||||
|  | dot-target = $(dir $@).$(notdir $@) | ||||||
|  |  | ||||||
|  | # taken from ../Kbuild.include | ||||||
|  | define filechk | ||||||
|  | 	$(Q)set -e;						\ | ||||||
|  | 	mkdir -p $(dir $@);					\ | ||||||
|  | 	trap "rm -f $(dot-target).tmp" EXIT;			\ | ||||||
|  | 	{ $(filechk_$(1)); } > $(dot-target).tmp;		\ | ||||||
|  | 	if [ ! -r $@ ] || ! cmp -s $@ $(dot-target).tmp; then	\ | ||||||
|  | 		$(kecho) '  UPD     $@';			\ | ||||||
|  | 		mv -f $(dot-target).tmp $@;			\ | ||||||
|  | 	fi | ||||||
|  | endef | ||||||
|  |  | ||||||
|  | ### Stripped down upstream Makefile follows: | ||||||
|  | # =========================================================================== | ||||||
| # object files used by all kconfig flavours | # object files used by all kconfig flavours | ||||||
|  | common-objs	:= confdata.o expr.o lexer.lex.o parser.tab.o preprocess.o \ | ||||||
|  | 		   symbol.o util.o | ||||||
|  |  | ||||||
|  | $(obj)/lexer.lex.o: $(obj)/parser.tab.h | ||||||
|  | HOSTCFLAGS_lexer.lex.o	:= -I $(srctree)/$(src) | ||||||
|  | HOSTCFLAGS_parser.tab.o	:= -I $(srctree)/$(src) | ||||||
|  |  | ||||||
| # Platform specific fixes | # conf: Used for defconfig, oldconfig and related targets | ||||||
| # | hostprogs-y	+= conf | ||||||
| # FreeBSD | conf-objs	:= conf.o $(common-objs) | ||||||
|  |  | ||||||
| check_lxdialog = $(shell $(SHELL) $(CURDIR)/lxdialog/check-lxdialog.sh -$(1)) | # mconf: Used for the menuconfig target based on lxdialog | ||||||
| export CFLAGS += -DKBUILD_NO_NLS -I. $(call check_lxdialog,ccflags) | hostprogs-y	+= mconf | ||||||
| export CXXFLAGS += -DKBUILD_NO_NLS | lxdialog	:= $(addprefix lxdialog/, \ | ||||||
|  | 		     checklist.o inputbox.o menubox.o textbox.o util.o yesno.o) | ||||||
|  | mconf-objs	:= mconf.o $(lxdialog) $(common-objs) | ||||||
|  |  | ||||||
| conf-objs	:= conf.o zconf.tab.o | HOSTLDLIBS_mconf = $(shell . $(obj)/mconf-cfg && echo $$libs) | ||||||
| mconf-objs	:= mconf.o zconf.tab.o | $(foreach f, mconf.o $(lxdialog), \ | ||||||
|  |   $(eval HOSTCFLAGS_$f = $$(shell . $(obj)/mconf-cfg && echo $$$$cflags))) | ||||||
|  |  | ||||||
|  | $(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/mconf-cfg | ||||||
|  |  | ||||||
|  | # qconf: Used for the xconfig target based on Qt | ||||||
|  | hostprogs-y	+= qconf | ||||||
| qconf-cxxobjs	:= qconf.o | qconf-cxxobjs	:= qconf.o | ||||||
| qconf-objs	:= zconf.tab.o | qconf-objs	:= images.o $(common-objs) | ||||||
|  |  | ||||||
| lxdialog-objs := \ | HOSTLDLIBS_qconf	= $(shell . $(obj)/qconf-cfg && echo $$libs) | ||||||
| 	lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o \ | HOSTCXXFLAGS_qconf.o	= $(shell . $(obj)/qconf-cfg && echo $$cflags) | ||||||
| 	lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o |  | ||||||
|  |  | ||||||
| clean-files	:= zconf.tab.c zconf.lex.c zconf.hash.c | $(obj)/qconf.o: $(obj)/qconf-cfg $(obj)/qconf.moc | ||||||
| # Remove qconf junk files |  | ||||||
| clean-files	+= $(qconf-cxxobjs) qconf.moc .tmp_qtcheck qconf |  | ||||||
|  |  | ||||||
| all: conf mconf | quiet_cmd_moc = MOC     $@ | ||||||
|  |       cmd_moc = $(shell . $(obj)/qconf-cfg && echo $$moc) -i $< -o $@ | ||||||
|  |  | ||||||
| conf: $(conf-objs) | $(obj)/%.moc: $(src)/%.h $(obj)/qconf-cfg | ||||||
| mconf: $(mconf-objs) $(lxdialog-objs) | 	$(call cmd,moc) | ||||||
| 	$(CC) -o $@ $^ $(call check_lxdialog,ldflags $(CC)) |  | ||||||
| qconf: $(qconf-cxxobjs) $(qconf-objs) |  | ||||||
| 	$(CXX) -o $@ $^ $(HOSTLOADLIBES_qconf) |  | ||||||
|  |  | ||||||
| clean: | # check if necessary packages are available, and configure build flags | ||||||
| 	rm -f *.o lxdialog/*.o $(clean-files) conf mconf | filechk_conf_cfg = $(CONFIG_SHELL) $< | ||||||
|  |  | ||||||
| zconf.tab.o: zconf.lex.c zconf.hash.c confdata.c | $(obj)/%conf-cfg: $(src)/%conf-cfg.sh FORCE | ||||||
|  | 	$(call filechk,conf_cfg) | ||||||
|  |  | ||||||
| kconfig_load.o: lkc_defs.h | clean-files += *conf-cfg | ||||||
|  |  | ||||||
| zconf.tab.c: zconf.y $(wildcard zconf.tab.c_shipped) | # =========================================================================== | ||||||
| zconf.lex.c: zconf.l $(wildcard zconf.lex.c_shipped) | # OpenWrt rules and final adjustments that need to be made after reading the | ||||||
| zconf.hash.c: zconf.gperf $(wildcard zconf.hash.c_shipped) | # full upstream Makefile | ||||||
|  |  | ||||||
| %.tab.c: %.y | FORCE: | ||||||
| 	cp $@_shipped $@ || bison -l -b $* -p $(notdir $*) $< |  | ||||||
|  | ifdef BUILD_SHIPPED_FILES | ||||||
|  | shipped-files := lexer.lex.c parser.tab.c parser.tab.h | ||||||
|  | clean-files += $(shipped-files) | ||||||
|  |  | ||||||
|  | .SECONDARY: $(shipped-files) | ||||||
|  |  | ||||||
|  | %.tab.c %.tab.h: %.y | ||||||
|  | 	bison -l -d -b $* $< | ||||||
|  |  | ||||||
| %.lex.c: %.l | %.lex.c: %.l | ||||||
| 	cp $@_shipped $@ || flex -L -P$(notdir $*) -o$@ $< | 	flex -L -o$@ $< | ||||||
|  |  | ||||||
| %.hash.c: %.gperf |  | ||||||
| 	cp $@_shipped $@ || gperf < $< > $@ |  | ||||||
|  |  | ||||||
| ifeq ($(MAKECMDGOALS),qconf) |  | ||||||
| qconf.o: .tmp_qtcheck |  | ||||||
| .tmp_qtcheck: Makefile |  | ||||||
| -include .tmp_qtcheck |  | ||||||
|  |  | ||||||
| # Qt needs some extra effort... |  | ||||||
| .tmp_qtcheck: |  | ||||||
| 	@set -e; echo "  CHECK   qt"; \ |  | ||||||
| 	if pkg-config --exists Qt5Core; then \ |  | ||||||
| 	    cflags="-std=c++11 -fPIC `pkg-config --cflags Qt5Core Qt5Gui Qt5Widgets`"; \ |  | ||||||
| 	    libs=`pkg-config --libs Qt5Core Qt5Gui Qt5Widgets`; \ |  | ||||||
| 	    moc=`pkg-config --variable=host_bins Qt5Core`/moc; \ |  | ||||||
| 	elif pkg-config --exists QtCore; then \ |  | ||||||
| 	    cflags=`pkg-config --cflags QtCore QtGui`; \ |  | ||||||
| 	    libs=`pkg-config --libs QtCore QtGui`; \ |  | ||||||
| 	    moc=`pkg-config --variable=moc_location QtCore`; \ |  | ||||||
| 	else \ |  | ||||||
| 	    echo >&2 "*"; \ |  | ||||||
| 	    echo >&2 "* Could not find Qt via pkg-config."; \ |  | ||||||
| 	    echo >&2 "* Please install either Qt 4.8 or 5.x. and make sure it's in PKG_CONFIG_PATH"; \ |  | ||||||
| 	    echo >&2 "*"; \ |  | ||||||
| 	    exit 1; \ |  | ||||||
| 	fi; \ |  | ||||||
| 	echo "KC_QT_CFLAGS=$$cflags" > $@; \ |  | ||||||
| 	echo "KC_QT_LIBS=$$libs" >> $@; \ |  | ||||||
| 	echo "KC_QT_MOC=$$moc" >> $@ |  | ||||||
| endif | endif | ||||||
|  |  | ||||||
| #Define compiler flags to build qconf | $(foreach f, mconf.o $(lxdialog), \ | ||||||
| HOSTLOADLIBES_qconf	= $(KC_QT_LIBS) |   $(eval $f: CFLAGS+=$$(HOSTCFLAGS_$f))) | ||||||
| HOSTCXXFLAGS_qconf.o	= $(KC_QT_CFLAGS) |  | ||||||
|  |  | ||||||
| qconf.o: qconf.moc | $(obj)/lexer.lex.o: CFLAGS += $(HOSTCFLAGS_lexer.lex.o) | ||||||
| qconf.o: CXXFLAGS+=$(HOSTCXXFLAGS_qconf.o) | $(obj)/parser.tab.o: CFLAGS += $(HOSTCFLAGS_parser.tab.o) | ||||||
|  | $(obj)/qconf.o: CXXFLAGS+=$(HOSTCXXFLAGS_qconf.o) | ||||||
|  |  | ||||||
| moc = $(KC_QT_MOC) -i $< -o $@ | conf: $(conf-objs) | ||||||
|  |  | ||||||
| %.moc: %.h .tmp_qtcheck | # The *conf-cfg file is used (then filtered out) as the first prerequisite to | ||||||
| 	$(call moc) | # avoid sourcing it before the script is built, when trying to compute CFLAGS | ||||||
|  | # for the actual first prerequisite.  This avoids errors like: | ||||||
|  | # '/bin/sh: ./mconf-cfg: No such file or directory' | ||||||
|  | mconf: mconf-cfg $(mconf-objs) | ||||||
|  | 	$(CC) -o $@ $(filter-out mconf-cfg,$^) $(HOSTLDLIBS_mconf) | ||||||
|  |  | ||||||
|  | qconf: qconf-cfg $(qconf-cxxobjs) $(qconf-objs) | ||||||
|  | 	$(CXX) -o $@ $(filter-out qconf-cfg,$^) $(HOSTLDLIBS_qconf) | ||||||
|   | |||||||
| @@ -1,2 +1,24 @@ | |||||||
| These files were taken from the Linux 3.9 Kernel | These files were taken from the Linux Kernel Configuration System at commit | ||||||
| Configuration System and modified for the OpenWrt Buildroot. | 089b7d890f972f6b649fedc9259f6b93a18fb970 (Feb 4, 2020) and modified for the | ||||||
|  | OpenWrt Buildroot: | ||||||
|  |  - removed nconf, gconf, tests and kernel configuration targets | ||||||
|  |  - adjusted the Makefile to compile outside the kernel | ||||||
|  |  - always use default file when running make all{no,mod,yes}config | ||||||
|  |  - added a 'reset' command to reset config when the target changes | ||||||
|  |  - allow config reading from & writing to a different file | ||||||
|  |  - allow 'source' command to use globs to include multiple files | ||||||
|  |  - don't write auto.conf and other files under include/ directory | ||||||
|  |  - reverted a commit to allow use of '/' & '.' in unquoted config symbols. | ||||||
|  |    There are too many of those in OpenWrt right now. | ||||||
|  |  - reverted a commit that was issuing a warning when there were more than | ||||||
|  |    one help text.  This is used in a few packages to use different texts | ||||||
|  |    for the menuconfig help, and the ipkg package description. | ||||||
|  |  - reverted an upstream change that avoids writing symbols that are not | ||||||
|  |    visible to .config, which breaks OpenWrt busybox's '.config' generation | ||||||
|  |    logic. | ||||||
|  |  - use pre-built *.lex.c *.tab.[ch] files by default, to avoid depending on | ||||||
|  |    flex & bison.  Rebuild/remove these files only if running make with | ||||||
|  |    BUILD_SHIPPED_FILES defined | ||||||
|  |  | ||||||
|  | For a full list of changes, see the repository at: | ||||||
|  | https://github.com/cotequeiroz/linux/commits/openwrt/scripts/kconfig | ||||||
|   | |||||||
| @@ -1,9 +1,8 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0 | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  * Released under the terms of the GNU GPL v2.0. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <locale.h> |  | ||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
| #include <limits.h> | #include <limits.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| @@ -20,11 +19,10 @@ | |||||||
|  |  | ||||||
| static void conf(struct menu *menu); | static void conf(struct menu *menu); | ||||||
| static void check_conf(struct menu *menu); | static void check_conf(struct menu *menu); | ||||||
| static void xfgets(char *str, int size, FILE *in); |  | ||||||
|  |  | ||||||
| enum input_mode { | enum input_mode { | ||||||
| 	oldaskconfig, | 	oldaskconfig, | ||||||
| 	silentoldconfig, | 	syncconfig, | ||||||
| 	oldconfig, | 	oldconfig, | ||||||
| 	allnoconfig, | 	allnoconfig, | ||||||
| 	allyesconfig, | 	allyesconfig, | ||||||
| @@ -34,12 +32,15 @@ enum input_mode { | |||||||
| 	defconfig, | 	defconfig, | ||||||
| 	savedefconfig, | 	savedefconfig, | ||||||
| 	listnewconfig, | 	listnewconfig, | ||||||
|  | 	helpnewconfig, | ||||||
| 	olddefconfig, | 	olddefconfig, | ||||||
| } input_mode = oldaskconfig; | 	yes2modconfig, | ||||||
|  | 	mod2yesconfig, | ||||||
|  | }; | ||||||
|  | static enum input_mode input_mode = oldaskconfig; | ||||||
|  |  | ||||||
| static int indent = 1; | static int indent = 1; | ||||||
| static int tty_stdio; | static int tty_stdio; | ||||||
| static int valid_stdin = 1; |  | ||||||
| static int sync_kconfig; | static int sync_kconfig; | ||||||
| static int conf_cnt; | static int conf_cnt; | ||||||
| static char line[PATH_MAX]; | static char line[PATH_MAX]; | ||||||
| @@ -72,14 +73,14 @@ static void strip(char *str) | |||||||
| 		*p-- = 0; | 		*p-- = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void check_stdin(void) | /* Helper function to facilitate fgets() by Jean Sacren. */ | ||||||
|  | static void xfgets(char *str, int size, FILE *in) | ||||||
| { | { | ||||||
| 	if (!valid_stdin) { | 	if (!fgets(str, size, in)) | ||||||
| 	        printf("%s",_("aborted!\n\n")); | 		fprintf(stderr, "\nError in reading or end of file.\n"); | ||||||
| 		printf("%s",_("Console input/output is redirected. ")); |  | ||||||
| 		printf("%s",_("Run 'make oldconfig' to update configuration.\n\n")); | 	if (!tty_stdio) | ||||||
| 		exit(1); | 		printf("%s", str); | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static int conf_askvalue(struct symbol *sym, const char *def) | static int conf_askvalue(struct symbol *sym, const char *def) | ||||||
| @@ -87,12 +88,12 @@ static int conf_askvalue(struct symbol *sym, const char *def) | |||||||
| 	enum symbol_type type = sym_get_type(sym); | 	enum symbol_type type = sym_get_type(sym); | ||||||
|  |  | ||||||
| 	if (!sym_has_value(sym)) | 	if (!sym_has_value(sym)) | ||||||
| 	        printf("%s",_("(NEW) ")); | 		printf("(NEW) "); | ||||||
|  |  | ||||||
| 	line[0] = '\n'; | 	line[0] = '\n'; | ||||||
| 	line[1] = 0; | 	line[1] = 0; | ||||||
|  |  | ||||||
| 	if (!sym_is_changable(sym)) { | 	if (!sym_is_changeable(sym)) { | ||||||
| 		printf("%s\n", def); | 		printf("%s\n", def); | ||||||
| 		line[0] = '\n'; | 		line[0] = '\n'; | ||||||
| 		line[1] = 0; | 		line[1] = 0; | ||||||
| @@ -101,18 +102,15 @@ static int conf_askvalue(struct symbol *sym, const char *def) | |||||||
|  |  | ||||||
| 	switch (input_mode) { | 	switch (input_mode) { | ||||||
| 	case oldconfig: | 	case oldconfig: | ||||||
| 	case silentoldconfig: | 	case syncconfig: | ||||||
| 		if (sym_has_value(sym)) { | 		if (sym_has_value(sym)) { | ||||||
| 			printf("%s\n", def); | 			printf("%s\n", def); | ||||||
| 			return 0; | 			return 0; | ||||||
| 		} | 		} | ||||||
| 		check_stdin(); |  | ||||||
| 		/* fall through */ | 		/* fall through */ | ||||||
| 	case oldaskconfig: | 	case oldaskconfig: | ||||||
| 		fflush(stdout); | 		fflush(stdout); | ||||||
| 		xfgets(line, sizeof(line), stdin); | 		xfgets(line, sizeof(line), stdin); | ||||||
| 		if (!tty_stdio) |  | ||||||
| 			printf("\n"); |  | ||||||
| 		return 1; | 		return 1; | ||||||
| 	default: | 	default: | ||||||
| 		break; | 		break; | ||||||
| @@ -137,7 +135,7 @@ static int conf_string(struct menu *menu) | |||||||
| 	const char *def; | 	const char *def; | ||||||
|  |  | ||||||
| 	while (1) { | 	while (1) { | ||||||
| 		printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); | 		printf("%*s%s ", indent - 1, "", menu->prompt->text); | ||||||
| 		printf("(%s) ", sym->name); | 		printf("(%s) ", sym->name); | ||||||
| 		def = sym_get_string_value(sym); | 		def = sym_get_string_value(sym); | ||||||
| 		if (sym_get_string_value(sym)) | 		if (sym_get_string_value(sym)) | ||||||
| @@ -170,7 +168,7 @@ static int conf_sym(struct menu *menu) | |||||||
| 	tristate oldval, newval; | 	tristate oldval, newval; | ||||||
|  |  | ||||||
| 	while (1) { | 	while (1) { | ||||||
| 		printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); | 		printf("%*s%s ", indent - 1, "", menu->prompt->text); | ||||||
| 		if (sym->name) | 		if (sym->name) | ||||||
| 			printf("(%s) ", sym->name); | 			printf("(%s) ", sym->name); | ||||||
| 		putchar('['); | 		putchar('['); | ||||||
| @@ -192,9 +190,7 @@ static int conf_sym(struct menu *menu) | |||||||
| 			printf("/m"); | 			printf("/m"); | ||||||
| 		if (oldval != yes && sym_tristate_within_range(sym, yes)) | 		if (oldval != yes && sym_tristate_within_range(sym, yes)) | ||||||
| 			printf("/y"); | 			printf("/y"); | ||||||
| 		if (menu_has_help(menu)) | 		printf("/?] "); | ||||||
| 			printf("/?"); |  | ||||||
| 		printf("] "); |  | ||||||
| 		if (!conf_askvalue(sym, sym_get_string_value(sym))) | 		if (!conf_askvalue(sym, sym_get_string_value(sym))) | ||||||
| 			return 0; | 			return 0; | ||||||
| 		strip(line); | 		strip(line); | ||||||
| @@ -241,7 +237,7 @@ static int conf_choice(struct menu *menu) | |||||||
|  |  | ||||||
| 	sym = menu->sym; | 	sym = menu->sym; | ||||||
| 	is_new = !sym_has_value(sym); | 	is_new = !sym_has_value(sym); | ||||||
| 	if (sym_is_changable(sym)) { | 	if (sym_is_changeable(sym)) { | ||||||
| 		conf_sym(menu); | 		conf_sym(menu); | ||||||
| 		sym_calc_value(sym); | 		sym_calc_value(sym); | ||||||
| 		switch (sym_get_tristate_value(sym)) { | 		switch (sym_get_tristate_value(sym)) { | ||||||
| @@ -257,7 +253,7 @@ static int conf_choice(struct menu *menu) | |||||||
| 		case no: | 		case no: | ||||||
| 			return 1; | 			return 1; | ||||||
| 		case mod: | 		case mod: | ||||||
| 			printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); | 			printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); | ||||||
| 			return 0; | 			return 0; | ||||||
| 		case yes: | 		case yes: | ||||||
| 			break; | 			break; | ||||||
| @@ -267,7 +263,7 @@ static int conf_choice(struct menu *menu) | |||||||
| 	while (1) { | 	while (1) { | ||||||
| 		int cnt, def; | 		int cnt, def; | ||||||
|  |  | ||||||
| 		printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); | 		printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); | ||||||
| 		def_sym = sym_get_choice_value(sym); | 		def_sym = sym_get_choice_value(sym); | ||||||
| 		cnt = def = 0; | 		cnt = def = 0; | ||||||
| 		line[0] = 0; | 		line[0] = 0; | ||||||
| @@ -275,7 +271,7 @@ static int conf_choice(struct menu *menu) | |||||||
| 			if (!menu_is_visible(child)) | 			if (!menu_is_visible(child)) | ||||||
| 				continue; | 				continue; | ||||||
| 			if (!child->sym) { | 			if (!child->sym) { | ||||||
| 				printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); | 				printf("%*c %s\n", indent, '*', menu_get_prompt(child)); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			cnt++; | 			cnt++; | ||||||
| @@ -284,31 +280,27 @@ static int conf_choice(struct menu *menu) | |||||||
| 				printf("%*c", indent, '>'); | 				printf("%*c", indent, '>'); | ||||||
| 			} else | 			} else | ||||||
| 				printf("%*c", indent, ' '); | 				printf("%*c", indent, ' '); | ||||||
| 			printf(" %d. %s", cnt, _(menu_get_prompt(child))); | 			printf(" %d. %s", cnt, menu_get_prompt(child)); | ||||||
| 			if (child->sym->name) | 			if (child->sym->name) | ||||||
| 				printf(" (%s)", child->sym->name); | 				printf(" (%s)", child->sym->name); | ||||||
| 			if (!sym_has_value(child->sym)) | 			if (!sym_has_value(child->sym)) | ||||||
| 			        printf("%s",_(" (NEW)")); | 				printf(" (NEW)"); | ||||||
| 			printf("\n"); | 			printf("\n"); | ||||||
| 		} | 		} | ||||||
| 		printf(_("%*schoice"), indent - 1, ""); | 		printf("%*schoice", indent - 1, ""); | ||||||
| 		if (cnt == 1) { | 		if (cnt == 1) { | ||||||
| 			printf("[1]: 1\n"); | 			printf("[1]: 1\n"); | ||||||
| 			goto conf_childs; | 			goto conf_childs; | ||||||
| 		} | 		} | ||||||
| 		printf("[1-%d", cnt); | 		printf("[1-%d?]: ", cnt); | ||||||
| 		if (menu_has_help(menu)) |  | ||||||
| 			printf("?"); |  | ||||||
| 		printf("]: "); |  | ||||||
| 		switch (input_mode) { | 		switch (input_mode) { | ||||||
| 		case oldconfig: | 		case oldconfig: | ||||||
| 		case silentoldconfig: | 		case syncconfig: | ||||||
| 			if (!is_new) { | 			if (!is_new) { | ||||||
| 				cnt = def; | 				cnt = def; | ||||||
| 				printf("%d\n", cnt); | 				printf("%d\n", cnt); | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 			check_stdin(); |  | ||||||
| 			/* fall through */ | 			/* fall through */ | ||||||
| 		case oldaskconfig: | 		case oldaskconfig: | ||||||
| 			fflush(stdout); | 			fflush(stdout); | ||||||
| @@ -368,10 +360,11 @@ static void conf(struct menu *menu) | |||||||
|  |  | ||||||
| 		switch (prop->type) { | 		switch (prop->type) { | ||||||
| 		case P_MENU: | 		case P_MENU: | ||||||
| 			if ((input_mode == silentoldconfig || | 			/* | ||||||
| 			     input_mode == listnewconfig || | 			 * Except in oldaskconfig mode, we show only menus that | ||||||
| 			     input_mode == olddefconfig) && | 			 * contain new symbols. | ||||||
| 			    rootEntry != menu) { | 			 */ | ||||||
|  | 			if (input_mode != oldaskconfig && rootEntry != menu) { | ||||||
| 				check_conf(menu); | 				check_conf(menu); | ||||||
| 				return; | 				return; | ||||||
| 			} | 			} | ||||||
| @@ -381,7 +374,7 @@ static void conf(struct menu *menu) | |||||||
| 			if (prompt) | 			if (prompt) | ||||||
| 				printf("%*c\n%*c %s\n%*c\n", | 				printf("%*c\n%*c %s\n%*c\n", | ||||||
| 					indent, '*', | 					indent, '*', | ||||||
| 					indent, '*', _(prompt), | 					indent, '*', prompt, | ||||||
| 					indent, '*'); | 					indent, '*'); | ||||||
| 		default: | 		default: | ||||||
| 			; | 			; | ||||||
| @@ -428,15 +421,30 @@ static void check_conf(struct menu *menu) | |||||||
|  |  | ||||||
| 	sym = menu->sym; | 	sym = menu->sym; | ||||||
| 	if (sym && !sym_has_value(sym)) { | 	if (sym && !sym_has_value(sym)) { | ||||||
| 		if (sym_is_changable(sym) || | 		if (sym_is_changeable(sym) || | ||||||
| 		    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { | 		    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { | ||||||
| 			if (input_mode == listnewconfig) { | 			if (input_mode == listnewconfig) { | ||||||
| 				if (sym->name && !sym_is_choice_value(sym)) { | 				if (sym->name) { | ||||||
| 					printf("%s%s\n", CONFIG_, sym->name); | 					const char *str; | ||||||
|  |  | ||||||
|  | 					if (sym->type == S_STRING) { | ||||||
|  | 						str = sym_get_string_value(sym); | ||||||
|  | 						str = sym_escape_string_value(str); | ||||||
|  | 						printf("%s%s=%s\n", CONFIG_, sym->name, str); | ||||||
|  | 						free((void *)str); | ||||||
|  | 					} else { | ||||||
|  | 						str = sym_get_string_value(sym); | ||||||
|  | 						printf("%s%s=%s\n", CONFIG_, sym->name, str); | ||||||
| 					} | 					} | ||||||
| 			} else if (input_mode != olddefconfig) { | 				} | ||||||
|  | 			} else if (input_mode == helpnewconfig) { | ||||||
|  | 				printf("-----\n"); | ||||||
|  | 				print_help(menu); | ||||||
|  | 				printf("-----\n"); | ||||||
|  |  | ||||||
|  | 			} else { | ||||||
| 				if (!conf_cnt++) | 				if (!conf_cnt++) | ||||||
| 				        printf("%s",_("*\n* Restart config...\n*\n")); | 					printf("*\n* Restart config...\n*\n"); | ||||||
| 				rootEntry = menu_get_parent_menu(menu); | 				rootEntry = menu_get_parent_menu(menu); | ||||||
| 				conf(rootEntry); | 				conf(rootEntry); | ||||||
| 			} | 			} | ||||||
| @@ -450,8 +458,8 @@ static void check_conf(struct menu *menu) | |||||||
| static struct option long_opts[] = { | static struct option long_opts[] = { | ||||||
| 	{"oldaskconfig",    no_argument,       NULL, oldaskconfig}, | 	{"oldaskconfig",    no_argument,       NULL, oldaskconfig}, | ||||||
| 	{"oldconfig",       no_argument,       NULL, oldconfig}, | 	{"oldconfig",       no_argument,       NULL, oldconfig}, | ||||||
| 	{"silentoldconfig", no_argument,       NULL, silentoldconfig}, | 	{"syncconfig",      no_argument,       NULL, syncconfig}, | ||||||
| 	{"defconfig",       optional_argument, NULL, defconfig}, | 	{"defconfig",       required_argument, NULL, defconfig}, | ||||||
| 	{"savedefconfig",   required_argument, NULL, savedefconfig}, | 	{"savedefconfig",   required_argument, NULL, savedefconfig}, | ||||||
| 	{"allnoconfig",     no_argument,       NULL, allnoconfig}, | 	{"allnoconfig",     no_argument,       NULL, allnoconfig}, | ||||||
| 	{"allyesconfig",    no_argument,       NULL, allyesconfig}, | 	{"allyesconfig",    no_argument,       NULL, allyesconfig}, | ||||||
| @@ -459,13 +467,10 @@ static struct option long_opts[] = { | |||||||
| 	{"alldefconfig",    no_argument,       NULL, alldefconfig}, | 	{"alldefconfig",    no_argument,       NULL, alldefconfig}, | ||||||
| 	{"randconfig",      no_argument,       NULL, randconfig}, | 	{"randconfig",      no_argument,       NULL, randconfig}, | ||||||
| 	{"listnewconfig",   no_argument,       NULL, listnewconfig}, | 	{"listnewconfig",   no_argument,       NULL, listnewconfig}, | ||||||
|  | 	{"helpnewconfig",   no_argument,       NULL, helpnewconfig}, | ||||||
| 	{"olddefconfig",    no_argument,       NULL, olddefconfig}, | 	{"olddefconfig",    no_argument,       NULL, olddefconfig}, | ||||||
| 	/* | 	{"yes2modconfig",   no_argument,       NULL, yes2modconfig}, | ||||||
| 	 * oldnoconfig is an alias of olddefconfig, because people already | 	{"mod2yesconfig",   no_argument,       NULL, mod2yesconfig}, | ||||||
| 	 * are dependent on its behavior(sets new symbols to their default |  | ||||||
| 	 * value but not 'n') with the counter-intuitive name. |  | ||||||
| 	 */ |  | ||||||
| 	{"oldnoconfig",     no_argument,       NULL, olddefconfig}, |  | ||||||
| 	{NULL, 0, NULL, 0} | 	{NULL, 0, NULL, 0} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -475,11 +480,12 @@ static void conf_usage(const char *progname) | |||||||
| 	printf("Usage: %s [-s] [option] <kconfig-file>\n", progname); | 	printf("Usage: %s [-s] [option] <kconfig-file>\n", progname); | ||||||
| 	printf("[option] is _one_ of the following:\n"); | 	printf("[option] is _one_ of the following:\n"); | ||||||
| 	printf("  --listnewconfig         List new options\n"); | 	printf("  --listnewconfig         List new options\n"); | ||||||
|  | 	printf("  --helpnewconfig         List new options and help text\n"); | ||||||
| 	printf("  --oldaskconfig          Start a new configuration using a line-oriented program\n"); | 	printf("  --oldaskconfig          Start a new configuration using a line-oriented program\n"); | ||||||
| 	printf("  --oldconfig             Update a configuration using a provided .config as base\n"); | 	printf("  --oldconfig             Update a configuration using a provided .config as base\n"); | ||||||
| 	printf("  --silentoldconfig       Same as oldconfig, but quietly, additionally update deps\n"); | 	printf("  --syncconfig            Similar to oldconfig but generates configuration in\n" | ||||||
| 	printf("  --olddefconfig          Same as silentoldconfig but sets new symbols to their default value\n"); | 	       "                          include/{generated/,config/}\n"); | ||||||
| 	printf("  --oldnoconfig           An alias of olddefconfig\n"); | 	printf("  --olddefconfig          Same as oldconfig but sets new symbols to their default value\n"); | ||||||
| 	printf("  --defconfig <file>      New config with default defined in <file>\n"); | 	printf("  --defconfig <file>      New config with default defined in <file>\n"); | ||||||
| 	printf("  --savedefconfig <file>  Save the minimal current configuration to <file>\n"); | 	printf("  --savedefconfig <file>  Save the minimal current configuration to <file>\n"); | ||||||
| 	printf("  --allnoconfig           New config where all options are answered with no\n"); | 	printf("  --allnoconfig           New config where all options are answered with no\n"); | ||||||
| @@ -487,6 +493,8 @@ static void conf_usage(const char *progname) | |||||||
| 	printf("  --allmodconfig          New config where all options are answered with mod\n"); | 	printf("  --allmodconfig          New config where all options are answered with mod\n"); | ||||||
| 	printf("  --alldefconfig          New config with all symbols set to default\n"); | 	printf("  --alldefconfig          New config with all symbols set to default\n"); | ||||||
| 	printf("  --randconfig            New config with random answer to all options\n"); | 	printf("  --randconfig            New config with random answer to all options\n"); | ||||||
|  | 	printf("  --yes2modconfig         Change answers from yes to mod if possible\n"); | ||||||
|  | 	printf("  --mod2yesconfig         Change answers from mod to yes if possible\n"); | ||||||
| } | } | ||||||
|  |  | ||||||
| int main(int ac, char **av) | int main(int ac, char **av) | ||||||
| @@ -494,14 +502,10 @@ int main(int ac, char **av) | |||||||
| 	const char *progname = av[0]; | 	const char *progname = av[0]; | ||||||
| 	int opt; | 	int opt; | ||||||
| 	const char *name, *defconfig_file = NULL /* gcc uninit */; | 	const char *name, *defconfig_file = NULL /* gcc uninit */; | ||||||
| 	struct stat tmpstat; |  | ||||||
| 	const char *input_file = NULL, *output_file = NULL; | 	const char *input_file = NULL, *output_file = NULL; | ||||||
|  | 	int no_conf_write = 0; | ||||||
|  |  | ||||||
| 	setlocale(LC_ALL, ""); | 	tty_stdio = isatty(0) && isatty(1); | ||||||
| 	bindtextdomain(PACKAGE, LOCALEDIR); |  | ||||||
| 	textdomain(PACKAGE); |  | ||||||
|  |  | ||||||
| 	tty_stdio = isatty(0) && isatty(1) && isatty(2); |  | ||||||
|  |  | ||||||
| 	while ((opt = getopt_long(ac, av, "r:w:s", long_opts, NULL)) != -1) { | 	while ((opt = getopt_long(ac, av, "r:w:s", long_opts, NULL)) != -1) { | ||||||
| 		if (opt == 's') { | 		if (opt == 's') { | ||||||
| @@ -509,7 +513,12 @@ int main(int ac, char **av) | |||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 		switch (opt) { | 		switch (opt) { | ||||||
| 		case silentoldconfig: | 		case syncconfig: | ||||||
|  | 			/* | ||||||
|  | 			 * syncconfig is invoked during the build stage. | ||||||
|  | 			 * Suppress distracting "configuration written to ..." | ||||||
|  | 			 */ | ||||||
|  | 			conf_set_message_callback(NULL); | ||||||
| 			sync_kconfig = 1; | 			sync_kconfig = 1; | ||||||
| 			break; | 			break; | ||||||
| 		case defconfig: | 		case defconfig: | ||||||
| @@ -548,7 +557,10 @@ int main(int ac, char **av) | |||||||
| 		case allmodconfig: | 		case allmodconfig: | ||||||
| 		case alldefconfig: | 		case alldefconfig: | ||||||
| 		case listnewconfig: | 		case listnewconfig: | ||||||
|  | 		case helpnewconfig: | ||||||
| 		case olddefconfig: | 		case olddefconfig: | ||||||
|  | 		case yes2modconfig: | ||||||
|  | 		case mod2yesconfig: | ||||||
| 			break; | 			break; | ||||||
| 		case 'r': | 		case 'r': | ||||||
| 			input_file = optarg; | 			input_file = optarg; | ||||||
| @@ -564,43 +576,34 @@ int main(int ac, char **av) | |||||||
| 		input_mode = (enum input_mode)opt; | 		input_mode = (enum input_mode)opt; | ||||||
| 	} | 	} | ||||||
| 	if (ac == optind) { | 	if (ac == optind) { | ||||||
| 		printf(_("%s: Kconfig file missing\n"), av[0]); | 		fprintf(stderr, "%s: Kconfig file missing\n", av[0]); | ||||||
| 		conf_usage(progname); | 		conf_usage(progname); | ||||||
| 		exit(1); | 		exit(1); | ||||||
| 	} | 	} | ||||||
| 	name = av[optind]; | 	name = av[optind]; | ||||||
| 	conf_parse(name); | 	conf_parse(name); | ||||||
| 	//zconfdump(stdout); | 	//zconfdump(stdout); | ||||||
| 	if (sync_kconfig) { |  | ||||||
| 		name = conf_get_configname(); |  | ||||||
| 		if (stat(name, &tmpstat)) { |  | ||||||
| 			fprintf(stderr, _("***\n" |  | ||||||
| 				"*** Configuration file \"%s\" not found!\n" |  | ||||||
| 				"***\n" |  | ||||||
| 				"*** Please run some configurator (e.g. \"make oldconfig\" or\n" |  | ||||||
| 				"*** \"make menuconfig\" or \"make xconfig\").\n" |  | ||||||
| 				"***\n"), name); |  | ||||||
| 			exit(1); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	switch (input_mode) { | 	switch (input_mode) { | ||||||
| 	case defconfig: | 	case defconfig: | ||||||
| 		if (!defconfig_file) |  | ||||||
| 			defconfig_file = conf_get_default_confname(); |  | ||||||
| 		if (conf_read(defconfig_file)) { | 		if (conf_read(defconfig_file)) { | ||||||
| 			printf(_("***\n" | 			fprintf(stderr, | ||||||
|  | 				"***\n" | ||||||
| 				  "*** Can't find default configuration \"%s\"!\n" | 				  "*** Can't find default configuration \"%s\"!\n" | ||||||
| 				"***\n"), defconfig_file); | 				  "***\n", | ||||||
|  | 				defconfig_file); | ||||||
| 			exit(1); | 			exit(1); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case savedefconfig: | 	case savedefconfig: | ||||||
| 	case silentoldconfig: | 	case syncconfig: | ||||||
| 	case oldaskconfig: | 	case oldaskconfig: | ||||||
| 	case oldconfig: | 	case oldconfig: | ||||||
| 	case listnewconfig: | 	case listnewconfig: | ||||||
|  | 	case helpnewconfig: | ||||||
| 	case olddefconfig: | 	case olddefconfig: | ||||||
|  | 	case yes2modconfig: | ||||||
|  | 	case mod2yesconfig: | ||||||
| 	case allnoconfig: | 	case allnoconfig: | ||||||
| 	case allyesconfig: | 	case allyesconfig: | ||||||
| 	case allmodconfig: | 	case allmodconfig: | ||||||
| @@ -613,15 +616,15 @@ int main(int ac, char **av) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (sync_kconfig) { | 	if (sync_kconfig) { | ||||||
| 		if (conf_get_changed()) { |  | ||||||
| 		name = getenv("KCONFIG_NOSILENTUPDATE"); | 		name = getenv("KCONFIG_NOSILENTUPDATE"); | ||||||
| 		if (name && *name) { | 		if (name && *name) { | ||||||
|  | 			if (conf_get_changed()) { | ||||||
| 				fprintf(stderr, | 				fprintf(stderr, | ||||||
| 					_("\n*** The configuration requires explicit update.\n\n")); | 					"\n*** The configuration requires explicit update.\n\n"); | ||||||
| 				return 1; | 				return 1; | ||||||
| 			} | 			} | ||||||
|  | 			no_conf_write = 1; | ||||||
| 		} | 		} | ||||||
| 		valid_stdin = tty_stdio; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	switch (input_mode) { | 	switch (input_mode) { | ||||||
| @@ -646,58 +649,59 @@ int main(int ac, char **av) | |||||||
| 		break; | 		break; | ||||||
| 	case savedefconfig: | 	case savedefconfig: | ||||||
| 		break; | 		break; | ||||||
|  | 	case yes2modconfig: | ||||||
|  | 		conf_rewrite_mod_or_yes(def_y2m); | ||||||
|  | 		break; | ||||||
|  | 	case mod2yesconfig: | ||||||
|  | 		conf_rewrite_mod_or_yes(def_m2y); | ||||||
|  | 		break; | ||||||
| 	case oldaskconfig: | 	case oldaskconfig: | ||||||
| 		rootEntry = &rootmenu; | 		rootEntry = &rootmenu; | ||||||
| 		conf(&rootmenu); | 		conf(&rootmenu); | ||||||
| 		input_mode = silentoldconfig; | 		input_mode = oldconfig; | ||||||
| 		/* fall through */ | 		/* fall through */ | ||||||
| 	case oldconfig: | 	case oldconfig: | ||||||
| 	case listnewconfig: | 	case listnewconfig: | ||||||
| 	case olddefconfig: | 	case helpnewconfig: | ||||||
| 	case silentoldconfig: | 	case syncconfig: | ||||||
| 		/* Update until a loop caused no more changes */ | 		/* Update until a loop caused no more changes */ | ||||||
| 		do { | 		do { | ||||||
| 			conf_cnt = 0; | 			conf_cnt = 0; | ||||||
| 			check_conf(&rootmenu); | 			check_conf(&rootmenu); | ||||||
| 		} while (conf_cnt && | 		} while (conf_cnt); | ||||||
| 			 (input_mode != listnewconfig && | 		break; | ||||||
| 			  input_mode != olddefconfig)); | 	case olddefconfig: | ||||||
|  | 	default: | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (sync_kconfig) { | 	if (input_mode == savedefconfig) { | ||||||
| 		/* silentoldconfig is used during the build so we shall update autoconf. |  | ||||||
| 		 * All other commands are only used to generate a config. |  | ||||||
| 		 */ |  | ||||||
| 		if ((output_file || conf_get_changed()) && |  | ||||||
| 		    conf_write(output_file)) { |  | ||||||
| 			fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); |  | ||||||
| 			exit(1); |  | ||||||
| 		} |  | ||||||
| 		if (conf_write_autoconf()) { |  | ||||||
| 			fprintf(stderr, _("\n*** Error during update of the configuration.\n\n")); |  | ||||||
| 			return 1; |  | ||||||
| 		} |  | ||||||
| 	} else if (input_mode == savedefconfig) { |  | ||||||
| 		if (conf_write_defconfig(defconfig_file)) { | 		if (conf_write_defconfig(defconfig_file)) { | ||||||
| 			fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"), | 			fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n", | ||||||
| 				defconfig_file); | 				defconfig_file); | ||||||
| 			return 1; | 			return 1; | ||||||
| 		} | 		} | ||||||
| 	} else if (input_mode != listnewconfig) { | 	} else if (input_mode != listnewconfig && input_mode != helpnewconfig) { | ||||||
| 		if (conf_write(output_file)) { | 		if ((output_file || !no_conf_write) && | ||||||
| 			fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); | 		    conf_write(output_file)) { | ||||||
|  | 			fprintf(stderr, "\n*** Error during writing of the configuration.\n\n"); | ||||||
| 			exit(1); | 			exit(1); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		/* | ||||||
|  | 		 * Create auto.conf if it does not exist. | ||||||
|  | 		 * This prevents GNU Make 4.1 or older from emitting | ||||||
|  | 		 * "include/config/auto.conf: No such file or directory" | ||||||
|  | 		 * in the top-level Makefile | ||||||
|  | 		 * | ||||||
|  | 		 * syncconfig always creates or updates auto.conf because it is | ||||||
|  | 		 * used during the build. | ||||||
|  | 		 */ | ||||||
|  | 		if (conf_write_autoconf(sync_kconfig) && sync_kconfig) { | ||||||
|  | 			fprintf(stderr, | ||||||
|  | 				"\n*** Error during sync of the configuration.\n\n"); | ||||||
|  | 			return 1; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Helper function to facilitate fgets() by Jean Sacren. |  | ||||||
|  */ |  | ||||||
| void xfgets(char *str, int size, FILE *in) |  | ||||||
| { |  | ||||||
| 	if (fgets(str, size, in) == NULL) |  | ||||||
| 		fprintf(stderr, "\nError in reading or end of file.\n"); |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -1,12 +1,14 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0 | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  * Released under the terms of the GNU GPL v2.0. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | #include <sys/mman.h> | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
|  | #include <limits.h> | ||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| @@ -16,6 +18,151 @@ | |||||||
|  |  | ||||||
| #include "lkc.h" | #include "lkc.h" | ||||||
|  |  | ||||||
|  | /* return true if 'path' exists, false otherwise */ | ||||||
|  | static bool is_present(const char *path) | ||||||
|  | { | ||||||
|  | 	struct stat st; | ||||||
|  |  | ||||||
|  | 	return !stat(path, &st); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* return true if 'path' exists and it is a directory, false otherwise */ | ||||||
|  | static bool is_dir(const char *path) | ||||||
|  | { | ||||||
|  | 	struct stat st; | ||||||
|  |  | ||||||
|  | 	if (stat(path, &st)) | ||||||
|  | 		return 0; | ||||||
|  |  | ||||||
|  | 	return S_ISDIR(st.st_mode); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* return true if the given two files are the same, false otherwise */ | ||||||
|  | static bool is_same(const char *file1, const char *file2) | ||||||
|  | { | ||||||
|  | 	int fd1, fd2; | ||||||
|  | 	struct stat st1, st2; | ||||||
|  | 	void *map1, *map2; | ||||||
|  | 	bool ret = false; | ||||||
|  |  | ||||||
|  | 	fd1 = open(file1, O_RDONLY); | ||||||
|  | 	if (fd1 < 0) | ||||||
|  | 		return ret; | ||||||
|  |  | ||||||
|  | 	fd2 = open(file2, O_RDONLY); | ||||||
|  | 	if (fd2 < 0) | ||||||
|  | 		goto close1; | ||||||
|  |  | ||||||
|  | 	ret = fstat(fd1, &st1); | ||||||
|  | 	if (ret) | ||||||
|  | 		goto close2; | ||||||
|  | 	ret = fstat(fd2, &st2); | ||||||
|  | 	if (ret) | ||||||
|  | 		goto close2; | ||||||
|  |  | ||||||
|  | 	if (st1.st_size != st2.st_size) | ||||||
|  | 		goto close2; | ||||||
|  |  | ||||||
|  | 	map1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0); | ||||||
|  | 	if (map1 == MAP_FAILED) | ||||||
|  | 		goto close2; | ||||||
|  |  | ||||||
|  | 	map2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0); | ||||||
|  | 	if (map2 == MAP_FAILED) | ||||||
|  | 		goto close2; | ||||||
|  |  | ||||||
|  | 	if (bcmp(map1, map2, st1.st_size)) | ||||||
|  | 		goto close2; | ||||||
|  |  | ||||||
|  | 	ret = true; | ||||||
|  | close2: | ||||||
|  | 	close(fd2); | ||||||
|  | close1: | ||||||
|  | 	close(fd1); | ||||||
|  |  | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Create the parent directory of the given path. | ||||||
|  |  * | ||||||
|  |  * For example, if 'include/config/auto.conf' is given, create 'include/config'. | ||||||
|  |  */ | ||||||
|  | static int make_parent_dir(const char *path) | ||||||
|  | { | ||||||
|  | 	char tmp[PATH_MAX + 1]; | ||||||
|  | 	char *p; | ||||||
|  |  | ||||||
|  | 	strncpy(tmp, path, sizeof(tmp)); | ||||||
|  | 	tmp[sizeof(tmp) - 1] = 0; | ||||||
|  |  | ||||||
|  | 	/* Remove the base name. Just return if nothing is left */ | ||||||
|  | 	p = strrchr(tmp, '/'); | ||||||
|  | 	if (!p) | ||||||
|  | 		return 0; | ||||||
|  | 	*(p + 1) = 0; | ||||||
|  |  | ||||||
|  | 	/* Just in case it is an absolute path */ | ||||||
|  | 	p = tmp; | ||||||
|  | 	while (*p == '/') | ||||||
|  | 		p++; | ||||||
|  |  | ||||||
|  | 	while ((p = strchr(p, '/'))) { | ||||||
|  | 		*p = 0; | ||||||
|  |  | ||||||
|  | 		/* skip if the directory exists */ | ||||||
|  | 		if (!is_dir(tmp) && mkdir(tmp, 0755)) | ||||||
|  | 			return -1; | ||||||
|  |  | ||||||
|  | 		*p = '/'; | ||||||
|  | 		while (*p == '/') | ||||||
|  | 			p++; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char depfile_path[PATH_MAX]; | ||||||
|  | static size_t depfile_prefix_len; | ||||||
|  |  | ||||||
|  | /* touch depfile for symbol 'name' */ | ||||||
|  | static int conf_touch_dep(const char *name) | ||||||
|  | { | ||||||
|  | 	int fd, ret; | ||||||
|  | 	const char *s; | ||||||
|  | 	char *d, c; | ||||||
|  |  | ||||||
|  | 	/* check overflow: prefix + name + ".h" + '\0' must fit in buffer. */ | ||||||
|  | 	if (depfile_prefix_len + strlen(name) + 3 > sizeof(depfile_path)) | ||||||
|  | 		return -1; | ||||||
|  |  | ||||||
|  | 	d = depfile_path + depfile_prefix_len; | ||||||
|  | 	s = name; | ||||||
|  |  | ||||||
|  | 	while ((c = *s++)) | ||||||
|  | 		*d++ = (c == '_') ? '/' : tolower(c); | ||||||
|  | 	strcpy(d, ".h"); | ||||||
|  |  | ||||||
|  | 	/* Assume directory path already exists. */ | ||||||
|  | 	fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); | ||||||
|  | 	if (fd == -1) { | ||||||
|  | 		if (errno != ENOENT) | ||||||
|  | 			return -1; | ||||||
|  |  | ||||||
|  | 		ret = make_parent_dir(depfile_path); | ||||||
|  | 		if (ret) | ||||||
|  | 			return ret; | ||||||
|  |  | ||||||
|  | 		/* Try it again. */ | ||||||
|  | 		fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); | ||||||
|  | 		if (fd == -1) | ||||||
|  | 			return -1; | ||||||
|  | 	} | ||||||
|  | 	close(fd); | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| struct conf_printer { | struct conf_printer { | ||||||
| 	void (*print_symbol)(FILE *, struct symbol *, const char *, void *); | 	void (*print_symbol)(FILE *, struct symbol *, const char *, void *); | ||||||
| 	void (*print_comment)(FILE *, const char *, void *); | 	void (*print_comment)(FILE *, const char *, void *); | ||||||
| @@ -28,9 +175,7 @@ static void conf_message(const char *fmt, ...) | |||||||
| 	__attribute__ ((format (printf, 1, 2))); | 	__attribute__ ((format (printf, 1, 2))); | ||||||
|  |  | ||||||
| static const char *conf_filename; | static const char *conf_filename; | ||||||
| static int conf_lineno, conf_warnings, conf_unsaved; | static int conf_lineno, conf_warnings; | ||||||
|  |  | ||||||
| const char conf_defname[] = "arch/$ARCH/defconfig"; |  | ||||||
|  |  | ||||||
| static void conf_warning(const char *fmt, ...) | static void conf_warning(const char *fmt, ...) | ||||||
| { | { | ||||||
| @@ -43,16 +188,16 @@ static void conf_warning(const char *fmt, ...) | |||||||
| 	conf_warnings++; | 	conf_warnings++; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void conf_default_message_callback(const char *fmt, va_list ap) | static void conf_default_message_callback(const char *s) | ||||||
| { | { | ||||||
| 	printf("#\n# "); | 	printf("#\n# "); | ||||||
| 	vprintf(fmt, ap); | 	printf("%s", s); | ||||||
| 	printf("\n#\n"); | 	printf("\n#\n"); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void (*conf_message_callback) (const char *fmt, va_list ap) = | static void (*conf_message_callback)(const char *s) = | ||||||
| 	conf_default_message_callback; | 	conf_default_message_callback; | ||||||
| void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) | void conf_set_message_callback(void (*fn)(const char *s)) | ||||||
| { | { | ||||||
| 	conf_message_callback = fn; | 	conf_message_callback = fn; | ||||||
| } | } | ||||||
| @@ -60,10 +205,15 @@ void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) | |||||||
| static void conf_message(const char *fmt, ...) | static void conf_message(const char *fmt, ...) | ||||||
| { | { | ||||||
| 	va_list ap; | 	va_list ap; | ||||||
|  | 	char buf[4096]; | ||||||
|  |  | ||||||
|  | 	if (!conf_message_callback) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
| 	va_start(ap, fmt); | 	va_start(ap, fmt); | ||||||
| 	if (conf_message_callback) |  | ||||||
| 		conf_message_callback(fmt, ap); | 	vsnprintf(buf, sizeof(buf), fmt, ap); | ||||||
|  | 	conf_message_callback(buf); | ||||||
| 	va_end(ap); | 	va_end(ap); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -74,55 +224,13 @@ const char *conf_get_configname(void) | |||||||
| 	return name ? name : ".config"; | 	return name ? name : ".config"; | ||||||
| } | } | ||||||
|  |  | ||||||
| const char *conf_get_autoconfig_name(void) | static const char *conf_get_autoconfig_name(void) | ||||||
| { | { | ||||||
| 	char *name = getenv("KCONFIG_AUTOCONFIG"); | 	char *name = getenv("KCONFIG_AUTOCONFIG"); | ||||||
|  |  | ||||||
| 	return name ? name : "include/config/auto.conf"; | 	return name ? name : "include/config/auto.conf"; | ||||||
| } | } | ||||||
|  |  | ||||||
| static char *conf_expand_value(const char *in) |  | ||||||
| { |  | ||||||
| 	struct symbol *sym; |  | ||||||
| 	const char *src; |  | ||||||
| 	static char res_value[SYMBOL_MAXLENGTH]; |  | ||||||
| 	char *dst, name[SYMBOL_MAXLENGTH]; |  | ||||||
|  |  | ||||||
| 	res_value[0] = 0; |  | ||||||
| 	dst = name; |  | ||||||
| 	while ((src = strchr(in, '$'))) { |  | ||||||
| 		strncat(res_value, in, src - in); |  | ||||||
| 		src++; |  | ||||||
| 		dst = name; |  | ||||||
| 		while (isalnum(*src) || *src == '_') |  | ||||||
| 			*dst++ = *src++; |  | ||||||
| 		*dst = 0; |  | ||||||
| 		sym = sym_lookup(name, 0); |  | ||||||
| 		sym_calc_value(sym); |  | ||||||
| 		strcat(res_value, sym_get_string_value(sym)); |  | ||||||
| 		in = src; |  | ||||||
| 	} |  | ||||||
| 	strcat(res_value, in); |  | ||||||
|  |  | ||||||
| 	return res_value; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| char *conf_get_default_confname(void) |  | ||||||
| { |  | ||||||
| 	struct stat buf; |  | ||||||
| 	static char fullname[PATH_MAX+1]; |  | ||||||
| 	char *env, *name; |  | ||||||
|  |  | ||||||
| 	name = conf_expand_value(conf_defname); |  | ||||||
| 	env = getenv(SRCTREE); |  | ||||||
| 	if (env) { |  | ||||||
| 		sprintf(fullname, "%s/%s", env, name); |  | ||||||
| 		if (!stat(fullname, &buf)) |  | ||||||
| 			return fullname; |  | ||||||
| 	} |  | ||||||
| 	return name; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) | static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) | ||||||
| { | { | ||||||
| 	char *p2; | 	char *p2; | ||||||
| @@ -150,14 +258,6 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) | |||||||
| 			conf_warning("symbol value '%s' invalid for %s", | 			conf_warning("symbol value '%s' invalid for %s", | ||||||
| 				     p, sym->name); | 				     p, sym->name); | ||||||
| 		return 1; | 		return 1; | ||||||
| 	case S_OTHER: |  | ||||||
| 		if (*p != '"') { |  | ||||||
| 			for (p2 = p; *p2 && !isspace(*p2); p2++) |  | ||||||
| 				; |  | ||||||
| 			sym->type = S_STRING; |  | ||||||
| 			goto done; |  | ||||||
| 		} |  | ||||||
| 		/* fall through */ |  | ||||||
| 	case S_STRING: | 	case S_STRING: | ||||||
| 		if (*p++ != '"') | 		if (*p++ != '"') | ||||||
| 			break; | 			break; | ||||||
| @@ -176,9 +276,8 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) | |||||||
| 		/* fall through */ | 		/* fall through */ | ||||||
| 	case S_INT: | 	case S_INT: | ||||||
| 	case S_HEX: | 	case S_HEX: | ||||||
| 	done: |  | ||||||
| 		if (sym_string_valid(sym, p)) { | 		if (sym_string_valid(sym, p)) { | ||||||
| 			sym->def[def].val = strdup(p); | 			sym->def[def].val = xstrdup(p); | ||||||
| 			sym->flags |= def_flags; | 			sym->flags |= def_flags; | ||||||
| 		} else { | 		} else { | ||||||
| 			if (def != S_DEF_AUTO) | 			if (def != S_DEF_AUTO) | ||||||
| @@ -201,7 +300,7 @@ static int add_byte(int c, char **lineptr, size_t slen, size_t *n) | |||||||
| 	if (new_size > *n) { | 	if (new_size > *n) { | ||||||
| 		new_size += LINE_GROWTH - 1; | 		new_size += LINE_GROWTH - 1; | ||||||
| 		new_size *= 2; | 		new_size *= 2; | ||||||
| 		nline = realloc(*lineptr, new_size); | 		nline = xrealloc(*lineptr, new_size); | ||||||
| 		if (!nline) | 		if (!nline) | ||||||
| 			return -1; | 			return -1; | ||||||
|  |  | ||||||
| @@ -299,10 +398,11 @@ int conf_read_simple(const char *name, int def) | |||||||
| 			if (expr_calc_value(prop->visible.expr) == no || | 			if (expr_calc_value(prop->visible.expr) == no || | ||||||
| 			    prop->expr->type != E_SYMBOL) | 			    prop->expr->type != E_SYMBOL) | ||||||
| 				continue; | 				continue; | ||||||
| 			name = conf_expand_value(prop->expr->left.sym->name); | 			sym_calc_value(prop->expr->left.sym); | ||||||
|  | 			name = sym_get_string_value(prop->expr->left.sym); | ||||||
| 			in = zconf_fopen(name); | 			in = zconf_fopen(name); | ||||||
| 			if (in) { | 			if (in) { | ||||||
| 				conf_message(_("using defaults found in %s"), | 				conf_message("using defaults found in %s", | ||||||
| 					 name); | 					 name); | ||||||
| 				goto load; | 				goto load; | ||||||
| 			} | 			} | ||||||
| @@ -315,7 +415,6 @@ load: | |||||||
| 	conf_filename = name; | 	conf_filename = name; | ||||||
| 	conf_lineno = 0; | 	conf_lineno = 0; | ||||||
| 	conf_warnings = 0; | 	conf_warnings = 0; | ||||||
| 	conf_unsaved = 0; |  | ||||||
|  |  | ||||||
| 	def_flags = SYMBOL_DEF << def; | 	def_flags = SYMBOL_DEF << def; | ||||||
| 	conf_reset(def); | 	conf_reset(def); | ||||||
| @@ -336,7 +435,7 @@ load: | |||||||
| 				sym = sym_find(line + 2 + strlen(CONFIG_)); | 				sym = sym_find(line + 2 + strlen(CONFIG_)); | ||||||
| 				if (!sym) { | 				if (!sym) { | ||||||
| 					sym_add_change_count(1); | 					sym_add_change_count(1); | ||||||
| 					goto setsym; | 					continue; | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); | 				sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); | ||||||
| @@ -363,17 +462,22 @@ load: | |||||||
| 				if (*p2 == '\r') | 				if (*p2 == '\r') | ||||||
| 					*p2 = 0; | 					*p2 = 0; | ||||||
| 			} | 			} | ||||||
| 			if (def == S_DEF_USER) { |  | ||||||
| 			sym = sym_find(line + strlen(CONFIG_)); | 			sym = sym_find(line + strlen(CONFIG_)); | ||||||
| 			if (!sym) { | 			if (!sym) { | ||||||
|  | 				if (def == S_DEF_AUTO) | ||||||
|  | 					/* | ||||||
|  | 					 * Reading from include/config/auto.conf | ||||||
|  | 					 * If CONFIG_FOO previously existed in | ||||||
|  | 					 * auto.conf but it is missing now, | ||||||
|  | 					 * include/config/foo.h must be touched. | ||||||
|  | 					 */ | ||||||
|  | 					conf_touch_dep(line + strlen(CONFIG_)); | ||||||
|  | 				else | ||||||
| 					sym_add_change_count(1); | 					sym_add_change_count(1); | ||||||
| 					goto setsym; | 				continue; | ||||||
| 				} |  | ||||||
| 			} else { |  | ||||||
| 				sym = sym_lookup(line + strlen(CONFIG_), 0); |  | ||||||
| 				if (sym->type == S_UNKNOWN) |  | ||||||
| 					sym->type = S_OTHER; |  | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if (conf_set_sym_val(sym, def, def_flags, p)) | 			if (conf_set_sym_val(sym, def, def_flags, p)) | ||||||
| 				continue; | 				continue; | ||||||
| 		} else { | 		} else { | ||||||
| @@ -383,7 +487,7 @@ load: | |||||||
|  |  | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| setsym: |  | ||||||
| 		if (sym && sym_is_choice_value(sym)) { | 		if (sym && sym_is_choice_value(sym)) { | ||||||
| 			struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); | 			struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); | ||||||
| 			switch (sym->def[def].tri) { | 			switch (sym->def[def].tri) { | ||||||
| @@ -412,6 +516,7 @@ setsym: | |||||||
| int conf_read(const char *name) | int conf_read(const char *name) | ||||||
| { | { | ||||||
| 	struct symbol *sym; | 	struct symbol *sym; | ||||||
|  | 	int conf_unsaved = 0; | ||||||
| 	int i; | 	int i; | ||||||
|  |  | ||||||
| 	sym_set_change_count(0); | 	sym_set_change_count(0); | ||||||
| @@ -425,18 +530,16 @@ int conf_read(const char *name) | |||||||
|  |  | ||||||
| 	for_all_symbols(i, sym) { | 	for_all_symbols(i, sym) { | ||||||
| 		sym_calc_value(sym); | 		sym_calc_value(sym); | ||||||
| 		if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) | 		if (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE)) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { | 		if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { | ||||||
| 			/* check that calculated value agrees with saved value */ | 			/* check that calculated value agrees with saved value */ | ||||||
| 			switch (sym->type) { | 			switch (sym->type) { | ||||||
| 			case S_BOOLEAN: | 			case S_BOOLEAN: | ||||||
| 			case S_TRISTATE: | 			case S_TRISTATE: | ||||||
| 				if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) | 				if (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym)) | ||||||
| 					break; |  | ||||||
| 				if (!sym_is_choice(sym)) |  | ||||||
| 					continue; | 					continue; | ||||||
| 				/* fall through */ | 				break; | ||||||
| 			default: | 			default: | ||||||
| 				if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) | 				if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) | ||||||
| 					continue; | 					continue; | ||||||
| @@ -610,32 +713,12 @@ static struct conf_printer header_printer_cb = | |||||||
| 	.print_comment = header_print_comment, | 	.print_comment = header_print_comment, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Tristate printer |  | ||||||
|  * |  | ||||||
|  * This printer is used when generating the `include/config/tristate.conf' file. |  | ||||||
|  */ |  | ||||||
| static void |  | ||||||
| tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) |  | ||||||
| { |  | ||||||
|  |  | ||||||
| 	if (sym->type == S_TRISTATE && *value != 'n') |  | ||||||
| 		fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static struct conf_printer tristate_printer_cb = |  | ||||||
| { |  | ||||||
| 	.print_symbol = tristate_print_symbol, |  | ||||||
| 	.print_comment = kconfig_print_comment, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static void conf_write_symbol(FILE *fp, struct symbol *sym, | static void conf_write_symbol(FILE *fp, struct symbol *sym, | ||||||
| 			      struct conf_printer *printer, void *printer_arg) | 			      struct conf_printer *printer, void *printer_arg) | ||||||
| { | { | ||||||
| 	const char *str; | 	const char *str; | ||||||
|  |  | ||||||
| 	switch (sym->type) { | 	switch (sym->type) { | ||||||
| 	case S_OTHER: |  | ||||||
| 	case S_UNKNOWN: | 	case S_UNKNOWN: | ||||||
| 		break; | 		break; | ||||||
| 	case S_STRING: | 	case S_STRING: | ||||||
| @@ -695,7 +778,7 @@ int conf_write_defconfig(const char *filename) | |||||||
| 				goto next_menu; | 				goto next_menu; | ||||||
| 			sym->flags &= ~SYMBOL_WRITE; | 			sym->flags &= ~SYMBOL_WRITE; | ||||||
| 			/* If we cannot change the symbol - skip */ | 			/* If we cannot change the symbol - skip */ | ||||||
| 			if (!sym_is_changable(sym)) | 			if (!sym_is_changeable(sym)) | ||||||
| 				goto next_menu; | 				goto next_menu; | ||||||
| 			/* If symbol equals to default value - skip */ | 			/* If symbol equals to default value - skip */ | ||||||
| 			if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0) | 			if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0) | ||||||
| @@ -746,41 +829,36 @@ int conf_write(const char *name) | |||||||
| 	FILE *out; | 	FILE *out; | ||||||
| 	struct symbol *sym; | 	struct symbol *sym; | ||||||
| 	struct menu *menu; | 	struct menu *menu; | ||||||
| 	const char *basename; |  | ||||||
| 	const char *str; | 	const char *str; | ||||||
| 	char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; | 	char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1]; | ||||||
| 	char *env; | 	char *env; | ||||||
|  | 	int i; | ||||||
|  | 	bool need_newline = false; | ||||||
|  |  | ||||||
| 	dirname[0] = 0; | 	if (!name) | ||||||
| 	if (name && name[0]) { | 		name = conf_get_configname(); | ||||||
| 		struct stat st; |  | ||||||
| 		char *slash; |  | ||||||
|  |  | ||||||
| 		if (!stat(name, &st) && S_ISDIR(st.st_mode)) { | 	if (!*name) { | ||||||
| 			strcpy(dirname, name); | 		fprintf(stderr, "config name is empty\n"); | ||||||
| 			strcat(dirname, "/"); | 		return -1; | ||||||
| 			basename = conf_get_configname(); | 	} | ||||||
| 		} else if ((slash = strrchr(name, '/'))) { |  | ||||||
| 			int size = slash - name + 1; | 	if (is_dir(name)) { | ||||||
| 			memcpy(dirname, name, size); | 		fprintf(stderr, "%s: Is a directory\n", name); | ||||||
| 			dirname[size] = 0; | 		return -1; | ||||||
| 			if (slash[1]) | 	} | ||||||
| 				basename = slash + 1; |  | ||||||
| 			else | 	if (make_parent_dir(name)) | ||||||
| 				basename = conf_get_configname(); | 		return -1; | ||||||
| 		} else |  | ||||||
| 			basename = name; |  | ||||||
| 	} else |  | ||||||
| 		basename = conf_get_configname(); |  | ||||||
|  |  | ||||||
| 	sprintf(newname, "%s%s", dirname, basename); |  | ||||||
| 	env = getenv("KCONFIG_OVERWRITECONFIG"); | 	env = getenv("KCONFIG_OVERWRITECONFIG"); | ||||||
| 	if (!env || !*env) { | 	if (env && *env) { | ||||||
| 		sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); |  | ||||||
| 		out = fopen(tmpname, "w"); |  | ||||||
| 	} else { |  | ||||||
| 		*tmpname = 0; | 		*tmpname = 0; | ||||||
| 		out = fopen(newname, "w"); | 		out = fopen(name, "w"); | ||||||
|  | 	} else { | ||||||
|  | 		snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp", | ||||||
|  | 			 name, (int)getpid()); | ||||||
|  | 		out = fopen(tmpname, "w"); | ||||||
| 	} | 	} | ||||||
| 	if (!out) | 	if (!out) | ||||||
| 		return 1; | 		return 1; | ||||||
| @@ -801,12 +879,17 @@ int conf_write(const char *name) | |||||||
| 				     "#\n" | 				     "#\n" | ||||||
| 				     "# %s\n" | 				     "# %s\n" | ||||||
| 				     "#\n", str); | 				     "#\n", str); | ||||||
| 		} else if (!(sym->flags & SYMBOL_CHOICE)) { | 			need_newline = false; | ||||||
|  | 		} else if (!(sym->flags & SYMBOL_CHOICE) && | ||||||
|  | 			   !(sym->flags & SYMBOL_WRITTEN)) { | ||||||
| 			sym_calc_value(sym); | 			sym_calc_value(sym); | ||||||
| 			if (!(sym->flags & SYMBOL_WRITE)) | 			if (!(sym->flags & SYMBOL_WRITE)) | ||||||
| 				goto next; | 				goto next; | ||||||
| 			sym->flags &= ~SYMBOL_WRITE; | 			if (need_newline) { | ||||||
|  | 				fprintf(out, "\n"); | ||||||
|  | 				need_newline = false; | ||||||
|  | 			} | ||||||
|  | 			sym->flags |= SYMBOL_WRITTEN; | ||||||
| 			conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); | 			conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -818,6 +901,12 @@ next: | |||||||
| 		if (menu->next) | 		if (menu->next) | ||||||
| 			menu = menu->next; | 			menu = menu->next; | ||||||
| 		else while ((menu = menu->parent)) { | 		else while ((menu = menu->parent)) { | ||||||
|  | 			if (!menu->sym && menu_is_visible(menu) && | ||||||
|  | 			    menu != &rootmenu) { | ||||||
|  | 				str = menu_get_prompt(menu); | ||||||
|  | 				fprintf(out, "# end of %s\n", str); | ||||||
|  | 				need_newline = true; | ||||||
|  | 			} | ||||||
| 			if (menu->next) { | 			if (menu->next) { | ||||||
| 				menu = menu->next; | 				menu = menu->next; | ||||||
| 				break; | 				break; | ||||||
| @@ -826,41 +915,76 @@ next: | |||||||
| 	} | 	} | ||||||
| 	fclose(out); | 	fclose(out); | ||||||
|  |  | ||||||
|  | 	for_all_symbols(i, sym) | ||||||
|  | 		sym->flags &= ~SYMBOL_WRITTEN; | ||||||
|  |  | ||||||
| 	if (*tmpname) { | 	if (*tmpname) { | ||||||
| 		strcat(dirname, basename); | 		if (is_same(name, tmpname)) { | ||||||
| 		strcat(dirname, ".old"); | 			conf_message("No change to %s", name); | ||||||
| 		rename(newname, dirname); | 			unlink(tmpname); | ||||||
| 		if (rename(tmpname, newname)) | 			sym_set_change_count(0); | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		snprintf(oldname, sizeof(oldname), "%s.old", name); | ||||||
|  | 		rename(name, oldname); | ||||||
|  | 		if (rename(tmpname, name)) | ||||||
| 			return 1; | 			return 1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	conf_message(_("configuration written to %s"), newname); | 	conf_message("configuration written to %s", name); | ||||||
|  |  | ||||||
| 	sym_set_change_count(0); | 	sym_set_change_count(0); | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int conf_split_config(void) | /* write a dependency file as used by kbuild to track dependencies */ | ||||||
|  | static int conf_write_dep(const char *name) | ||||||
|  | { | ||||||
|  | 	struct file *file; | ||||||
|  | 	FILE *out; | ||||||
|  |  | ||||||
|  | 	out = fopen("..config.tmp", "w"); | ||||||
|  | 	if (!out) | ||||||
|  | 		return 1; | ||||||
|  | 	fprintf(out, "deps_config := \\\n"); | ||||||
|  | 	for (file = file_list; file; file = file->next) { | ||||||
|  | 		if (file->next) | ||||||
|  | 			fprintf(out, "\t%s \\\n", file->name); | ||||||
|  | 		else | ||||||
|  | 			fprintf(out, "\t%s\n", file->name); | ||||||
|  | 	} | ||||||
|  | 	fprintf(out, "\n%s: \\\n" | ||||||
|  | 		     "\t$(deps_config)\n\n", conf_get_autoconfig_name()); | ||||||
|  |  | ||||||
|  | 	env_write_dep(out, conf_get_autoconfig_name()); | ||||||
|  |  | ||||||
|  | 	fprintf(out, "\n$(deps_config): ;\n"); | ||||||
|  | 	fclose(out); | ||||||
|  |  | ||||||
|  | 	if (make_parent_dir(name)) | ||||||
|  | 		return 1; | ||||||
|  | 	rename("..config.tmp", name); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int conf_touch_deps(void) | ||||||
| { | { | ||||||
| 	const char *name; | 	const char *name; | ||||||
| 	char path[PATH_MAX+1]; |  | ||||||
| 	char *s, *d, c; |  | ||||||
| 	struct symbol *sym; | 	struct symbol *sym; | ||||||
| 	struct stat sb; | 	int res, i; | ||||||
| 	int res, i, fd; |  | ||||||
|  | 	strcpy(depfile_path, "include/config/"); | ||||||
|  | 	depfile_prefix_len = strlen(depfile_path); | ||||||
|  |  | ||||||
| 	name = conf_get_autoconfig_name(); | 	name = conf_get_autoconfig_name(); | ||||||
| 	conf_read_simple(name, S_DEF_AUTO); | 	conf_read_simple(name, S_DEF_AUTO); | ||||||
| 	sym_calc_value(modules_sym); | 	sym_calc_value(modules_sym); | ||||||
|  |  | ||||||
| 	if (chdir("include/config")) |  | ||||||
| 		return 1; |  | ||||||
|  |  | ||||||
| 	res = 0; |  | ||||||
| 	for_all_symbols(i, sym) { | 	for_all_symbols(i, sym) { | ||||||
| 		sym_calc_value(sym); | 		sym_calc_value(sym); | ||||||
| 		if ((sym->flags & SYMBOL_AUTO) || !sym->name) | 		if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (sym->flags & SYMBOL_WRITE) { | 		if (sym->flags & SYMBOL_WRITE) { | ||||||
| 			if (sym->flags & SYMBOL_DEF_AUTO) { | 			if (sym->flags & SYMBOL_DEF_AUTO) { | ||||||
| @@ -909,86 +1033,44 @@ static int conf_split_config(void) | |||||||
| 		 *	different from 'no'). | 		 *	different from 'no'). | ||||||
| 		 */ | 		 */ | ||||||
|  |  | ||||||
| 		/* Replace all '_' and append ".h" */ | 		res = conf_touch_dep(sym->name); | ||||||
| 		s = sym->name; | 		if (res) | ||||||
| 		d = path; |  | ||||||
| 		while ((c = *s++)) { |  | ||||||
| 			c = tolower(c); |  | ||||||
| 			*d++ = (c == '_') ? '/' : c; |  | ||||||
| 		} |  | ||||||
| 		strcpy(d, ".h"); |  | ||||||
|  |  | ||||||
| 		/* Assume directory path already exists. */ |  | ||||||
| 		fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); |  | ||||||
| 		if (fd == -1) { |  | ||||||
| 			if (errno != ENOENT) { |  | ||||||
| 				res = 1; |  | ||||||
| 				break; |  | ||||||
| 			} |  | ||||||
| 			/* |  | ||||||
| 			 * Create directory components, |  | ||||||
| 			 * unless they exist already. |  | ||||||
| 			 */ |  | ||||||
| 			d = path; |  | ||||||
| 			while ((d = strchr(d, '/'))) { |  | ||||||
| 				*d = 0; |  | ||||||
| 				if (stat(path, &sb) && mkdir(path, 0755)) { |  | ||||||
| 					res = 1; |  | ||||||
| 					goto out; |  | ||||||
| 				} |  | ||||||
| 				*d++ = '/'; |  | ||||||
| 			} |  | ||||||
| 			/* Try it again. */ |  | ||||||
| 			fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); |  | ||||||
| 			if (fd == -1) { |  | ||||||
| 				res = 1; |  | ||||||
| 				break; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		close(fd); |  | ||||||
| 	} |  | ||||||
| out: |  | ||||||
| 	if (chdir("../..")) |  | ||||||
| 		return 1; |  | ||||||
|  |  | ||||||
| 			return res; | 			return res; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int conf_write_autoconf(void) | int conf_write_autoconf(int overwrite) | ||||||
| { | { | ||||||
| 	struct symbol *sym; | 	struct symbol *sym; | ||||||
| 	const char *name; | 	const char *name; | ||||||
| 	FILE *out, *tristate, *out_h; | 	const char *autoconf_name = conf_get_autoconfig_name(); | ||||||
|  | 	FILE *out, *out_h; | ||||||
| 	int i; | 	int i; | ||||||
|  |  | ||||||
| 	sym_clear_all_valid(); | #ifndef OPENWRT_DOES_NOT_WANT_THIS | ||||||
|  | 	return 0; | ||||||
|  | #endif | ||||||
|  | 	if (!overwrite && is_present(autoconf_name)) | ||||||
|  | 		return 0; | ||||||
|  |  | ||||||
| 	file_write_dep("include/config/auto.conf.cmd"); | 	conf_write_dep("include/config/auto.conf.cmd"); | ||||||
|  |  | ||||||
| 	if (conf_split_config()) | 	if (conf_touch_deps()) | ||||||
| 		return 1; | 		return 1; | ||||||
|  |  | ||||||
| 	out = fopen(".tmpconfig", "w"); | 	out = fopen(".tmpconfig", "w"); | ||||||
| 	if (!out) | 	if (!out) | ||||||
| 		return 1; | 		return 1; | ||||||
|  |  | ||||||
| 	tristate = fopen(".tmpconfig_tristate", "w"); |  | ||||||
| 	if (!tristate) { |  | ||||||
| 		fclose(out); |  | ||||||
| 		return 1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	out_h = fopen(".tmpconfig.h", "w"); | 	out_h = fopen(".tmpconfig.h", "w"); | ||||||
| 	if (!out_h) { | 	if (!out_h) { | ||||||
| 		fclose(out); | 		fclose(out); | ||||||
| 		fclose(tristate); |  | ||||||
| 		return 1; | 		return 1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	conf_write_heading(out, &kconfig_printer_cb, NULL); | 	conf_write_heading(out, &kconfig_printer_cb, NULL); | ||||||
|  |  | ||||||
| 	conf_write_heading(tristate, &tristate_printer_cb, NULL); |  | ||||||
|  |  | ||||||
| 	conf_write_heading(out_h, &header_printer_cb, NULL); | 	conf_write_heading(out_h, &header_printer_cb, NULL); | ||||||
|  |  | ||||||
| 	for_all_symbols(i, sym) { | 	for_all_symbols(i, sym) { | ||||||
| @@ -996,33 +1078,28 @@ int conf_write_autoconf(void) | |||||||
| 		if (!(sym->flags & SYMBOL_WRITE) || !sym->name) | 		if (!(sym->flags & SYMBOL_WRITE) || !sym->name) | ||||||
| 			continue; | 			continue; | ||||||
|  |  | ||||||
| 		/* write symbol to auto.conf, tristate and header files */ | 		/* write symbols to auto.conf and autoconf.h */ | ||||||
| 		conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); | 		conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); | ||||||
|  |  | ||||||
| 		conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); |  | ||||||
|  |  | ||||||
| 		conf_write_symbol(out_h, sym, &header_printer_cb, NULL); | 		conf_write_symbol(out_h, sym, &header_printer_cb, NULL); | ||||||
| 	} | 	} | ||||||
| 	fclose(out); | 	fclose(out); | ||||||
| 	fclose(tristate); |  | ||||||
| 	fclose(out_h); | 	fclose(out_h); | ||||||
|  |  | ||||||
| 	name = getenv("KCONFIG_AUTOHEADER"); | 	name = getenv("KCONFIG_AUTOHEADER"); | ||||||
| 	if (!name) | 	if (!name) | ||||||
| 		name = "include/generated/autoconf.h"; | 		name = "include/generated/autoconf.h"; | ||||||
|  | 	if (make_parent_dir(name)) | ||||||
|  | 		return 1; | ||||||
| 	if (rename(".tmpconfig.h", name)) | 	if (rename(".tmpconfig.h", name)) | ||||||
| 		return 1; | 		return 1; | ||||||
| 	name = getenv("KCONFIG_TRISTATE"); |  | ||||||
| 	if (!name) | 	if (make_parent_dir(autoconf_name)) | ||||||
| 		name = "include/config/tristate.conf"; |  | ||||||
| 	if (rename(".tmpconfig_tristate", name)) |  | ||||||
| 		return 1; | 		return 1; | ||||||
| 	name = conf_get_autoconfig_name(); |  | ||||||
| 	/* | 	/* | ||||||
| 	 * This must be the last step, kbuild has a dependency on auto.conf | 	 * This must be the last step, kbuild has a dependency on auto.conf | ||||||
| 	 * and this marks the successful completion of the previous steps. | 	 * and this marks the successful completion of the previous steps. | ||||||
| 	 */ | 	 */ | ||||||
| 	if (rename(".tmpconfig", name)) | 	if (rename(".tmpconfig", autoconf_name)) | ||||||
| 		return 1; | 		return 1; | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| @@ -1126,7 +1203,7 @@ void set_all_choice_values(struct symbol *csym) | |||||||
| bool conf_set_all_new_symbols(enum conf_def_mode mode) | bool conf_set_all_new_symbols(enum conf_def_mode mode) | ||||||
| { | { | ||||||
| 	struct symbol *sym, *csym; | 	struct symbol *sym, *csym; | ||||||
| 	int i, cnt, pby, pty, ptm;	/* pby: probability of boolean  = y | 	int i, cnt, pby, pty, ptm;	/* pby: probability of bool     = y | ||||||
| 					 * pty: probability of tristate = y | 					 * pty: probability of tristate = y | ||||||
| 					 * ptm: probability of tristate = m | 					 * ptm: probability of tristate = m | ||||||
| 					 */ | 					 */ | ||||||
| @@ -1250,3 +1327,19 @@ bool conf_set_all_new_symbols(enum conf_def_mode mode) | |||||||
|  |  | ||||||
| 	return has_changed; | 	return has_changed; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void conf_rewrite_mod_or_yes(enum conf_def_mode mode) | ||||||
|  | { | ||||||
|  | 	struct symbol *sym; | ||||||
|  | 	int i; | ||||||
|  | 	tristate old_val = (mode == def_y2m) ? yes : mod; | ||||||
|  | 	tristate new_val = (mode == def_y2m) ? mod : yes; | ||||||
|  |  | ||||||
|  | 	for_all_symbols(i, sym) { | ||||||
|  | 		if (sym_get_type(sym) == S_TRISTATE && | ||||||
|  | 		    sym->def[S_DEF_USER].tri == old_val) { | ||||||
|  | 			sym->def[S_DEF_USER].tri = new_val; | ||||||
|  | 			sym_add_change_count(1); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,8 +1,10 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0 | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  * Released under the terms of the GNU GPL v2.0. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | #include <ctype.h> | ||||||
|  | #include <errno.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| @@ -11,7 +13,6 @@ | |||||||
|  |  | ||||||
| #define DEBUG_EXPR	0 | #define DEBUG_EXPR	0 | ||||||
|  |  | ||||||
| static int expr_eq(struct expr *e1, struct expr *e2); |  | ||||||
| static struct expr *expr_eliminate_yn(struct expr *e); | static struct expr *expr_eliminate_yn(struct expr *e); | ||||||
|  |  | ||||||
| struct expr *expr_alloc_symbol(struct symbol *sym) | struct expr *expr_alloc_symbol(struct symbol *sym) | ||||||
| @@ -94,7 +95,7 @@ struct expr *expr_copy(const struct expr *org) | |||||||
| 		e->right.expr = expr_copy(org->right.expr); | 		e->right.expr = expr_copy(org->right.expr); | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		printf("can't copy type %d\n", e->type); | 		fprintf(stderr, "can't copy type %d\n", e->type); | ||||||
| 		free(e); | 		free(e); | ||||||
| 		e = NULL; | 		e = NULL; | ||||||
| 		break; | 		break; | ||||||
| @@ -113,7 +114,7 @@ void expr_free(struct expr *e) | |||||||
| 		break; | 		break; | ||||||
| 	case E_NOT: | 	case E_NOT: | ||||||
| 		expr_free(e->left.expr); | 		expr_free(e->left.expr); | ||||||
| 		return; | 		break; | ||||||
| 	case E_EQUAL: | 	case E_EQUAL: | ||||||
| 	case E_GEQ: | 	case E_GEQ: | ||||||
| 	case E_GTH: | 	case E_GTH: | ||||||
| @@ -127,7 +128,7 @@ void expr_free(struct expr *e) | |||||||
| 		expr_free(e->right.expr); | 		expr_free(e->right.expr); | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		printf("how to free type %d?\n", e->type); | 		fprintf(stderr, "how to free type %d?\n", e->type); | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	free(e); | 	free(e); | ||||||
| @@ -138,8 +139,18 @@ static int trans_count; | |||||||
| #define e1 (*ep1) | #define e1 (*ep1) | ||||||
| #define e2 (*ep2) | #define e2 (*ep2) | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * expr_eliminate_eq() helper. | ||||||
|  |  * | ||||||
|  |  * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does | ||||||
|  |  * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared | ||||||
|  |  * against all other leaves. Two equal leaves are both replaced with either 'y' | ||||||
|  |  * or 'n' as appropriate for 'type', to be eliminated later. | ||||||
|  |  */ | ||||||
| static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) | static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) | ||||||
| { | { | ||||||
|  | 	/* Recurse down to leaves */ | ||||||
|  |  | ||||||
| 	if (e1->type == type) { | 	if (e1->type == type) { | ||||||
| 		__expr_eliminate_eq(type, &e1->left.expr, &e2); | 		__expr_eliminate_eq(type, &e1->left.expr, &e2); | ||||||
| 		__expr_eliminate_eq(type, &e1->right.expr, &e2); | 		__expr_eliminate_eq(type, &e1->right.expr, &e2); | ||||||
| @@ -150,12 +161,18 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e | |||||||
| 		__expr_eliminate_eq(type, &e1, &e2->right.expr); | 		__expr_eliminate_eq(type, &e1, &e2->right.expr); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/* e1 and e2 are leaves. Compare them. */ | ||||||
|  |  | ||||||
| 	if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && | 	if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && | ||||||
| 	    e1->left.sym == e2->left.sym && | 	    e1->left.sym == e2->left.sym && | ||||||
| 	    (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) | 	    (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) | ||||||
| 		return; | 		return; | ||||||
| 	if (!expr_eq(e1, e2)) | 	if (!expr_eq(e1, e2)) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
|  | 	/* e1 and e2 are equal leaves. Prepare them for elimination. */ | ||||||
|  |  | ||||||
| 	trans_count++; | 	trans_count++; | ||||||
| 	expr_free(e1); expr_free(e2); | 	expr_free(e1); expr_free(e2); | ||||||
| 	switch (type) { | 	switch (type) { | ||||||
| @@ -172,6 +189,35 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Rewrites the expressions 'ep1' and 'ep2' to remove operands common to both. | ||||||
|  |  * Example reductions: | ||||||
|  |  * | ||||||
|  |  *	ep1: A && B           ->  ep1: y | ||||||
|  |  *	ep2: A && B && C      ->  ep2: C | ||||||
|  |  * | ||||||
|  |  *	ep1: A || B           ->  ep1: n | ||||||
|  |  *	ep2: A || B || C      ->  ep2: C | ||||||
|  |  * | ||||||
|  |  *	ep1: A && (B && FOO)  ->  ep1: FOO | ||||||
|  |  *	ep2: (BAR && B) && A  ->  ep2: BAR | ||||||
|  |  * | ||||||
|  |  *	ep1: A && (B || C)    ->  ep1: y | ||||||
|  |  *	ep2: (C || B) && A    ->  ep2: y | ||||||
|  |  * | ||||||
|  |  * Comparisons are done between all operands at the same "level" of && or ||. | ||||||
|  |  * For example, in the expression 'e1 && (e2 || e3) && (e4 || e5)', the | ||||||
|  |  * following operands will be compared: | ||||||
|  |  * | ||||||
|  |  *	- 'e1', 'e2 || e3', and 'e4 || e5', against each other | ||||||
|  |  *	- e2 against e3 | ||||||
|  |  *	- e4 against e5 | ||||||
|  |  * | ||||||
|  |  * Parentheses are irrelevant within a single level. 'e1 && (e2 && e3)' and | ||||||
|  |  * '(e1 && e2) && e3' are both a single level. | ||||||
|  |  * | ||||||
|  |  * See __expr_eliminate_eq() as well. | ||||||
|  |  */ | ||||||
| void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) | void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) | ||||||
| { | { | ||||||
| 	if (!e1 || !e2) | 	if (!e1 || !e2) | ||||||
| @@ -197,10 +243,23 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) | |||||||
| #undef e1 | #undef e1 | ||||||
| #undef e2 | #undef e2 | ||||||
|  |  | ||||||
| static int expr_eq(struct expr *e1, struct expr *e2) | /* | ||||||
|  |  * Returns true if 'e1' and 'e2' are equal, after minor simplification. Two | ||||||
|  |  * &&/|| expressions are considered equal if every operand in one expression | ||||||
|  |  * equals some operand in the other (operands do not need to appear in the same | ||||||
|  |  * order), recursively. | ||||||
|  |  */ | ||||||
|  | int expr_eq(struct expr *e1, struct expr *e2) | ||||||
| { | { | ||||||
| 	int res, old_count; | 	int res, old_count; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * A NULL expr is taken to be yes, but there's also a different way to | ||||||
|  | 	 * represent yes. expr_is_yes() checks for either representation. | ||||||
|  | 	 */ | ||||||
|  | 	if (!e1 || !e2) | ||||||
|  | 		return expr_is_yes(e1) && expr_is_yes(e2); | ||||||
|  |  | ||||||
| 	if (e1->type != e2->type) | 	if (e1->type != e2->type) | ||||||
| 		return 0; | 		return 0; | ||||||
| 	switch (e1->type) { | 	switch (e1->type) { | ||||||
| @@ -243,6 +302,17 @@ static int expr_eq(struct expr *e1, struct expr *e2) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Recursively performs the following simplifications in-place (as well as the | ||||||
|  |  * corresponding simplifications with swapped operands): | ||||||
|  |  * | ||||||
|  |  *	expr && n  ->  n | ||||||
|  |  *	expr && y  ->  expr | ||||||
|  |  *	expr || n  ->  expr | ||||||
|  |  *	expr || y  ->  y | ||||||
|  |  * | ||||||
|  |  * Returns the optimized expression. | ||||||
|  |  */ | ||||||
| static struct expr *expr_eliminate_yn(struct expr *e) | static struct expr *expr_eliminate_yn(struct expr *e) | ||||||
| { | { | ||||||
| 	struct expr *tmp; | 	struct expr *tmp; | ||||||
| @@ -516,12 +586,21 @@ static struct expr *expr_join_and(struct expr *e1, struct expr *e2) | |||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * expr_eliminate_dups() helper. | ||||||
|  |  * | ||||||
|  |  * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does | ||||||
|  |  * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared | ||||||
|  |  * against all other leaves to look for simplifications. | ||||||
|  |  */ | ||||||
| static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2) | static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2) | ||||||
| { | { | ||||||
| #define e1 (*ep1) | #define e1 (*ep1) | ||||||
| #define e2 (*ep2) | #define e2 (*ep2) | ||||||
| 	struct expr *tmp; | 	struct expr *tmp; | ||||||
|  |  | ||||||
|  | 	/* Recurse down to leaves */ | ||||||
|  |  | ||||||
| 	if (e1->type == type) { | 	if (e1->type == type) { | ||||||
| 		expr_eliminate_dups1(type, &e1->left.expr, &e2); | 		expr_eliminate_dups1(type, &e1->left.expr, &e2); | ||||||
| 		expr_eliminate_dups1(type, &e1->right.expr, &e2); | 		expr_eliminate_dups1(type, &e1->right.expr, &e2); | ||||||
| @@ -532,6 +611,9 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct | |||||||
| 		expr_eliminate_dups1(type, &e1, &e2->right.expr); | 		expr_eliminate_dups1(type, &e1, &e2->right.expr); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/* e1 and e2 are leaves. Compare and process them. */ | ||||||
|  |  | ||||||
| 	if (e1 == e2) | 	if (e1 == e2) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| @@ -568,6 +650,17 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct | |||||||
| #undef e2 | #undef e2 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Rewrites 'e' in-place to remove ("join") duplicate and other redundant | ||||||
|  |  * operands. | ||||||
|  |  * | ||||||
|  |  * Example simplifications: | ||||||
|  |  * | ||||||
|  |  *	A || B || A    ->  A || B | ||||||
|  |  *	A && B && A=y  ->  A=y && B | ||||||
|  |  * | ||||||
|  |  * Returns the deduplicated expression. | ||||||
|  |  */ | ||||||
| struct expr *expr_eliminate_dups(struct expr *e) | struct expr *expr_eliminate_dups(struct expr *e) | ||||||
| { | { | ||||||
| 	int oldcount; | 	int oldcount; | ||||||
| @@ -584,6 +677,7 @@ struct expr *expr_eliminate_dups(struct expr *e) | |||||||
| 			; | 			; | ||||||
| 		} | 		} | ||||||
| 		if (!trans_count) | 		if (!trans_count) | ||||||
|  | 			/* No simplifications done in this pass. We're done */ | ||||||
| 			break; | 			break; | ||||||
| 		e = expr_eliminate_yn(e); | 		e = expr_eliminate_yn(e); | ||||||
| 	} | 	} | ||||||
| @@ -591,6 +685,12 @@ struct expr *expr_eliminate_dups(struct expr *e) | |||||||
| 	return e; | 	return e; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Performs various simplifications involving logical operators and | ||||||
|  |  * comparisons. | ||||||
|  |  * | ||||||
|  |  * Allocates and returns a new expression. | ||||||
|  |  */ | ||||||
| struct expr *expr_transform(struct expr *e) | struct expr *expr_transform(struct expr *e) | ||||||
| { | { | ||||||
| 	struct expr *tmp; | 	struct expr *tmp; | ||||||
| @@ -805,6 +905,20 @@ bool expr_depends_symbol(struct expr *dep, struct symbol *sym) | |||||||
|  	return false; |  	return false; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Inserts explicit comparisons of type 'type' to symbol 'sym' into the | ||||||
|  |  * expression 'e'. | ||||||
|  |  * | ||||||
|  |  * Examples transformations for type == E_UNEQUAL, sym == &symbol_no: | ||||||
|  |  * | ||||||
|  |  *	A              ->  A!=n | ||||||
|  |  *	!A             ->  A=n | ||||||
|  |  *	A && B         ->  !(A=n || B=n) | ||||||
|  |  *	A || B         ->  !(A=n && B=n) | ||||||
|  |  *	A && (B || C)  ->  !(A=n || (B=n && C=n)) | ||||||
|  |  * | ||||||
|  |  * Allocates and returns a new expression. | ||||||
|  |  */ | ||||||
| struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) | struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) | ||||||
| { | { | ||||||
| 	struct expr *e1, *e2; | 	struct expr *e1, *e2; | ||||||
| @@ -874,7 +988,6 @@ enum string_value_kind { | |||||||
| 	k_string, | 	k_string, | ||||||
| 	k_signed, | 	k_signed, | ||||||
| 	k_unsigned, | 	k_unsigned, | ||||||
| 	k_invalid |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| union string_value { | union string_value { | ||||||
| @@ -905,13 +1018,10 @@ static enum string_value_kind expr_parse_string(const char *str, | |||||||
| 		val->u = strtoull(str, &tail, 16); | 		val->u = strtoull(str, &tail, 16); | ||||||
| 		kind = k_unsigned; | 		kind = k_unsigned; | ||||||
| 		break; | 		break; | ||||||
| 	case S_STRING: | 	default: | ||||||
| 	case S_UNKNOWN: |  | ||||||
| 		val->s = strtoll(str, &tail, 0); | 		val->s = strtoll(str, &tail, 0); | ||||||
| 		kind = k_signed; | 		kind = k_signed; | ||||||
| 		break; | 		break; | ||||||
| 	default: |  | ||||||
| 		return k_invalid; |  | ||||||
| 	} | 	} | ||||||
| 	return !errno && !*tail && tail > str && isxdigit(tail[-1]) | 	return !errno && !*tail && tail > str && isxdigit(tail[-1]) | ||||||
| 	       ? kind : k_string; | 	       ? kind : k_string; | ||||||
| @@ -967,13 +1077,7 @@ tristate expr_calc_value(struct expr *e) | |||||||
|  |  | ||||||
| 	if (k1 == k_string || k2 == k_string) | 	if (k1 == k_string || k2 == k_string) | ||||||
| 		res = strcmp(str1, str2); | 		res = strcmp(str1, str2); | ||||||
| 	else if (k1 == k_invalid || k2 == k_invalid) { | 	else if (k1 == k_unsigned || k2 == k_unsigned) | ||||||
| 		if (e->type != E_EQUAL && e->type != E_UNEQUAL) { |  | ||||||
| 			printf("Cannot compare \"%s\" and \"%s\"\n", str1, str2); |  | ||||||
| 			return no; |  | ||||||
| 		} |  | ||||||
| 		res = strcmp(str1, str2); |  | ||||||
| 	} else if (k1 == k_unsigned || k2 == k_unsigned) |  | ||||||
| 		res = (lval.u > rval.u) - (lval.u < rval.u); | 		res = (lval.u > rval.u) - (lval.u < rval.u); | ||||||
| 	else /* if (k1 == k_signed && k2 == k_signed) */ | 	else /* if (k1 == k_signed && k2 == k_signed) */ | ||||||
| 		res = (lval.s > rval.s) - (lval.s < rval.s); | 		res = (lval.s > rval.s) - (lval.s < rval.s); | ||||||
| @@ -1031,49 +1135,9 @@ static int expr_compare_type(enum expr_type t1, enum expr_type t2) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline struct expr * | void expr_print(struct expr *e, | ||||||
| expr_get_leftmost_symbol(const struct expr *e) | 		void (*fn)(void *, struct symbol *, const char *), | ||||||
| { | 		void *data, int prevtoken) | ||||||
|  |  | ||||||
| 	if (e == NULL) |  | ||||||
| 		return NULL; |  | ||||||
|  |  | ||||||
| 	while (e->type != E_SYMBOL) |  | ||||||
| 		e = e->left.expr; |  | ||||||
|  |  | ||||||
| 	return expr_copy(e); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Given expression `e1' and `e2', returns the leaf of the longest |  | ||||||
|  * sub-expression of `e1' not containing 'e2. |  | ||||||
|  */ |  | ||||||
| struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2) |  | ||||||
| { |  | ||||||
| 	struct expr *ret; |  | ||||||
|  |  | ||||||
| 	switch (e1->type) { |  | ||||||
| 	case E_OR: |  | ||||||
| 		return expr_alloc_and( |  | ||||||
| 		    expr_simplify_unmet_dep(e1->left.expr, e2), |  | ||||||
| 		    expr_simplify_unmet_dep(e1->right.expr, e2)); |  | ||||||
| 	case E_AND: { |  | ||||||
| 		struct expr *e; |  | ||||||
| 		e = expr_alloc_and(expr_copy(e1), expr_copy(e2)); |  | ||||||
| 		e = expr_eliminate_dups(e); |  | ||||||
| 		ret = (!expr_eq(e, e1)) ? e1 : NULL; |  | ||||||
| 		expr_free(e); |  | ||||||
| 		break; |  | ||||||
| 		} |  | ||||||
| 	default: |  | ||||||
| 		ret = e1; |  | ||||||
| 		break; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return expr_get_leftmost_symbol(ret); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken) |  | ||||||
| { | { | ||||||
| 	if (!e) { | 	if (!e) { | ||||||
| 		fn(data, NULL, "y"); | 		fn(data, NULL, "y"); | ||||||
| @@ -1207,3 +1271,33 @@ void expr_gstr_print(struct expr *e, struct gstr *gs) | |||||||
| { | { | ||||||
| 	expr_print(e, expr_print_gstr_helper, gs, E_NONE); | 	expr_print(e, expr_print_gstr_helper, gs, E_NONE); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Transform the top level "||" tokens into newlines and prepend each | ||||||
|  |  * line with a minus. This makes expressions much easier to read. | ||||||
|  |  * Suitable for reverse dependency expressions. | ||||||
|  |  */ | ||||||
|  | static void expr_print_revdep(struct expr *e, | ||||||
|  | 			      void (*fn)(void *, struct symbol *, const char *), | ||||||
|  | 			      void *data, tristate pr_type, const char **title) | ||||||
|  | { | ||||||
|  | 	if (e->type == E_OR) { | ||||||
|  | 		expr_print_revdep(e->left.expr, fn, data, pr_type, title); | ||||||
|  | 		expr_print_revdep(e->right.expr, fn, data, pr_type, title); | ||||||
|  | 	} else if (expr_calc_value(e) == pr_type) { | ||||||
|  | 		if (*title) { | ||||||
|  | 			fn(data, NULL, *title); | ||||||
|  | 			*title = NULL; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		fn(data, NULL, "  - "); | ||||||
|  | 		expr_print(e, fn, data, E_NONE); | ||||||
|  | 		fn(data, NULL, "\n"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void expr_gstr_print_revdep(struct expr *e, struct gstr *gs, | ||||||
|  | 			    tristate pr_type, const char *title) | ||||||
|  | { | ||||||
|  | 	expr_print_revdep(e, expr_print_gstr_helper, gs, pr_type, &title); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
|  | /* SPDX-License-Identifier: GPL-2.0 */ | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  * Released under the terms of the GNU GPL v2.0. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef EXPR_H | #ifndef EXPR_H | ||||||
| @@ -62,7 +62,7 @@ struct symbol_value { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| enum symbol_type { | enum symbol_type { | ||||||
| 	S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER | 	S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* enum values are used as index to symbol.def[] */ | /* enum values are used as index to symbol.def[] */ | ||||||
| @@ -74,20 +74,64 @@ enum { | |||||||
| 	S_DEF_COUNT | 	S_DEF_COUNT | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Represents a configuration symbol. | ||||||
|  |  * | ||||||
|  |  * Choices are represented as a special kind of symbol and have the | ||||||
|  |  * SYMBOL_CHOICE bit set in 'flags'. | ||||||
|  |  */ | ||||||
| struct symbol { | struct symbol { | ||||||
|  | 	/* The next symbol in the same bucket in the symbol hash table */ | ||||||
| 	struct symbol *next; | 	struct symbol *next; | ||||||
|  |  | ||||||
|  | 	/* The name of the symbol, e.g. "FOO" for 'config FOO' */ | ||||||
| 	char *name; | 	char *name; | ||||||
|  |  | ||||||
|  | 	/* S_BOOLEAN, S_TRISTATE, ... */ | ||||||
| 	enum symbol_type type; | 	enum symbol_type type; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * The calculated value of the symbol. The SYMBOL_VALID bit is set in | ||||||
|  | 	 * 'flags' when this is up to date. Note that this value might differ | ||||||
|  | 	 * from the user value set in e.g. a .config file, due to visibility. | ||||||
|  | 	 */ | ||||||
| 	struct symbol_value curr; | 	struct symbol_value curr; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Values for the symbol provided from outside. def[S_DEF_USER] holds | ||||||
|  | 	 * the .config value. | ||||||
|  | 	 */ | ||||||
| 	struct symbol_value def[S_DEF_COUNT]; | 	struct symbol_value def[S_DEF_COUNT]; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * An upper bound on the tristate value the user can set for the symbol | ||||||
|  | 	 * if it is a boolean or tristate. Calculated from prompt dependencies, | ||||||
|  | 	 * which also inherit dependencies from enclosing menus, choices, and | ||||||
|  | 	 * ifs. If 'n', the user value will be ignored. | ||||||
|  | 	 * | ||||||
|  | 	 * Symbols lacking prompts always have visibility 'n'. | ||||||
|  | 	 */ | ||||||
| 	tristate visible; | 	tristate visible; | ||||||
|  |  | ||||||
|  | 	/* SYMBOL_* flags */ | ||||||
| 	int flags; | 	int flags; | ||||||
|  |  | ||||||
|  | 	/* List of properties. See prop_type. */ | ||||||
| 	struct property *prop; | 	struct property *prop; | ||||||
|  |  | ||||||
|  | 	/* Dependencies from enclosing menus, choices, and ifs */ | ||||||
| 	struct expr_value dir_dep; | 	struct expr_value dir_dep; | ||||||
|  |  | ||||||
|  | 	/* Reverse dependencies through being selected by other symbols */ | ||||||
| 	struct expr_value rev_dep; | 	struct expr_value rev_dep; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * "Weak" reverse dependencies through being implied by other symbols | ||||||
|  | 	 */ | ||||||
|  | 	struct expr_value implied; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #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 for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) | ||||||
|  |  | ||||||
| #define SYMBOL_CONST      0x0001  /* symbol is const */ | #define SYMBOL_CONST      0x0001  /* symbol is const */ | ||||||
| #define SYMBOL_CHECK      0x0008  /* used during dependency checking */ | #define SYMBOL_CHECK      0x0008  /* used during dependency checking */ | ||||||
| @@ -97,7 +141,8 @@ struct symbol { | |||||||
| #define SYMBOL_OPTIONAL   0x0100  /* choice is optional - values can be 'n' */ | #define SYMBOL_OPTIONAL   0x0100  /* choice is optional - values can be 'n' */ | ||||||
| #define SYMBOL_WRITE      0x0200  /* write symbol to file (KCONFIG_CONFIG) */ | #define SYMBOL_WRITE      0x0200  /* write symbol to file (KCONFIG_CONFIG) */ | ||||||
| #define SYMBOL_CHANGED    0x0400  /* ? */ | #define SYMBOL_CHANGED    0x0400  /* ? */ | ||||||
| #define SYMBOL_AUTO       0x1000  /* value from environment variable */ | #define SYMBOL_WRITTEN    0x0800  /* track info to avoid double-write to .config */ | ||||||
|  | #define SYMBOL_NO_WRITE   0x1000  /* Symbol for internal use only; it will not be written */ | ||||||
| #define SYMBOL_CHECKED    0x2000  /* used during dependency checking */ | #define SYMBOL_CHECKED    0x2000  /* used during dependency checking */ | ||||||
| #define SYMBOL_WARNED     0x8000  /* warning has been issued */ | #define SYMBOL_WARNED     0x8000  /* warning has been issued */ | ||||||
|  |  | ||||||
| @@ -127,24 +172,26 @@ struct symbol { | |||||||
|  * config BAZ |  * config BAZ | ||||||
|  *         int "BAZ Value" |  *         int "BAZ Value" | ||||||
|  *         range 1..255 |  *         range 1..255 | ||||||
|  |  * | ||||||
|  |  * Please, also check parser.y:print_symbol() when modifying the | ||||||
|  |  * list of property types! | ||||||
|  */ |  */ | ||||||
| enum prop_type { | enum prop_type { | ||||||
| 	P_UNKNOWN, | 	P_UNKNOWN, | ||||||
| 	P_PROMPT,   /* prompt "foo prompt" or "BAZ Value" */ | 	P_PROMPT,   /* prompt "foo prompt" or "BAZ Value" */ | ||||||
| 	P_COMMENT,  /* text associated with a comment */ | 	P_COMMENT,  /* text associated with a comment */ | ||||||
| 	P_MENU,     /* prompt associated with a menuconfig option */ | 	P_MENU,     /* prompt associated with a menu or menuconfig symbol */ | ||||||
| 	P_DEFAULT,  /* default y */ | 	P_DEFAULT,  /* default y */ | ||||||
| 	P_CHOICE,   /* choice value */ | 	P_CHOICE,   /* choice value */ | ||||||
| 	P_SELECT,   /* select BAR */ | 	P_SELECT,   /* select BAR */ | ||||||
|  | 	P_IMPLY,    /* imply BAR */ | ||||||
| 	P_RANGE,    /* range 7..100 (for a symbol) */ | 	P_RANGE,    /* range 7..100 (for a symbol) */ | ||||||
| 	P_ENV,      /* value from environment variable */ |  | ||||||
| 	P_SYMBOL,   /* where a symbol is defined */ | 	P_SYMBOL,   /* where a symbol is defined */ | ||||||
| 	P_RESET,	/* reset to defaults condition */ | 	P_RESET,	/* reset to defaults condition */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct property { | struct property { | ||||||
| 	struct property *next;     /* next property - null if last */ | 	struct property *next;     /* next property - null if last */ | ||||||
| 	struct symbol *sym;        /* the symbol for which the property is associated */ |  | ||||||
| 	enum prop_type type;       /* type of property */ | 	enum prop_type type;       /* type of property */ | ||||||
| 	const char *text;          /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */ | 	const char *text;          /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */ | ||||||
| 	struct expr_value visible; | 	struct expr_value visible; | ||||||
| @@ -165,22 +212,67 @@ struct property { | |||||||
| 	for (st = sym->prop; st; st = st->next) \ | 	for (st = sym->prop; st; st = st->next) \ | ||||||
| 		if (st->text) | 		if (st->text) | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Represents a node in the menu tree, as seen in e.g. menuconfig (though used | ||||||
|  |  * for all front ends). Each symbol, menu, etc. defined in the Kconfig files | ||||||
|  |  * gets a node. A symbol defined in multiple locations gets one node at each | ||||||
|  |  * location. | ||||||
|  |  */ | ||||||
| struct menu { | struct menu { | ||||||
|  | 	/* The next menu node at the same level */ | ||||||
| 	struct menu *next; | 	struct menu *next; | ||||||
|  |  | ||||||
|  | 	/* The parent menu node, corresponding to e.g. a menu or choice */ | ||||||
| 	struct menu *parent; | 	struct menu *parent; | ||||||
|  |  | ||||||
|  | 	/* The first child menu node, for e.g. menus and choices */ | ||||||
| 	struct menu *list; | 	struct menu *list; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * The symbol associated with the menu node. Choices are implemented as | ||||||
|  | 	 * a special kind of symbol. NULL for menus, comments, and ifs. | ||||||
|  | 	 */ | ||||||
| 	struct symbol *sym; | 	struct symbol *sym; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * The prompt associated with the node. This holds the prompt for a | ||||||
|  | 	 * symbol as well as the text for a menu or comment, along with the | ||||||
|  | 	 * type (P_PROMPT, P_MENU, etc.) | ||||||
|  | 	 */ | ||||||
| 	struct property *prompt; | 	struct property *prompt; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * 'visible if' dependencies. If more than one is given, they will be | ||||||
|  | 	 * ANDed together. | ||||||
|  | 	 */ | ||||||
| 	struct expr *visibility; | 	struct expr *visibility; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Ordinary dependencies from e.g. 'depends on' and 'if', ANDed | ||||||
|  | 	 * together | ||||||
|  | 	 */ | ||||||
| 	struct expr *dep; | 	struct expr *dep; | ||||||
|  |  | ||||||
|  | 	/* MENU_* flags */ | ||||||
| 	unsigned int flags; | 	unsigned int flags; | ||||||
|  |  | ||||||
|  | 	/* Any help text associated with the node */ | ||||||
| 	char *help; | 	char *help; | ||||||
|  |  | ||||||
|  | 	/* The location where the menu node appears in the Kconfig files */ | ||||||
| 	struct file *file; | 	struct file *file; | ||||||
| 	int lineno; | 	int lineno; | ||||||
|  |  | ||||||
|  | 	/* For use by front ends that need to store auxiliary data */ | ||||||
| 	void *data; | 	void *data; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Set on a menu node when the corresponding symbol changes state in some way. | ||||||
|  |  * Can be checked by front ends. | ||||||
|  |  */ | ||||||
| #define MENU_CHANGED		0x0001 | #define MENU_CHANGED		0x0001 | ||||||
|  |  | ||||||
| #define MENU_ROOT		0x0002 | #define MENU_ROOT		0x0002 | ||||||
|  |  | ||||||
| struct jump_key { | struct jump_key { | ||||||
| @@ -209,6 +301,7 @@ struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); | |||||||
| struct expr *expr_copy(const struct expr *org); | struct expr *expr_copy(const struct expr *org); | ||||||
| void expr_free(struct expr *e); | void expr_free(struct expr *e); | ||||||
| void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); | void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); | ||||||
|  | int expr_eq(struct expr *e1, struct expr *e2); | ||||||
| tristate expr_calc_value(struct expr *e); | tristate expr_calc_value(struct expr *e); | ||||||
| struct expr *expr_trans_bool(struct expr *e); | struct expr *expr_trans_bool(struct expr *e); | ||||||
| struct expr *expr_eliminate_dups(struct expr *e); | struct expr *expr_eliminate_dups(struct expr *e); | ||||||
| @@ -216,11 +309,12 @@ struct expr *expr_transform(struct expr *e); | |||||||
| int expr_contains_symbol(struct expr *dep, struct symbol *sym); | int expr_contains_symbol(struct expr *dep, struct symbol *sym); | ||||||
| bool expr_depends_symbol(struct expr *dep, struct symbol *sym); | bool expr_depends_symbol(struct expr *dep, struct symbol *sym); | ||||||
| struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); | struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); | ||||||
| struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2); |  | ||||||
|  |  | ||||||
| void expr_fprint(struct expr *e, FILE *out); | void expr_fprint(struct expr *e, FILE *out); | ||||||
| struct gstr; /* forward */ | struct gstr; /* forward */ | ||||||
| void expr_gstr_print(struct expr *e, struct gstr *gs); | void expr_gstr_print(struct expr *e, struct gstr *gs); | ||||||
|  | void expr_gstr_print_revdep(struct expr *e, struct gstr *gs, | ||||||
|  | 			    tristate pr_type, const char *title); | ||||||
|  |  | ||||||
| static inline int expr_is_yes(struct expr *e) | static inline int expr_is_yes(struct expr *e) | ||||||
| { | { | ||||||
|   | |||||||
| @@ -1,9 +1,11 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0 | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  * Released under the terms of the GNU GPL v2.0. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| static const char *xpm_load[] = { | #include "images.h" | ||||||
|  |  | ||||||
|  | const char *xpm_load[] = { | ||||||
| "22 22 5 1", | "22 22 5 1", | ||||||
| ". c None", | ". c None", | ||||||
| "# c #000000", | "# c #000000", | ||||||
| @@ -33,7 +35,7 @@ static const char *xpm_load[] = { | |||||||
| "###############.......", | "###############.......", | ||||||
| "......................"}; | "......................"}; | ||||||
|  |  | ||||||
| static const char *xpm_save[] = { | const char *xpm_save[] = { | ||||||
| "22 22 5 1", | "22 22 5 1", | ||||||
| ". c None", | ". c None", | ||||||
| "# c #000000", | "# c #000000", | ||||||
| @@ -63,7 +65,7 @@ static const char *xpm_save[] = { | |||||||
| "..##################..", | "..##################..", | ||||||
| "......................"}; | "......................"}; | ||||||
|  |  | ||||||
| static const char *xpm_back[] = { | const char *xpm_back[] = { | ||||||
| "22 22 3 1", | "22 22 3 1", | ||||||
| ". c None", | ". c None", | ||||||
| "# c #000083", | "# c #000083", | ||||||
| @@ -91,7 +93,7 @@ static const char *xpm_back[] = { | |||||||
| "......................", | "......................", | ||||||
| "......................"}; | "......................"}; | ||||||
|  |  | ||||||
| static const char *xpm_tree_view[] = { | const char *xpm_tree_view[] = { | ||||||
| "22 22 2 1", | "22 22 2 1", | ||||||
| ". c None", | ". c None", | ||||||
| "# c #000000", | "# c #000000", | ||||||
| @@ -118,7 +120,7 @@ static const char *xpm_tree_view[] = { | |||||||
| "......................", | "......................", | ||||||
| "......................"}; | "......................"}; | ||||||
|  |  | ||||||
| static const char *xpm_single_view[] = { | const char *xpm_single_view[] = { | ||||||
| "22 22 2 1", | "22 22 2 1", | ||||||
| ". c None", | ". c None", | ||||||
| "# c #000000", | "# c #000000", | ||||||
| @@ -145,7 +147,7 @@ static const char *xpm_single_view[] = { | |||||||
| "......................", | "......................", | ||||||
| "......................"}; | "......................"}; | ||||||
|  |  | ||||||
| static const char *xpm_split_view[] = { | const char *xpm_split_view[] = { | ||||||
| "22 22 2 1", | "22 22 2 1", | ||||||
| ". c None", | ". c None", | ||||||
| "# c #000000", | "# c #000000", | ||||||
| @@ -172,7 +174,7 @@ static const char *xpm_split_view[] = { | |||||||
| "......................", | "......................", | ||||||
| "......................"}; | "......................"}; | ||||||
|  |  | ||||||
| static const char *xpm_symbol_no[] = { | const char *xpm_symbol_no[] = { | ||||||
| "12 12 2 1", | "12 12 2 1", | ||||||
| "  c white", | "  c white", | ||||||
| ". c black", | ". c black", | ||||||
| @@ -189,7 +191,7 @@ static const char *xpm_symbol_no[] = { | |||||||
| " .......... ", | " .......... ", | ||||||
| "            "}; | "            "}; | ||||||
|  |  | ||||||
| static const char *xpm_symbol_mod[] = { | const char *xpm_symbol_mod[] = { | ||||||
| "12 12 2 1", | "12 12 2 1", | ||||||
| "  c white", | "  c white", | ||||||
| ". c black", | ". c black", | ||||||
| @@ -206,7 +208,7 @@ static const char *xpm_symbol_mod[] = { | |||||||
| " .......... ", | " .......... ", | ||||||
| "            "}; | "            "}; | ||||||
|  |  | ||||||
| static const char *xpm_symbol_yes[] = { | const char *xpm_symbol_yes[] = { | ||||||
| "12 12 2 1", | "12 12 2 1", | ||||||
| "  c white", | "  c white", | ||||||
| ". c black", | ". c black", | ||||||
| @@ -223,7 +225,7 @@ static const char *xpm_symbol_yes[] = { | |||||||
| " .......... ", | " .......... ", | ||||||
| "            "}; | "            "}; | ||||||
|  |  | ||||||
| static const char *xpm_choice_no[] = { | const char *xpm_choice_no[] = { | ||||||
| "12 12 2 1", | "12 12 2 1", | ||||||
| "  c white", | "  c white", | ||||||
| ". c black", | ". c black", | ||||||
| @@ -240,7 +242,7 @@ static const char *xpm_choice_no[] = { | |||||||
| "    ....    ", | "    ....    ", | ||||||
| "            "}; | "            "}; | ||||||
|  |  | ||||||
| static const char *xpm_choice_yes[] = { | const char *xpm_choice_yes[] = { | ||||||
| "12 12 2 1", | "12 12 2 1", | ||||||
| "  c white", | "  c white", | ||||||
| ". c black", | ". c black", | ||||||
| @@ -257,7 +259,7 @@ static const char *xpm_choice_yes[] = { | |||||||
| "    ....    ", | "    ....    ", | ||||||
| "            "}; | "            "}; | ||||||
|  |  | ||||||
| static const char *xpm_menu[] = { | const char *xpm_menu[] = { | ||||||
| "12 12 2 1", | "12 12 2 1", | ||||||
| "  c white", | "  c white", | ||||||
| ". c black", | ". c black", | ||||||
| @@ -274,7 +276,7 @@ static const char *xpm_menu[] = { | |||||||
| " .......... ", | " .......... ", | ||||||
| "            "}; | "            "}; | ||||||
|  |  | ||||||
| static const char *xpm_menu_inv[] = { | const char *xpm_menu_inv[] = { | ||||||
| "12 12 2 1", | "12 12 2 1", | ||||||
| "  c white", | "  c white", | ||||||
| ". c black", | ". c black", | ||||||
| @@ -291,7 +293,7 @@ static const char *xpm_menu_inv[] = { | |||||||
| " .......... ", | " .......... ", | ||||||
| "            "}; | "            "}; | ||||||
|  |  | ||||||
| static const char *xpm_menuback[] = { | const char *xpm_menuback[] = { | ||||||
| "12 12 2 1", | "12 12 2 1", | ||||||
| "  c white", | "  c white", | ||||||
| ". c black", | ". c black", | ||||||
| @@ -308,7 +310,7 @@ static const char *xpm_menuback[] = { | |||||||
| " .......... ", | " .......... ", | ||||||
| "            "}; | "            "}; | ||||||
|  |  | ||||||
| static const char *xpm_void[] = { | const char *xpm_void[] = { | ||||||
| "12 12 2 1", | "12 12 2 1", | ||||||
| "  c white", | "  c white", | ||||||
| ". c black", | ". c black", | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								scripts/config/images.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								scripts/config/images.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | /* SPDX-License-Identifier: GPL-2.0 */ | ||||||
|  | /* | ||||||
|  |  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef IMAGES_H | ||||||
|  | #define IMAGES_H | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | extern const char *xpm_load[]; | ||||||
|  | extern const char *xpm_save[]; | ||||||
|  | extern const char *xpm_back[]; | ||||||
|  | extern const char *xpm_tree_view[]; | ||||||
|  | extern const char *xpm_single_view[]; | ||||||
|  | extern const char *xpm_split_view[]; | ||||||
|  | extern const char *xpm_symbol_no[]; | ||||||
|  | extern const char *xpm_symbol_mod[]; | ||||||
|  | extern const char *xpm_symbol_yes[]; | ||||||
|  | extern const char *xpm_choice_no[]; | ||||||
|  | extern const char *xpm_choice_yes[]; | ||||||
|  | extern const char *xpm_menu[]; | ||||||
|  | extern const char *xpm_menu_inv[]; | ||||||
|  | extern const char *xpm_menuback[]; | ||||||
|  | extern const char *xpm_void[]; | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif /* IMAGES_H */ | ||||||
| @@ -1,13 +1,13 @@ | |||||||
| %option nostdinit noyywrap never-interactive full ecs | /* SPDX-License-Identifier: GPL-2.0 */ | ||||||
| %option 8bit nodefault perf-report perf-report |  | ||||||
| %option noinput |  | ||||||
| %x COMMAND HELP STRING PARAM |  | ||||||
| %{ |  | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  * Released under the terms of the GNU GPL v2.0. |  | ||||||
|  */ |  */ | ||||||
|  | %option nostdinit noyywrap never-interactive full ecs | ||||||
|  | %option 8bit nodefault yylineno | ||||||
|  | %x ASSIGN_VAL HELP STRING | ||||||
|  | %{ | ||||||
| 
 | 
 | ||||||
|  | #include <assert.h> | ||||||
| #include <limits.h> | #include <limits.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| @@ -17,6 +17,9 @@ | |||||||
| #include <libgen.h> | #include <libgen.h> | ||||||
| 
 | 
 | ||||||
| #include "lkc.h" | #include "lkc.h" | ||||||
|  | #include "parser.tab.h" | ||||||
|  | 
 | ||||||
|  | #define YY_DECL		static int yylex1(void) | ||||||
| 
 | 
 | ||||||
| #define START_STRSIZE	16 | #define START_STRSIZE	16 | ||||||
| 
 | 
 | ||||||
| @@ -25,6 +28,8 @@ static struct { | |||||||
| 	int lineno; | 	int lineno; | ||||||
| } current_pos; | } current_pos; | ||||||
| 
 | 
 | ||||||
|  | static int prev_prev_token = T_EOL; | ||||||
|  | static int prev_token = T_EOL; | ||||||
| static char *text; | static char *text; | ||||||
| static int text_size, text_asize; | static int text_size, text_asize; | ||||||
| 
 | 
 | ||||||
| @@ -37,6 +42,8 @@ struct buffer *current_buf; | |||||||
| 
 | 
 | ||||||
| static int last_ts, first_ts; | static int last_ts, first_ts; | ||||||
| 
 | 
 | ||||||
|  | static char *expand_token(const char *in, size_t n); | ||||||
|  | static void append_expanded_string(const char *in); | ||||||
| static void zconf_endhelp(void); | static void zconf_endhelp(void); | ||||||
| static void zconf_endfile(void); | static void zconf_endfile(void); | ||||||
| 
 | 
 | ||||||
| @@ -54,7 +61,7 @@ static void append_string(const char *str, int size) | |||||||
| 	if (new_size > text_asize) { | 	if (new_size > text_asize) { | ||||||
| 		new_size += START_STRSIZE - 1; | 		new_size += START_STRSIZE - 1; | ||||||
| 		new_size &= -START_STRSIZE; | 		new_size &= -START_STRSIZE; | ||||||
| 		text = realloc(text, new_size); | 		text = xrealloc(text, new_size); | ||||||
| 		text_asize = new_size; | 		text_asize = new_size; | ||||||
| 	} | 	} | ||||||
| 	memcpy(text + text_size, str, size); | 	memcpy(text + text_size, str, size); | ||||||
| @@ -73,7 +80,7 @@ static void warn_ignored_character(char chr) | |||||||
| { | { | ||||||
| 	fprintf(stderr, | 	fprintf(stderr, | ||||||
| 	        "%s:%d:warning: ignoring unsupported character '%c'\n", | 	        "%s:%d:warning: ignoring unsupported character '%c'\n", | ||||||
| 	        zconf_curname(), zconf_lineno(), chr); | 	        current_file->name, yylineno, chr); | ||||||
| } | } | ||||||
| %} | %} | ||||||
| 
 | 
 | ||||||
| @@ -83,116 +90,114 @@ n	[A-Za-z0-9_-] | |||||||
| 	int str = 0; | 	int str = 0; | ||||||
| 	int ts, i; | 	int ts, i; | ||||||
| 
 | 
 | ||||||
| [ \t]*#.*\n	| | #.*			/* ignore comment */ | ||||||
| [ \t]*\n	{ | [ \t]*			/* whitespaces */ | ||||||
| 	current_file->lineno++; | \\\n			/* escaped new line */ | ||||||
| 	return T_EOL; | \n			return T_EOL; | ||||||
| } | "allnoconfig_y"		return T_ALLNOCONFIG_Y; | ||||||
| [ \t]*#.* | "bool"			return T_BOOL; | ||||||
| 
 | "choice"		return T_CHOICE; | ||||||
| 
 | "comment"		return T_COMMENT; | ||||||
| [ \t]+	{ | "config"		return T_CONFIG; | ||||||
| 	BEGIN(COMMAND); | "def_bool"		return T_DEF_BOOL; | ||||||
| } | "def_tristate"		return T_DEF_TRISTATE; | ||||||
| 
 | "default"		return T_DEFAULT; | ||||||
| .	{ | "defconfig_list"	return T_DEFCONFIG_LIST; | ||||||
| 	unput(yytext[0]); | "depends"		return T_DEPENDS; | ||||||
| 	BEGIN(COMMAND); | "endchoice"		return T_ENDCHOICE; | ||||||
| } | "endif"			return T_ENDIF; | ||||||
| 
 | "endmenu"		return T_ENDMENU; | ||||||
| 
 | "help"|"---help---"	return T_HELP; | ||||||
| <COMMAND>{ | "hex"			return T_HEX; | ||||||
| 	{n}+	{ | "if"			return T_IF; | ||||||
| 		const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); | "imply"			return T_IMPLY; | ||||||
| 		BEGIN(PARAM); | "int"			return T_INT; | ||||||
| 		current_pos.file = current_file; | "mainmenu"		return T_MAINMENU; | ||||||
| 		current_pos.lineno = current_file->lineno; | "menu"			return T_MENU; | ||||||
| 		if (id && id->flags & TF_COMMAND) { | "menuconfig"		return T_MENUCONFIG; | ||||||
| 			zconflval.id = id; | "modules"		return T_MODULES; | ||||||
| 			return id->token; | "on"			return T_ON; | ||||||
| 		} | "option"		return T_OPTION; | ||||||
| 		alloc_string(yytext, yyleng); | "optional"		return T_OPTIONAL; | ||||||
| 		zconflval.string = text; | "prompt"		return T_PROMPT; | ||||||
| 		return T_WORD; | "range"			return T_RANGE; | ||||||
| 	} | "reset"			return T_RESET; | ||||||
| 	.	warn_ignored_character(*yytext); | "select"		return T_SELECT; | ||||||
| 	\n	{ | "source"		return T_SOURCE; | ||||||
| 		BEGIN(INITIAL); | "string"		return T_STRING; | ||||||
| 		current_file->lineno++; | "tristate"		return T_TRISTATE; | ||||||
| 		return T_EOL; | "visible"		return T_VISIBLE; | ||||||
| 	} | "||"			return T_OR; | ||||||
| } | "&&"			return T_AND; | ||||||
| 
 | "="			return T_EQUAL; | ||||||
| <PARAM>{ | "!="			return T_UNEQUAL; | ||||||
| 	"&&"	return T_AND; | "<"			return T_LESS; | ||||||
| 	"||"	return T_OR; | "<="			return T_LESS_EQUAL; | ||||||
| 	"("	return T_OPEN_PAREN; | ">"			return T_GREATER; | ||||||
| 	")"	return T_CLOSE_PAREN; | ">="			return T_GREATER_EQUAL; | ||||||
| 	"!"	return T_NOT; | "!"			return T_NOT; | ||||||
| 	"="	return T_EQUAL; | "("			return T_OPEN_PAREN; | ||||||
| 	"!="	return T_UNEQUAL; | ")"			return T_CLOSE_PAREN; | ||||||
| 	"<="	return T_LESS_EQUAL; | ":="			return T_COLON_EQUAL; | ||||||
| 	">="	return T_GREATER_EQUAL; | "+="			return T_PLUS_EQUAL; | ||||||
| 	"<"	return T_LESS; | \"|\'			{ | ||||||
| 	">"	return T_GREATER; |  | ||||||
| 	\"|\'	{ |  | ||||||
| 				str = yytext[0]; | 				str = yytext[0]; | ||||||
| 				new_string(); | 				new_string(); | ||||||
| 				BEGIN(STRING); | 				BEGIN(STRING); | ||||||
| 			} | 			} | ||||||
| 	\n	BEGIN(INITIAL); current_file->lineno++; return T_EOL; | ({n}|[/.])+		{ | ||||||
| 	({n}|[/.])+	{ |  | ||||||
| 		const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); |  | ||||||
| 		if (id && id->flags & TF_PARAM) { |  | ||||||
| 			zconflval.id = id; |  | ||||||
| 			return id->token; |  | ||||||
| 		} |  | ||||||
| 				alloc_string(yytext, yyleng); | 				alloc_string(yytext, yyleng); | ||||||
| 		zconflval.string = text; | 				yylval.string = text; | ||||||
| 				return T_WORD; | 				return T_WORD; | ||||||
| 			} | 			} | ||||||
| 	#.*	/* comment */ | ({n}|[/.$])+		{ | ||||||
| 	\\\n	current_file->lineno++; | 				/* this token includes at least one '$' */ | ||||||
| 	[[:blank:]]+ | 				yylval.string = expand_token(yytext, yyleng); | ||||||
| 	.	warn_ignored_character(*yytext); | 				if (strlen(yylval.string)) | ||||||
| 	<<EOF>> { | 					return T_WORD; | ||||||
| 		BEGIN(INITIAL); | 				free(yylval.string); | ||||||
| 			} | 			} | ||||||
|  | .			warn_ignored_character(*yytext); | ||||||
|  | 
 | ||||||
|  | <ASSIGN_VAL>{ | ||||||
|  | 	[^[:blank:]\n]+.*	{ | ||||||
|  | 		alloc_string(yytext, yyleng); | ||||||
|  | 		yylval.string = text; | ||||||
|  | 		return T_ASSIGN_VAL; | ||||||
|  | 	} | ||||||
|  | 	\n	{ BEGIN(INITIAL); return T_EOL; } | ||||||
|  | 	. | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| <STRING>{ | <STRING>{ | ||||||
| 	[^'"\\\n]+/\n	{ | 	"$".*	append_expanded_string(yytext); | ||||||
|  | 	[^$'"\\\n]+	{ | ||||||
| 		append_string(yytext, yyleng); | 		append_string(yytext, yyleng); | ||||||
| 		zconflval.string = text; |  | ||||||
| 		return T_WORD_QUOTE; |  | ||||||
| 	} |  | ||||||
| 	[^'"\\\n]+	{ |  | ||||||
| 		append_string(yytext, yyleng); |  | ||||||
| 	} |  | ||||||
| 	\\.?/\n	{ |  | ||||||
| 		append_string(yytext + 1, yyleng - 1); |  | ||||||
| 		zconflval.string = text; |  | ||||||
| 		return T_WORD_QUOTE; |  | ||||||
| 	} | 	} | ||||||
| 	\\.?	{ | 	\\.?	{ | ||||||
| 		append_string(yytext + 1, yyleng - 1); | 		append_string(yytext + 1, yyleng - 1); | ||||||
| 	} | 	} | ||||||
| 	\'|\"	{ | 	\'|\"	{ | ||||||
| 		if (str == yytext[0]) { | 		if (str == yytext[0]) { | ||||||
| 			BEGIN(PARAM); | 			BEGIN(INITIAL); | ||||||
| 			zconflval.string = text; | 			yylval.string = text; | ||||||
| 			return T_WORD_QUOTE; | 			return T_WORD_QUOTE; | ||||||
| 		} else | 		} else | ||||||
| 			append_string(yytext, 1); | 			append_string(yytext, 1); | ||||||
| 	} | 	} | ||||||
| 	\n	{ | 	\n	{ | ||||||
| 		printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); | 		fprintf(stderr, | ||||||
| 		current_file->lineno++; | 			"%s:%d:warning: multi-line strings not supported\n", | ||||||
|  | 			zconf_curname(), zconf_lineno()); | ||||||
|  | 		unput('\n'); | ||||||
| 		BEGIN(INITIAL); | 		BEGIN(INITIAL); | ||||||
| 		return T_EOL; | 		yylval.string = text; | ||||||
|  | 		return T_WORD_QUOTE; | ||||||
| 	} | 	} | ||||||
| 	<<EOF>>	{ | 	<<EOF>>	{ | ||||||
| 		BEGIN(INITIAL); | 		BEGIN(INITIAL); | ||||||
|  | 		yylval.string = text; | ||||||
|  | 		return T_WORD_QUOTE; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @@ -220,12 +225,10 @@ n	[A-Za-z0-9_-] | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	[ \t]*\n/[^ \t\n] { | 	[ \t]*\n/[^ \t\n] { | ||||||
| 		current_file->lineno++; |  | ||||||
| 		zconf_endhelp(); | 		zconf_endhelp(); | ||||||
| 		return T_HELPTEXT; | 		return T_HELPTEXT; | ||||||
| 	} | 	} | ||||||
| 	[ \t]*\n	{ | 	[ \t]*\n	{ | ||||||
| 		current_file->lineno++; |  | ||||||
| 		append_string("\n", 1); | 		append_string("\n", 1); | ||||||
| 	} | 	} | ||||||
| 	[^ \t\n].* { | 	[^ \t\n].* { | ||||||
| @@ -245,6 +248,12 @@ n	[A-Za-z0-9_-] | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| <<EOF>>	{ | <<EOF>>	{ | ||||||
|  | 	BEGIN(INITIAL); | ||||||
|  | 
 | ||||||
|  | 	if (prev_token != T_EOL && prev_token != T_HELPTEXT) | ||||||
|  | 		fprintf(stderr, "%s:%d:warning: no new line at end of file\n", | ||||||
|  | 			current_file->name, yylineno); | ||||||
|  | 
 | ||||||
| 	if (current_file) { | 	if (current_file) { | ||||||
| 		zconf_endfile(); | 		zconf_endfile(); | ||||||
| 		return T_EOL; | 		return T_EOL; | ||||||
| @@ -254,6 +263,93 @@ n	[A-Za-z0-9_-] | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| %% | %% | ||||||
|  | 
 | ||||||
|  | /* second stage lexer */ | ||||||
|  | int yylex(void) | ||||||
|  | { | ||||||
|  | 	int token; | ||||||
|  | 
 | ||||||
|  | repeat: | ||||||
|  | 	token = yylex1(); | ||||||
|  | 
 | ||||||
|  | 	if (prev_token == T_EOL || prev_token == T_HELPTEXT) { | ||||||
|  | 		if (token == T_EOL) { | ||||||
|  | 			/* Do not pass unneeded T_EOL to the parser. */ | ||||||
|  | 			goto repeat; | ||||||
|  | 		} else { | ||||||
|  | 			/* | ||||||
|  | 			 * For the parser, update file/lineno at the first token | ||||||
|  | 			 * of each statement. Generally, \n is a statement | ||||||
|  | 			 * terminator in Kconfig, but it is not always true | ||||||
|  | 			 * because \n could be escaped by a backslash. | ||||||
|  | 			 */ | ||||||
|  | 			current_pos.file = current_file; | ||||||
|  | 			current_pos.lineno = yylineno; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (prev_prev_token == T_EOL && prev_token == T_WORD && | ||||||
|  | 	    (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL)) | ||||||
|  | 		BEGIN(ASSIGN_VAL); | ||||||
|  | 
 | ||||||
|  | 	prev_prev_token = prev_token; | ||||||
|  | 	prev_token = token; | ||||||
|  | 
 | ||||||
|  | 	return token; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static char *expand_token(const char *in, size_t n) | ||||||
|  | { | ||||||
|  | 	char *out; | ||||||
|  | 	int c; | ||||||
|  | 	char c2; | ||||||
|  | 	const char *rest, *end; | ||||||
|  | 
 | ||||||
|  | 	new_string(); | ||||||
|  | 	append_string(in, n); | ||||||
|  | 
 | ||||||
|  | 	/* get the whole line because we do not know the end of token. */ | ||||||
|  | 	while ((c = input()) != EOF) { | ||||||
|  | 		if (c == '\n') { | ||||||
|  | 			unput(c); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		c2 = c; | ||||||
|  | 		append_string(&c2, 1); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	rest = text; | ||||||
|  | 	out = expand_one_token(&rest); | ||||||
|  | 
 | ||||||
|  | 	/* push back unused characters to the input stream */ | ||||||
|  | 	end = rest + strlen(rest); | ||||||
|  | 	while (end > rest) | ||||||
|  | 		unput(*--end); | ||||||
|  | 
 | ||||||
|  | 	free(text); | ||||||
|  | 
 | ||||||
|  | 	return out; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void append_expanded_string(const char *str) | ||||||
|  | { | ||||||
|  | 	const char *end; | ||||||
|  | 	char *res; | ||||||
|  | 
 | ||||||
|  | 	str++; | ||||||
|  | 
 | ||||||
|  | 	res = expand_dollar(&str); | ||||||
|  | 
 | ||||||
|  | 	/* push back unused characters to the input stream */ | ||||||
|  | 	end = str + strlen(str); | ||||||
|  | 	while (end > str) | ||||||
|  | 		unput(*--end); | ||||||
|  | 
 | ||||||
|  | 	append_string(res, strlen(res)); | ||||||
|  | 
 | ||||||
|  | 	free(res); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void zconf_starthelp(void) | void zconf_starthelp(void) | ||||||
| { | { | ||||||
| 	new_string(); | 	new_string(); | ||||||
| @@ -263,7 +359,7 @@ void zconf_starthelp(void) | |||||||
| 
 | 
 | ||||||
| static void zconf_endhelp(void) | static void zconf_endhelp(void) | ||||||
| { | { | ||||||
| 	zconflval.string = text; | 	yylval.string = text; | ||||||
| 	BEGIN(INITIAL); | 	BEGIN(INITIAL); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @@ -285,7 +381,8 @@ FILE *zconf_fopen(const char *name) | |||||||
| 	if (!f && name != NULL && name[0] != '/') { | 	if (!f && name != NULL && name[0] != '/') { | ||||||
| 		env = getenv(SRCTREE); | 		env = getenv(SRCTREE); | ||||||
| 		if (env) { | 		if (env) { | ||||||
| 			sprintf(fullname, "%s/%s", env, name); | 			snprintf(fullname, sizeof(fullname), | ||||||
|  | 				 "%s/%s", env, name); | ||||||
| 			f = fopen(fullname, "r"); | 			f = fopen(fullname, "r"); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -296,7 +393,7 @@ void zconf_initscan(const char *name) | |||||||
| { | { | ||||||
| 	yyin = zconf_fopen(name); | 	yyin = zconf_fopen(name); | ||||||
| 	if (!yyin) { | 	if (!yyin) { | ||||||
| 		printf("can't find file %s\n", name); | 		fprintf(stderr, "can't find file %s\n", name); | ||||||
| 		exit(1); | 		exit(1); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @@ -304,7 +401,7 @@ void zconf_initscan(const char *name) | |||||||
| 	memset(current_buf, 0, sizeof(*current_buf)); | 	memset(current_buf, 0, sizeof(*current_buf)); | ||||||
| 
 | 
 | ||||||
| 	current_file = file_lookup(name); | 	current_file = file_lookup(name); | ||||||
| 	current_file->lineno = 1; | 	yylineno = 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void __zconf_nextfile(const char *name) | static void __zconf_nextfile(const char *name) | ||||||
| @@ -317,7 +414,7 @@ static void __zconf_nextfile(const char *name) | |||||||
| 	current_buf->state = YY_CURRENT_BUFFER; | 	current_buf->state = YY_CURRENT_BUFFER; | ||||||
| 	yyin = zconf_fopen(file->name); | 	yyin = zconf_fopen(file->name); | ||||||
| 	if (!yyin) { | 	if (!yyin) { | ||||||
| 		printf("%s:%d: can't open file \"%s\"\n", | 		fprintf(stderr, "%s:%d: can't open file \"%s\"\n", | ||||||
| 			zconf_curname(), zconf_lineno(), file->name); | 			zconf_curname(), zconf_lineno(), file->name); | ||||||
| 		exit(1); | 		exit(1); | ||||||
| 	} | 	} | ||||||
| @@ -325,27 +422,26 @@ static void __zconf_nextfile(const char *name) | |||||||
| 	buf->parent = current_buf; | 	buf->parent = current_buf; | ||||||
| 	current_buf = buf; | 	current_buf = buf; | ||||||
| 
 | 
 | ||||||
| 	for (iter = current_file->parent; iter; iter = iter->parent ) { | 	current_file->lineno = yylineno; | ||||||
| 		if (!strcmp(current_file->name,iter->name) ) { | 	file->parent = current_file; | ||||||
| 			printf("%s:%d: recursive inclusion detected. " | 
 | ||||||
| 			       "Inclusion path:\n  current file : '%s'\n", | 	for (iter = current_file; iter; iter = iter->parent) { | ||||||
| 			       zconf_curname(), zconf_lineno(), | 		if (!strcmp(iter->name, file->name)) { | ||||||
| 			       zconf_curname()); | 			fprintf(stderr, | ||||||
| 			iter = current_file->parent; | 				"Recursive inclusion detected.\n" | ||||||
| 			while (iter && \ | 				"Inclusion path:\n" | ||||||
| 			       strcmp(iter->name,current_file->name)) { | 				"  current file : %s\n", file->name); | ||||||
| 				printf("  included from: '%s:%d'\n", | 			iter = file; | ||||||
| 				       iter->name, iter->lineno-1); | 			do { | ||||||
| 				iter = iter->parent; | 				iter = iter->parent; | ||||||
| 			} | 				fprintf(stderr, "  included from: %s:%d\n", | ||||||
| 			if (iter) | 					iter->name, iter->lineno - 1); | ||||||
| 				printf("  included from: '%s:%d'\n", | 			} while (strcmp(iter->name, file->name)); | ||||||
| 				       iter->name, iter->lineno+1); |  | ||||||
| 			exit(1); | 			exit(1); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	file->lineno = 1; | 
 | ||||||
| 	file->parent = current_file; | 	yylineno = 1; | ||||||
| 	current_file = file; | 	current_file = file; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @@ -405,6 +501,8 @@ static void zconf_endfile(void) | |||||||
| 	struct buffer *parent; | 	struct buffer *parent; | ||||||
| 
 | 
 | ||||||
| 	current_file = current_file->parent; | 	current_file = current_file->parent; | ||||||
|  | 	if (current_file) | ||||||
|  | 		yylineno = current_file->lineno; | ||||||
| 
 | 
 | ||||||
| 	parent = current_buf->parent; | 	parent = current_buf->parent; | ||||||
| 	if (parent) { | 	if (parent) { | ||||||
							
								
								
									
										4499
									
								
								scripts/config/lexer.lex.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4499
									
								
								scripts/config/lexer.lex.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,3 +1,4 @@ | |||||||
|  | /* SPDX-License-Identifier: GPL-2.0 */ | ||||||
| #ifndef LIST_H | #ifndef LIST_H | ||||||
| #define LIST_H | #define LIST_H | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
|  | /* SPDX-License-Identifier: GPL-2.0 */ | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  * Released under the terms of the GNU GPL v2.0. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef LKC_H | #ifndef LKC_H | ||||||
| @@ -8,15 +8,6 @@ | |||||||
|  |  | ||||||
| #include "expr.h" | #include "expr.h" | ||||||
|  |  | ||||||
| #ifndef KBUILD_NO_NLS |  | ||||||
| # include <libintl.h> |  | ||||||
| #else |  | ||||||
| static inline const char *gettext(const char *txt) { return txt; } |  | ||||||
| static inline void textdomain(const char *domainname) {} |  | ||||||
| static inline void bindtextdomain(const char *name, const char *dir) {} |  | ||||||
| static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
| @@ -29,11 +20,6 @@ extern "C" { | |||||||
| #define PACKAGE "linux" | #define PACKAGE "linux" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #define LOCALEDIR "/usr/share/locale" |  | ||||||
|  |  | ||||||
| #define _(text) gettext(text) |  | ||||||
| #define N_(text) (text) |  | ||||||
|  |  | ||||||
| #ifndef CONFIG_ | #ifndef CONFIG_ | ||||||
| #define CONFIG_ "CONFIG_" | #define CONFIG_ "CONFIG_" | ||||||
| #endif | #endif | ||||||
| @@ -44,30 +30,17 @@ static inline const char *CONFIG_prefix(void) | |||||||
| #undef CONFIG_ | #undef CONFIG_ | ||||||
| #define CONFIG_ CONFIG_prefix() | #define CONFIG_ CONFIG_prefix() | ||||||
|  |  | ||||||
| #define TF_COMMAND	0x0001 |  | ||||||
| #define TF_PARAM	0x0002 |  | ||||||
| #define TF_OPTION	0x0004 |  | ||||||
|  |  | ||||||
| enum conf_def_mode { | enum conf_def_mode { | ||||||
| 	def_default, | 	def_default, | ||||||
| 	def_yes, | 	def_yes, | ||||||
| 	def_mod, | 	def_mod, | ||||||
|  | 	def_y2m, | ||||||
|  | 	def_m2y, | ||||||
| 	def_no, | 	def_no, | ||||||
| 	def_random | 	def_random | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define T_OPT_MODULES		1 | extern int yylineno; | ||||||
| #define T_OPT_DEFCONFIG_LIST	2 |  | ||||||
| #define T_OPT_ENV		3 |  | ||||||
| #define T_OPT_ALLNOCONFIG_Y	4 |  | ||||||
|  |  | ||||||
| struct kconf_id { |  | ||||||
| 	int name; |  | ||||||
| 	int token; |  | ||||||
| 	unsigned int flags; |  | ||||||
| 	enum symbol_type stype; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| void zconfdump(FILE *out); | void zconfdump(FILE *out); | ||||||
| void zconf_starthelp(void); | void zconf_starthelp(void); | ||||||
| FILE *zconf_fopen(const char *name); | FILE *zconf_fopen(const char *name); | ||||||
| @@ -78,11 +51,10 @@ const char *zconf_curname(void); | |||||||
|  |  | ||||||
| /* confdata.c */ | /* confdata.c */ | ||||||
| const char *conf_get_configname(void); | const char *conf_get_configname(void); | ||||||
| const char *conf_get_autoconfig_name(void); |  | ||||||
| char *conf_get_default_confname(void); |  | ||||||
| void sym_set_change_count(int count); | void sym_set_change_count(int count); | ||||||
| void sym_add_change_count(int count); | void sym_add_change_count(int count); | ||||||
| bool conf_set_all_new_symbols(enum conf_def_mode mode); | bool conf_set_all_new_symbols(enum conf_def_mode mode); | ||||||
|  | void conf_rewrite_mod_or_yes(enum conf_def_mode mode); | ||||||
| void set_all_choice_values(struct symbol *csym); | void set_all_choice_values(struct symbol *csym); | ||||||
|  |  | ||||||
| /* confdata.c and expr.c */ | /* confdata.c and expr.c */ | ||||||
| @@ -100,22 +72,28 @@ void menu_warn(struct menu *menu, const char *fmt, ...); | |||||||
| struct menu *menu_add_menu(void); | struct menu *menu_add_menu(void); | ||||||
| void menu_end_menu(void); | void menu_end_menu(void); | ||||||
| void menu_add_entry(struct symbol *sym); | void menu_add_entry(struct symbol *sym); | ||||||
| void menu_end_entry(void); |  | ||||||
| void menu_add_dep(struct expr *dep); | void menu_add_dep(struct expr *dep); | ||||||
| void menu_add_visibility(struct expr *dep); | void menu_add_visibility(struct expr *dep); | ||||||
| struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep); | struct property *menu_add_prop(enum prop_type type, struct expr *expr, struct expr *dep); | ||||||
| struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); | struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); | ||||||
| void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); | void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); | ||||||
| void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); | void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); | ||||||
| void menu_add_option(int token, char *arg); | void menu_add_option_modules(void); | ||||||
|  | void menu_add_option_defconfig_list(void); | ||||||
|  | void menu_add_option_allnoconfig_y(void); | ||||||
| void menu_finalize(struct menu *parent); | void menu_finalize(struct menu *parent); | ||||||
| void menu_set_type(int type); | void menu_set_type(int type); | ||||||
|  |  | ||||||
| /* util.c */ | /* util.c */ | ||||||
| struct file *file_lookup(const char *name); | struct file *file_lookup(const char *name); | ||||||
| int file_write_dep(const char *name); |  | ||||||
| void *xmalloc(size_t size); | void *xmalloc(size_t size); | ||||||
| void *xcalloc(size_t nmemb, size_t size); | void *xcalloc(size_t nmemb, size_t size); | ||||||
|  | void *xrealloc(void *p, size_t size); | ||||||
|  | char *xstrdup(const char *s); | ||||||
|  | char *xstrndup(const char *s, size_t n); | ||||||
|  |  | ||||||
|  | /* lexer.l */ | ||||||
|  | int yylex(void); | ||||||
|  |  | ||||||
| struct gstr { | struct gstr { | ||||||
| 	size_t len; | 	size_t len; | ||||||
| @@ -133,16 +111,12 @@ void str_printf(struct gstr *gs, const char *fmt, ...); | |||||||
| const char *str_get(struct gstr *gs); | const char *str_get(struct gstr *gs); | ||||||
|  |  | ||||||
| /* symbol.c */ | /* symbol.c */ | ||||||
| extern struct expr *sym_env_list; |  | ||||||
|  |  | ||||||
| void sym_init(void); |  | ||||||
| void sym_clear_all_valid(void); | void sym_clear_all_valid(void); | ||||||
| struct symbol *sym_choice_default(struct symbol *sym); | struct symbol *sym_choice_default(struct symbol *sym); | ||||||
|  | struct property *sym_get_range_prop(struct symbol *sym); | ||||||
| const char *sym_get_string_default(struct symbol *sym); | const char *sym_get_string_default(struct symbol *sym); | ||||||
| struct symbol *sym_check_deps(struct symbol *sym); | struct symbol *sym_check_deps(struct symbol *sym); | ||||||
| struct property *prop_alloc(enum prop_type type, struct symbol *sym); |  | ||||||
| struct symbol *prop_get_symbol(struct property *prop); | struct symbol *prop_get_symbol(struct property *prop); | ||||||
| struct property *sym_get_env_prop(struct symbol *sym); |  | ||||||
|  |  | ||||||
| static inline tristate sym_get_tristate_value(struct symbol *sym) | static inline tristate sym_get_tristate_value(struct symbol *sym) | ||||||
| { | { | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | /* SPDX-License-Identifier: GPL-2.0 */ | ||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
|  |  | ||||||
| /* confdata.c */ | /* confdata.c */ | ||||||
| @@ -7,10 +8,10 @@ int conf_read_simple(const char *name, int); | |||||||
| void conf_reset(int def); | void conf_reset(int def); | ||||||
| int conf_write_defconfig(const char *name); | int conf_write_defconfig(const char *name); | ||||||
| int conf_write(const char *name); | int conf_write(const char *name); | ||||||
| int conf_write_autoconf(void); | int conf_write_autoconf(int overwrite); | ||||||
| bool conf_get_changed(void); | bool conf_get_changed(void); | ||||||
| void conf_set_changed_callback(void (*fn)(void)); | void conf_set_changed_callback(void (*fn)(void)); | ||||||
| void conf_set_message_callback(void (*fn)(const char *fmt, va_list ap)); | void conf_set_message_callback(void (*fn)(const char *s)); | ||||||
|  |  | ||||||
| /* menu.c */ | /* menu.c */ | ||||||
| extern struct menu rootmenu; | extern struct menu rootmenu; | ||||||
| @@ -31,7 +32,6 @@ extern struct symbol * symbol_hash[SYMBOL_HASHSIZE]; | |||||||
|  |  | ||||||
| struct symbol * sym_lookup(const char *name, int flags); | struct symbol * sym_lookup(const char *name, int flags); | ||||||
| struct symbol * sym_find(const char *name); | struct symbol * sym_find(const char *name); | ||||||
| const char * sym_expand_string_value(const char *in); |  | ||||||
| const char * sym_escape_string_value(const char *in); | const char * sym_escape_string_value(const char *in); | ||||||
| struct symbol ** sym_re_search(const char *pattern); | struct symbol ** sym_re_search(const char *pattern); | ||||||
| const char * sym_type_name(enum symbol_type type); | const char * sym_type_name(enum symbol_type type); | ||||||
| @@ -43,11 +43,24 @@ tristate sym_toggle_tristate_value(struct symbol *sym); | |||||||
| bool sym_string_valid(struct symbol *sym, const char *newval); | bool sym_string_valid(struct symbol *sym, const char *newval); | ||||||
| bool sym_string_within_range(struct symbol *sym, const char *str); | bool sym_string_within_range(struct symbol *sym, const char *str); | ||||||
| bool sym_set_string_value(struct symbol *sym, const char *newval); | bool sym_set_string_value(struct symbol *sym, const char *newval); | ||||||
| bool sym_is_changable(struct symbol *sym); | bool sym_is_changeable(struct symbol *sym); | ||||||
| struct property * sym_get_choice_prop(struct symbol *sym); | struct property * sym_get_choice_prop(struct symbol *sym); | ||||||
| const char * sym_get_string_value(struct symbol *sym); | const char * sym_get_string_value(struct symbol *sym); | ||||||
|  |  | ||||||
| const char * prop_get_type_name(enum prop_type type); | const char * prop_get_type_name(enum prop_type type); | ||||||
|  |  | ||||||
|  | /* preprocess.c */ | ||||||
|  | enum variable_flavor { | ||||||
|  | 	VAR_SIMPLE, | ||||||
|  | 	VAR_RECURSIVE, | ||||||
|  | 	VAR_APPEND, | ||||||
|  | }; | ||||||
|  | void env_write_dep(FILE *f, const char *auto_conf_name); | ||||||
|  | void variable_add(const char *name, const char *value, | ||||||
|  | 		  enum variable_flavor flavor); | ||||||
|  | void variable_all_del(void); | ||||||
|  | char *expand_dollar(const char **str); | ||||||
|  | char *expand_one_token(const char **str); | ||||||
|  |  | ||||||
| /* expr.c */ | /* expr.c */ | ||||||
| void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken); | void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken); | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								scripts/config/lxdialog/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								scripts/config/lxdialog/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,2 +0,0 @@ | |||||||
| lxdialog |  | ||||||
| *.o |  | ||||||
| @@ -1,91 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
| # Check ncurses compatibility |  | ||||||
|  |  | ||||||
| # What library to link |  | ||||||
| ldflags() |  | ||||||
| { |  | ||||||
| 	pkg-config --libs ncursesw 2>/dev/null && exit |  | ||||||
| 	pkg-config --libs ncurses 2>/dev/null && exit |  | ||||||
| 	for ext in so a dll.a dylib ; do |  | ||||||
| 		for lib in ncursesw ncurses curses ; do |  | ||||||
| 			$cc -print-file-name=lib${lib}.${ext} | grep -q / |  | ||||||
| 			if [ $? -eq 0 ]; then |  | ||||||
| 				echo "-l${lib}" |  | ||||||
| 				exit |  | ||||||
| 			fi |  | ||||||
| 		done |  | ||||||
| 	done |  | ||||||
| 	exit 1 |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # Where is ncurses.h? |  | ||||||
| ccflags() |  | ||||||
| { |  | ||||||
| 	if pkg-config --cflags ncursesw 2>/dev/null; then |  | ||||||
| 		echo '-DCURSES_LOC="<ncurses.h>" -DNCURSES_WIDECHAR=1' |  | ||||||
| 	elif pkg-config --cflags ncurses 2>/dev/null; then |  | ||||||
| 		echo '-DCURSES_LOC="<ncurses.h>"' |  | ||||||
| 	elif [ -f /usr/include/ncursesw/curses.h ]; then |  | ||||||
| 		echo '-I/usr/include/ncursesw -DCURSES_LOC="<curses.h>"' |  | ||||||
| 		echo ' -DNCURSES_WIDECHAR=1' |  | ||||||
| 	elif [ -f /usr/include/ncurses/ncurses.h ]; then |  | ||||||
| 		echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"' |  | ||||||
| 	elif [ -f /usr/include/ncurses/curses.h ]; then |  | ||||||
| 		echo '-I/usr/include/ncurses -DCURSES_LOC="<curses.h>"' |  | ||||||
| 	elif [ -f /usr/include/ncurses.h ]; then |  | ||||||
| 		echo '-DCURSES_LOC="<ncurses.h>"' |  | ||||||
| 	else |  | ||||||
| 		echo '-DCURSES_LOC="<curses.h>"' |  | ||||||
| 	fi |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # Temp file, try to clean up after us |  | ||||||
| tmp=.lxdialog.tmp |  | ||||||
| trap "rm -f $tmp" 0 1 2 3 15 |  | ||||||
|  |  | ||||||
| # Check if we can link to ncurses |  | ||||||
| check() { |  | ||||||
|         $cc -x c - -o $tmp 2>/dev/null <<'EOF' |  | ||||||
| #include CURSES_LOC |  | ||||||
| main() {} |  | ||||||
| EOF |  | ||||||
| 	if [ $? != 0 ]; then |  | ||||||
| 	    echo " *** Unable to find the ncurses libraries or the"       1>&2 |  | ||||||
| 	    echo " *** required header files."                            1>&2 |  | ||||||
| 	    echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2 |  | ||||||
| 	    echo " *** "                                                  1>&2 |  | ||||||
| 	    echo " *** Install ncurses (ncurses-devel) and try again."    1>&2 |  | ||||||
| 	    echo " *** "                                                  1>&2 |  | ||||||
| 	    exit 1 |  | ||||||
| 	fi |  | ||||||
| } |  | ||||||
|  |  | ||||||
| usage() { |  | ||||||
| 	printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| if [ $# -eq 0 ]; then |  | ||||||
| 	usage |  | ||||||
| 	exit 1 |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| cc="" |  | ||||||
| case "$1" in |  | ||||||
| 	"-check") |  | ||||||
| 		shift |  | ||||||
| 		cc="$@" |  | ||||||
| 		check |  | ||||||
| 		;; |  | ||||||
| 	"-ccflags") |  | ||||||
| 		ccflags |  | ||||||
| 		;; |  | ||||||
| 	"-ldflags") |  | ||||||
| 		shift |  | ||||||
| 		cc="$@" |  | ||||||
| 		ldflags |  | ||||||
| 		;; |  | ||||||
| 	"*") |  | ||||||
| 		usage |  | ||||||
| 		exit 1 |  | ||||||
| 		;; |  | ||||||
| esac |  | ||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0+ | ||||||
| /* | /* | ||||||
|  *  checklist.c -- implements the checklist box |  *  checklist.c -- implements the checklist box | ||||||
|  * |  * | ||||||
| @@ -5,20 +6,6 @@ | |||||||
|  *     Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension |  *     Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension | ||||||
|  *     Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two |  *     Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two | ||||||
|  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) |  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | ||||||
|  * |  | ||||||
|  *  This program is free software; you can redistribute it and/or |  | ||||||
|  *  modify it under the terms of the GNU General Public License |  | ||||||
|  *  as published by the Free Software Foundation; either version 2 |  | ||||||
|  *  of the License, or (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  *  This program is distributed in the hope that it will be useful, |  | ||||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  *  GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  *  You should have received a copy of the GNU General Public License |  | ||||||
|  *  along with this program; if not, write to the Free Software |  | ||||||
|  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "dialog.h" | #include "dialog.h" | ||||||
| @@ -103,8 +90,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) | |||||||
| 	int x = width / 2 - 11; | 	int x = width / 2 - 11; | ||||||
| 	int y = height - 2; | 	int y = height - 2; | ||||||
|  |  | ||||||
| 	print_button(dialog, gettext("Select"), y, x, selected == 0); | 	print_button(dialog, "Select", y, x, selected == 0); | ||||||
| 	print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); | 	print_button(dialog, " Help ", y, x + 14, selected == 1); | ||||||
|  |  | ||||||
| 	wmove(dialog, y, x + 1 + 14 * selected); | 	wmove(dialog, y, x + 1 + 14 * selected); | ||||||
| 	wrefresh(dialog); | 	wrefresh(dialog); | ||||||
|   | |||||||
| @@ -1,21 +1,8 @@ | |||||||
|  | /* SPDX-License-Identifier: GPL-2.0+ */ | ||||||
| /* | /* | ||||||
|  *  dialog.h -- common declarations for all dialog modules |  *  dialog.h -- common declarations for all dialog modules | ||||||
|  * |  * | ||||||
|  *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |  *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | ||||||
|  * |  | ||||||
|  *  This program is free software; you can redistribute it and/or |  | ||||||
|  *  modify it under the terms of the GNU General Public License |  | ||||||
|  *  as published by the Free Software Foundation; either version 2 |  | ||||||
|  *  of the License, or (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  *  This program is distributed in the hope that it will be useful, |  | ||||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  *  GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  *  You should have received a copy of the GNU General Public License |  | ||||||
|  *  along with this program; if not, write to the Free Software |  | ||||||
|  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| @@ -26,16 +13,10 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
|  |  | ||||||
| #ifndef KBUILD_NO_NLS |  | ||||||
| # include <libintl.h> |  | ||||||
| #else |  | ||||||
| # define gettext(Msgid) ((const char *) (Msgid)) |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef __sun__ | #ifdef __sun__ | ||||||
| #define CURS_MACROS | #define CURS_MACROS | ||||||
| #endif | #endif | ||||||
| #include CURSES_LOC | #include <ncurses.h> | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Colors in ncurses 1.9.9e do not work properly since foreground and |  * Colors in ncurses 1.9.9e do not work properly since foreground and | ||||||
|   | |||||||
| @@ -1,22 +1,9 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0+ | ||||||
| /* | /* | ||||||
|  *  inputbox.c -- implements the input box |  *  inputbox.c -- implements the input box | ||||||
|  * |  * | ||||||
|  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | ||||||
|  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) |  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | ||||||
|  * |  | ||||||
|  *  This program is free software; you can redistribute it and/or |  | ||||||
|  *  modify it under the terms of the GNU General Public License |  | ||||||
|  *  as published by the Free Software Foundation; either version 2 |  | ||||||
|  *  of the License, or (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  *  This program is distributed in the hope that it will be useful, |  | ||||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  *  GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  *  You should have received a copy of the GNU General Public License |  | ||||||
|  *  along with this program; if not, write to the Free Software |  | ||||||
|  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "dialog.h" | #include "dialog.h" | ||||||
| @@ -31,8 +18,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) | |||||||
| 	int x = width / 2 - 11; | 	int x = width / 2 - 11; | ||||||
| 	int y = height - 2; | 	int y = height - 2; | ||||||
|  |  | ||||||
| 	print_button(dialog, gettext("  Ok  "), y, x, selected == 0); | 	print_button(dialog, "  Ok  ", y, x, selected == 0); | ||||||
| 	print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); | 	print_button(dialog, " Help ", y, x + 14, selected == 1); | ||||||
|  |  | ||||||
| 	wmove(dialog, y, x + 1 + 14 * selected); | 	wmove(dialog, y, x + 1 + 14 * selected); | ||||||
| 	wrefresh(dialog); | 	wrefresh(dialog); | ||||||
| @@ -126,7 +113,8 @@ do_resize: | |||||||
| 			case KEY_DOWN: | 			case KEY_DOWN: | ||||||
| 				break; | 				break; | ||||||
| 			case KEY_BACKSPACE: | 			case KEY_BACKSPACE: | ||||||
| 			case 127: | 			case 8:   /* ^H */ | ||||||
|  | 			case 127: /* ^? */ | ||||||
| 				if (pos) { | 				if (pos) { | ||||||
| 					wattrset(dialog, dlg.inputbox.atr); | 					wattrset(dialog, dlg.inputbox.atr); | ||||||
| 					if (input_x == 0) { | 					if (input_x == 0) { | ||||||
|   | |||||||
| @@ -1,22 +1,9 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0+ | ||||||
| /* | /* | ||||||
|  *  menubox.c -- implements the menu box |  *  menubox.c -- implements the menu box | ||||||
|  * |  * | ||||||
|  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | ||||||
|  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) |  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) | ||||||
|  * |  | ||||||
|  *  This program is free software; you can redistribute it and/or |  | ||||||
|  *  modify it under the terms of the GNU General Public License |  | ||||||
|  *  as published by the Free Software Foundation; either version 2 |  | ||||||
|  *  of the License, or (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  *  This program is distributed in the hope that it will be useful, |  | ||||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  *  GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  *  You should have received a copy of the GNU General Public License |  | ||||||
|  *  along with this program; if not, write to the Free Software |  | ||||||
|  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -157,11 +144,11 @@ static void print_buttons(WINDOW * win, int height, int width, int selected) | |||||||
| 	int x = width / 2 - 28; | 	int x = width / 2 - 28; | ||||||
| 	int y = height - 2; | 	int y = height - 2; | ||||||
|  |  | ||||||
| 	print_button(win, gettext("Select"), y, x, selected == 0); | 	print_button(win, "Select", y, x, selected == 0); | ||||||
| 	print_button(win, gettext(" Exit "), y, x + 12, selected == 1); | 	print_button(win, " Exit ", y, x + 12, selected == 1); | ||||||
| 	print_button(win, gettext(" Help "), y, x + 24, selected == 2); | 	print_button(win, " Help ", y, x + 24, selected == 2); | ||||||
| 	print_button(win, gettext(" Save "), y, x + 36, selected == 3); | 	print_button(win, " Save ", y, x + 36, selected == 3); | ||||||
| 	print_button(win, gettext(" Load "), y, x + 48, selected == 4); | 	print_button(win, " Load ", y, x + 48, selected == 4); | ||||||
|  |  | ||||||
| 	wmove(win, y, x + 1 + 12 * selected); | 	wmove(win, y, x + 1 + 12 * selected); | ||||||
| 	wrefresh(win); | 	wrefresh(win); | ||||||
|   | |||||||
| @@ -1,22 +1,9 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0+ | ||||||
| /* | /* | ||||||
|  *  textbox.c -- implements the text box |  *  textbox.c -- implements the text box | ||||||
|  * |  * | ||||||
|  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | ||||||
|  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) |  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | ||||||
|  * |  | ||||||
|  *  This program is free software; you can redistribute it and/or |  | ||||||
|  *  modify it under the terms of the GNU General Public License |  | ||||||
|  *  as published by the Free Software Foundation; either version 2 |  | ||||||
|  *  of the License, or (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  *  This program is distributed in the hope that it will be useful, |  | ||||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  *  GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  *  You should have received a copy of the GNU General Public License |  | ||||||
|  *  along with this program; if not, write to the Free Software |  | ||||||
|  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "dialog.h" | #include "dialog.h" | ||||||
| @@ -129,7 +116,7 @@ do_resize: | |||||||
|  |  | ||||||
| 	print_title(dialog, title, width); | 	print_title(dialog, title, width); | ||||||
|  |  | ||||||
| 	print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE); | 	print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE); | ||||||
| 	wnoutrefresh(dialog); | 	wnoutrefresh(dialog); | ||||||
| 	getyx(dialog, cur_y, cur_x);	/* Save cursor position */ | 	getyx(dialog, cur_y, cur_x);	/* Save cursor position */ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,22 +1,9 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0+ | ||||||
| /* | /* | ||||||
|  *  util.c |  *  util.c | ||||||
|  * |  * | ||||||
|  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | ||||||
|  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) |  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | ||||||
|  * |  | ||||||
|  *  This program is free software; you can redistribute it and/or |  | ||||||
|  *  modify it under the terms of the GNU General Public License |  | ||||||
|  *  as published by the Free Software Foundation; either version 2 |  | ||||||
|  *  of the License, or (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  *  This program is distributed in the hope that it will be useful, |  | ||||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  *  GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  *  You should have received a copy of the GNU General Public License |  | ||||||
|  *  along with this program; if not, write to the Free Software |  | ||||||
|  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
|   | |||||||
| @@ -1,22 +1,9 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0+ | ||||||
| /* | /* | ||||||
|  *  yesno.c -- implements the yes/no box |  *  yesno.c -- implements the yes/no box | ||||||
|  * |  * | ||||||
|  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) |  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | ||||||
|  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) |  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | ||||||
|  * |  | ||||||
|  *  This program is free software; you can redistribute it and/or |  | ||||||
|  *  modify it under the terms of the GNU General Public License |  | ||||||
|  *  as published by the Free Software Foundation; either version 2 |  | ||||||
|  *  of the License, or (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  *  This program is distributed in the hope that it will be useful, |  | ||||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  *  GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  *  You should have received a copy of the GNU General Public License |  | ||||||
|  *  along with this program; if not, write to the Free Software |  | ||||||
|  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "dialog.h" | #include "dialog.h" | ||||||
| @@ -29,8 +16,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) | |||||||
| 	int x = width / 2 - 10; | 	int x = width / 2 - 10; | ||||||
| 	int y = height - 2; | 	int y = height - 2; | ||||||
|  |  | ||||||
| 	print_button(dialog, gettext(" Yes "), y, x, selected == 0); | 	print_button(dialog, " Yes ", y, x, selected == 0); | ||||||
| 	print_button(dialog, gettext("  No  "), y, x + 13, selected == 1); | 	print_button(dialog, "  No  ", y, x + 13, selected == 1); | ||||||
|  |  | ||||||
| 	wmove(dialog, y, x + 1 + 13 * selected); | 	wmove(dialog, y, x + 1 + 13 * selected); | ||||||
| 	wrefresh(dialog); | 	wrefresh(dialog); | ||||||
|   | |||||||
							
								
								
									
										50
									
								
								scripts/config/mconf-cfg.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										50
									
								
								scripts/config/mconf-cfg.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,50 @@ | |||||||
|  | #!/bin/sh | ||||||
|  | # SPDX-License-Identifier: GPL-2.0 | ||||||
|  |  | ||||||
|  | PKG="ncursesw" | ||||||
|  | PKG2="ncurses" | ||||||
|  |  | ||||||
|  | if [ -n "$(command -v pkg-config)" ]; then | ||||||
|  | 	if pkg-config --exists $PKG; then | ||||||
|  | 		echo cflags=\"$(pkg-config --cflags $PKG)\" | ||||||
|  | 		echo libs=\"$(pkg-config --libs $PKG)\" | ||||||
|  | 		exit 0 | ||||||
|  | 	fi | ||||||
|  |  | ||||||
|  | 	if pkg-config --exists $PKG2; then | ||||||
|  | 		echo cflags=\"$(pkg-config --cflags $PKG2)\" | ||||||
|  | 		echo libs=\"$(pkg-config --libs $PKG2)\" | ||||||
|  | 		exit 0 | ||||||
|  | 	fi | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Check the default paths in case pkg-config is not installed. | ||||||
|  | # (Even if it is installed, some distributions such as openSUSE cannot | ||||||
|  | # find ncurses by pkg-config.) | ||||||
|  | if [ -f /usr/include/ncursesw/ncurses.h ]; then | ||||||
|  | 	echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\" | ||||||
|  | 	echo libs=\"-lncursesw\" | ||||||
|  | 	exit 0 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | if [ -f /usr/include/ncurses/ncurses.h ]; then | ||||||
|  | 	echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\" | ||||||
|  | 	echo libs=\"-lncurses\" | ||||||
|  | 	exit 0 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | if [ -f /usr/include/ncurses.h ]; then | ||||||
|  | 	echo cflags=\"-D_GNU_SOURCE\" | ||||||
|  | 	echo libs=\"-lncurses\" | ||||||
|  | 	exit 0 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | echo >&2 "*" | ||||||
|  | echo >&2 "* Unable to find the ncurses package." | ||||||
|  | echo >&2 "* Install ncurses (ncurses-devel or libncurses-dev" | ||||||
|  | echo >&2 "* depending on your distribution)." | ||||||
|  | echo >&2 "*" | ||||||
|  | echo >&2 "* You may also need to install pkg-config to find the" | ||||||
|  | echo >&2 "* ncurses installed in a non-default location." | ||||||
|  | echo >&2 "*" | ||||||
|  | exit 1 | ||||||
| @@ -1,6 +1,6 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0 | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  * Released under the terms of the GNU GPL v2.0. |  | ||||||
|  * |  * | ||||||
|  * Introduced single menu mode (show all sub-menus in one large tree). |  * Introduced single menu mode (show all sub-menus in one large tree). | ||||||
|  * 2002-11-06 Petr Baudis <pasky@ucw.cz> |  * 2002-11-06 Petr Baudis <pasky@ucw.cz> | ||||||
| @@ -15,23 +15,27 @@ | |||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  | #include <strings.h> | ||||||
| #include <signal.h> | #include <signal.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| #include <locale.h> |  | ||||||
|  |  | ||||||
| #include "lkc.h" | #include "lkc.h" | ||||||
| #include "lxdialog/dialog.h" | #include "lxdialog/dialog.h" | ||||||
|  |  | ||||||
| static const char mconf_readme[] = N_( | static const char mconf_readme[] = | ||||||
| "Overview\n" | "Overview\n" | ||||||
| "--------\n" | "--------\n" | ||||||
| "Some OpenWrt features may be built directly into the image.\n" | "Some OpenWrt features may be built directly into the image.\n" | ||||||
| "Some may be made into installable ipkg packages. Some features\n" | "Some may be made into installable ipkg packages (referred here as\n" | ||||||
| "may be completely removed altogether.\n" | "modules). Some features may be completely removed altogether.\n" | ||||||
| "\n" | "\n" | ||||||
| "Menu items beginning with [*], <M> or [ ] represent features\n" | "Menu items beginning with following braces represent features that\n" | ||||||
| "configured to be included, built as package or removed respectively.\n" | "  [ ] can be built in or removed\n" | ||||||
| "Pointed brackets <> represent packaging capable features.\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" | ||||||
|  | "while *, M or whitespace inside braces means to build in, build as\n" | ||||||
|  | "a module or to exclude the feature respectively.\n" | ||||||
| "\n" | "\n" | ||||||
| "To change any of these features, highlight it with the cursor\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" | "keys and press <Y> to build it in, <M> to make it a module or\n" | ||||||
| @@ -167,37 +171,37 @@ static const char mconf_readme[] = N_( | |||||||
| " blackbg    => selects a color scheme with black background\n" | " blackbg    => selects a color scheme with black background\n" | ||||||
| " classic    => theme with blue background. The classic look\n" | " classic    => theme with blue background. The classic look\n" | ||||||
| " bluetitle  => an LCD friendly version of classic. (default)\n" | " bluetitle  => an LCD friendly version of classic. (default)\n" | ||||||
| "\n"), | "\n", | ||||||
| menu_instructions[] = N_( | menu_instructions[] = | ||||||
| 	"Arrow keys navigate the menu.  " | 	"Arrow keys navigate the menu.  " | ||||||
| 	"<Enter> selects submenus ---> (or empty submenus ----).  " | 	"<Enter> selects submenus ---> (or empty submenus ----).  " | ||||||
| 	"Highlighted letters are hotkeys.  " | 	"Highlighted letters are hotkeys.  " | ||||||
| 	"Pressing <Y> includes, <N> excludes, <M> modularizes features.  " | 	"Pressing <Y> includes, <N> excludes, <M> modularizes features.  " | ||||||
| 	"Press <Esc><Esc> to exit, <?> for Help, </> for Search.  " | 	"Press <Esc><Esc> to exit, <?> for Help, </> for Search.  " | ||||||
| 	"Legend: [*] built-in  [ ] excluded  <M> module  < > module capable"), | 	"Legend: [*] built-in  [ ] excluded  <M> module  < > module capable", | ||||||
| radiolist_instructions[] = N_( | radiolist_instructions[] = | ||||||
| 	"Use the arrow keys to navigate this window or " | 	"Use the arrow keys to navigate this window or " | ||||||
| 	"press the hotkey of the item you wish to select " | 	"press the hotkey of the item you wish to select " | ||||||
| 	"followed by the <SPACE BAR>. " | 	"followed by the <SPACE BAR>. " | ||||||
| 	"Press <?> for additional information about this option."), | 	"Press <?> for additional information about this option.", | ||||||
| inputbox_instructions_int[] = N_( | inputbox_instructions_int[] = | ||||||
| 	"Please enter a decimal value. " | 	"Please enter a decimal value. " | ||||||
| 	"Fractions will not be accepted.  " | 	"Fractions will not be accepted.  " | ||||||
| 	"Use the <TAB> key to move from the input field to the buttons below it."), | 	"Use the <TAB> key to move from the input field to the buttons below it.", | ||||||
| inputbox_instructions_hex[] = N_( | inputbox_instructions_hex[] = | ||||||
| 	"Please enter a hexadecimal value. " | 	"Please enter a hexadecimal value. " | ||||||
| 	"Use the <TAB> key to move from the input field to the buttons below it."), | 	"Use the <TAB> key to move from the input field to the buttons below it.", | ||||||
| inputbox_instructions_string[] = N_( | inputbox_instructions_string[] = | ||||||
| 	"Please enter a string value. " | 	"Please enter a string value. " | ||||||
| 	"Use the <TAB> key to move from the input field to the buttons below it."), | 	"Use the <TAB> key to move from the input field to the buttons below it.", | ||||||
| setmod_text[] = N_( | setmod_text[] = | ||||||
| 	"This feature depends on another which has been configured as a module.\n" | 	"This feature depends on another which has been configured as a module.\n" | ||||||
| 	"As a result, this feature will be built as a module."), | 	"As a result, this feature will be built as a module.", | ||||||
| load_config_text[] = N_( | load_config_text[] = | ||||||
| 	"Enter the name of the configuration file you wish to load.  " | 	"Enter the name of the configuration file you wish to load.  " | ||||||
| 	"Accept the name shown to restore the configuration you " | 	"Accept the name shown to restore the configuration you " | ||||||
| 	"last retrieved.  Leave blank to abort."), | 	"last retrieved.  Leave blank to abort.", | ||||||
| load_config_help[] = N_( | load_config_help[] = | ||||||
| 	"\n" | 	"\n" | ||||||
| 	"For various reasons, one may wish to keep several different\n" | 	"For various reasons, one may wish to keep several different\n" | ||||||
| 	"configurations available on a single machine.\n" | 	"configurations available on a single machine.\n" | ||||||
| @@ -207,11 +211,11 @@ load_config_help[] = N_( | |||||||
| 	"configuration.\n" | 	"configuration.\n" | ||||||
| 	"\n" | 	"\n" | ||||||
| 	"If you are uncertain, then you have probably never used alternate\n" | 	"If you are uncertain, then you have probably never used alternate\n" | ||||||
| 	"configuration files. You should therefore leave this blank to abort.\n"), | 	"configuration files. You should therefore leave this blank to abort.\n", | ||||||
| save_config_text[] = N_( | save_config_text[] = | ||||||
| 	"Enter a filename to which this configuration should be saved " | 	"Enter a filename to which this configuration should be saved " | ||||||
| 	"as an alternate.  Leave blank to abort."), | 	"as an alternate.  Leave blank to abort.", | ||||||
| save_config_help[] = N_( | save_config_help[] = | ||||||
| 	"\n" | 	"\n" | ||||||
| 	"For various reasons, one may wish to keep different configurations\n" | 	"For various reasons, one may wish to keep different configurations\n" | ||||||
| 	"available on a single machine.\n" | 	"available on a single machine.\n" | ||||||
| @@ -221,8 +225,8 @@ save_config_help[] = N_( | |||||||
| 	"configuration options you have selected at that time.\n" | 	"configuration options you have selected at that time.\n" | ||||||
| 	"\n" | 	"\n" | ||||||
| 	"If you are uncertain what all this means then you should probably\n" | 	"If you are uncertain what all this means then you should probably\n" | ||||||
| 	"leave this blank.\n"), | 	"leave this blank.\n", | ||||||
| search_help[] = N_( | search_help[] = | ||||||
| 	"\n" | 	"\n" | ||||||
| 	"Search for symbols and display their relations.\n" | 	"Search for symbols and display their relations.\n" | ||||||
| 	"Regular expressions are allowed.\n" | 	"Regular expressions are allowed.\n" | ||||||
| @@ -242,7 +246,7 @@ search_help[] = N_( | |||||||
| 	"  Selected by: BAR [=n]\n" | 	"  Selected by: BAR [=n]\n" | ||||||
| 	"-----------------------------------------------------------------\n" | 	"-----------------------------------------------------------------\n" | ||||||
| 	"o The line 'Type:' shows the type of the configuration option for\n" | 	"o The line 'Type:' shows the type of the configuration option for\n" | ||||||
| 	"  this symbol (boolean, tristate, string, ...)\n" | 	"  this symbol (bool, tristate, string, ...)\n" | ||||||
| 	"o The line 'Prompt:' shows the text used in the menu structure for\n" | 	"o The line 'Prompt:' shows the text used in the menu structure for\n" | ||||||
| 	"  this symbol\n" | 	"  this symbol\n" | ||||||
| 	"o The 'Defined at' line tells at what file / line number the symbol\n" | 	"o The 'Defined at' line tells at what file / line number the symbol\n" | ||||||
| @@ -267,7 +271,7 @@ search_help[] = N_( | |||||||
| 	"Examples: USB	=> find all symbols containing USB\n" | 	"Examples: USB	=> find all symbols containing USB\n" | ||||||
| 	"          ^USB => find all symbols starting with USB\n" | 	"          ^USB => find all symbols starting with USB\n" | ||||||
| 	"          USB$ => find all symbols ending with USB\n" | 	"          USB$ => find all symbols ending with USB\n" | ||||||
| 	"\n"); | 	"\n"; | ||||||
|  |  | ||||||
| static int indent; | static int indent; | ||||||
| static struct menu *current_menu; | static struct menu *current_menu; | ||||||
| @@ -396,19 +400,19 @@ static void search_conf(void) | |||||||
| 	struct subtitle_part stpart; | 	struct subtitle_part stpart; | ||||||
|  |  | ||||||
| 	title = str_new(); | 	title = str_new(); | ||||||
| 	str_printf( &title, _("Enter (sub)string or regexp to search for " | 	str_printf( &title, "Enter (sub)string or regexp to search for " | ||||||
| 			      "(with or without \"%s\")"), CONFIG_); | 			      "(with or without \"%s\")", CONFIG_); | ||||||
|  |  | ||||||
| again: | again: | ||||||
| 	dialog_clear(); | 	dialog_clear(); | ||||||
| 	dres = dialog_inputbox(_("Search Configuration Parameter"), | 	dres = dialog_inputbox("Search Configuration Parameter", | ||||||
| 			      str_get(&title), | 			      str_get(&title), | ||||||
| 			      10, 75, ""); | 			      10, 75, ""); | ||||||
| 	switch (dres) { | 	switch (dres) { | ||||||
| 	case 0: | 	case 0: | ||||||
| 		break; | 		break; | ||||||
| 	case 1: | 	case 1: | ||||||
| 		show_helptext(_("Search Configuration"), search_help); | 		show_helptext("Search Configuration", search_help); | ||||||
| 		goto again; | 		goto again; | ||||||
| 	default: | 	default: | ||||||
| 		str_free(&title); | 		str_free(&title); | ||||||
| @@ -439,7 +443,7 @@ again: | |||||||
|  |  | ||||||
| 		res = get_relations_str(sym_arr, &head); | 		res = get_relations_str(sym_arr, &head); | ||||||
| 		set_subtitle(); | 		set_subtitle(); | ||||||
| 		dres = show_textbox_ext(_("Search Results"), (char *) | 		dres = show_textbox_ext("Search Results", (char *) | ||||||
| 					str_get(&res), 0, 0, keys, &vscroll, | 					str_get(&res), 0, 0, keys, &vscroll, | ||||||
| 					&hscroll, &update_text, (void *) | 					&hscroll, &update_text, (void *) | ||||||
| 					&data); | 					&data); | ||||||
| @@ -487,7 +491,6 @@ static void build_conf(struct menu *menu) | |||||||
| 			switch (prop->type) { | 			switch (prop->type) { | ||||||
| 			case P_MENU: | 			case P_MENU: | ||||||
| 				child_count++; | 				child_count++; | ||||||
| 				prompt = _(prompt); |  | ||||||
| 				if (single_menu_mode) { | 				if (single_menu_mode) { | ||||||
| 					item_make("%s%*c%s", | 					item_make("%s%*c%s", | ||||||
| 						  menu->data ? "-->" : "++>", | 						  menu->data ? "-->" : "++>", | ||||||
| @@ -504,7 +507,7 @@ static void build_conf(struct menu *menu) | |||||||
| 			case P_COMMENT: | 			case P_COMMENT: | ||||||
| 				if (prompt) { | 				if (prompt) { | ||||||
| 					child_count++; | 					child_count++; | ||||||
| 					item_make("   %*c*** %s ***", indent + 1, ' ', _(prompt)); | 					item_make("   %*c*** %s ***", indent + 1, ' ', prompt); | ||||||
| 					item_set_tag(':'); | 					item_set_tag(':'); | ||||||
| 					item_set_data(menu); | 					item_set_data(menu); | ||||||
| 				} | 				} | ||||||
| @@ -512,7 +515,7 @@ static void build_conf(struct menu *menu) | |||||||
| 			default: | 			default: | ||||||
| 				if (prompt) { | 				if (prompt) { | ||||||
| 					child_count++; | 					child_count++; | ||||||
| 					item_make("---%*c%s", indent + 1, ' ', _(prompt)); | 					item_make("---%*c%s", indent + 1, ' ', prompt); | ||||||
| 					item_set_tag(':'); | 					item_set_tag(':'); | ||||||
| 					item_set_data(menu); | 					item_set_data(menu); | ||||||
| 				} | 				} | ||||||
| @@ -534,7 +537,7 @@ static void build_conf(struct menu *menu) | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		val = sym_get_tristate_value(sym); | 		val = sym_get_tristate_value(sym); | ||||||
| 		if (sym_is_changable(sym)) { | 		if (sym_is_changeable(sym)) { | ||||||
| 			switch (type) { | 			switch (type) { | ||||||
| 			case S_BOOLEAN: | 			case S_BOOLEAN: | ||||||
| 				item_make("[%c]", val == no ? ' ' : '*'); | 				item_make("[%c]", val == no ? ' ' : '*'); | ||||||
| @@ -556,10 +559,10 @@ static void build_conf(struct menu *menu) | |||||||
| 			item_set_data(menu); | 			item_set_data(menu); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); | 		item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu)); | ||||||
| 		if (val == yes) { | 		if (val == yes) { | ||||||
| 			if (def_menu) { | 			if (def_menu) { | ||||||
| 				item_add_str(" (%s)", _(menu_get_prompt(def_menu))); | 				item_add_str(" (%s)", menu_get_prompt(def_menu)); | ||||||
| 				item_add_str("  --->"); | 				item_add_str("  --->"); | ||||||
| 				if (def_menu->list) { | 				if (def_menu->list) { | ||||||
| 					indent += 2; | 					indent += 2; | ||||||
| @@ -571,7 +574,7 @@ static void build_conf(struct menu *menu) | |||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		if (menu == current_menu) { | 		if (menu == current_menu) { | ||||||
| 			item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); | 			item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu)); | ||||||
| 			item_set_tag(':'); | 			item_set_tag(':'); | ||||||
| 			item_set_data(menu); | 			item_set_data(menu); | ||||||
| 			goto conf_childs; | 			goto conf_childs; | ||||||
| @@ -585,7 +588,7 @@ static void build_conf(struct menu *menu) | |||||||
| 		} else { | 		} else { | ||||||
| 			switch (type) { | 			switch (type) { | ||||||
| 			case S_BOOLEAN: | 			case S_BOOLEAN: | ||||||
| 				if (sym_is_changable(sym)) | 				if (sym_is_changeable(sym)) | ||||||
| 					item_make("[%c]", val == no ? ' ' : '*'); | 					item_make("[%c]", val == no ? ' ' : '*'); | ||||||
| 				else | 				else | ||||||
| 					item_make("-%c-", val == no ? ' ' : '*'); | 					item_make("-%c-", val == no ? ' ' : '*'); | ||||||
| @@ -598,7 +601,7 @@ static void build_conf(struct menu *menu) | |||||||
| 				case mod: ch = 'M'; break; | 				case mod: ch = 'M'; break; | ||||||
| 				default:  ch = ' '; break; | 				default:  ch = ' '; break; | ||||||
| 				} | 				} | ||||||
| 				if (sym_is_changable(sym)) { | 				if (sym_is_changeable(sym)) { | ||||||
| 					if (sym->rev_dep.tri == mod) | 					if (sym->rev_dep.tri == mod) | ||||||
| 						item_make("{%c}", ch); | 						item_make("{%c}", ch); | ||||||
| 					else | 					else | ||||||
| @@ -614,17 +617,17 @@ static void build_conf(struct menu *menu) | |||||||
| 				tmp = indent - tmp + 4; | 				tmp = indent - tmp + 4; | ||||||
| 				if (tmp < 0) | 				if (tmp < 0) | ||||||
| 					tmp = 0; | 					tmp = 0; | ||||||
| 				item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)), | 				item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu), | ||||||
| 					     (sym_has_value(sym) || !sym_is_changable(sym)) ? | 					     (sym_has_value(sym) || !sym_is_changeable(sym)) ? | ||||||
| 					     "" : _(" (NEW)")); | 					     "" : " (NEW)"); | ||||||
| 				item_set_tag('s'); | 				item_set_tag('s'); | ||||||
| 				item_set_data(menu); | 				item_set_data(menu); | ||||||
| 				goto conf_childs; | 				goto conf_childs; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)), | 		item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu), | ||||||
| 			  (sym_has_value(sym) || !sym_is_changable(sym)) ? | 			  (sym_has_value(sym) || !sym_is_changeable(sym)) ? | ||||||
| 			  "" : _(" (NEW)")); | 			  "" : " (NEW)"); | ||||||
| 		if (menu->prompt->type == P_MENU) { | 		if (menu->prompt->type == P_MENU) { | ||||||
| 			item_add_str("  %s", menu_is_empty(menu) ? "----" : "--->"); | 			item_add_str("  %s", menu_is_empty(menu) ? "----" : "--->"); | ||||||
| 			return; | 			return; | ||||||
| @@ -661,8 +664,8 @@ static void conf(struct menu *menu, struct menu *active_menu) | |||||||
| 			break; | 			break; | ||||||
| 		set_subtitle(); | 		set_subtitle(); | ||||||
| 		dialog_clear(); | 		dialog_clear(); | ||||||
| 		res = dialog_menu(prompt ? _(prompt) : _("Main Menu"), | 		res = dialog_menu(prompt ? prompt : "Main Menu", | ||||||
| 				  _(menu_instructions), | 				  menu_instructions, | ||||||
| 				  active_menu, &s_scroll); | 				  active_menu, &s_scroll); | ||||||
| 		if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) | 		if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) | ||||||
| 			break; | 			break; | ||||||
| @@ -704,7 +707,7 @@ static void conf(struct menu *menu, struct menu *active_menu) | |||||||
| 				show_help(submenu); | 				show_help(submenu); | ||||||
| 			else { | 			else { | ||||||
| 				reset_subtitle(); | 				reset_subtitle(); | ||||||
| 				show_helptext(_("README"), _(mconf_readme)); | 				show_helptext("README", mconf_readme); | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| 		case 3: | 		case 3: | ||||||
| @@ -769,16 +772,13 @@ static void show_helptext(const char *title, const char *text) | |||||||
| 	show_textbox(title, text, 0, 0); | 	show_textbox(title, text, 0, 0); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void conf_message_callback(const char *fmt, va_list ap) | static void conf_message_callback(const char *s) | ||||||
| { | { | ||||||
| 	char buf[PATH_MAX+1]; |  | ||||||
|  |  | ||||||
| 	vsnprintf(buf, sizeof(buf), fmt, ap); |  | ||||||
| 	if (save_and_exit) { | 	if (save_and_exit) { | ||||||
| 		if (!silent) | 		if (!silent) | ||||||
| 			printf("%s", buf); | 			printf("%s", s); | ||||||
| 	} else { | 	} else { | ||||||
| 		show_textbox(NULL, buf, 6, 60); | 		show_textbox(NULL, s, 6, 60); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -789,13 +789,13 @@ static void show_help(struct menu *menu) | |||||||
| 	help.max_width = getmaxx(stdscr) - 10; | 	help.max_width = getmaxx(stdscr) - 10; | ||||||
| 	menu_get_ext_help(menu, &help); | 	menu_get_ext_help(menu, &help); | ||||||
|  |  | ||||||
| 	show_helptext(_(menu_get_prompt(menu)), str_get(&help)); | 	show_helptext(menu_get_prompt(menu), str_get(&help)); | ||||||
| 	str_free(&help); | 	str_free(&help); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void conf_choice(struct menu *menu) | static void conf_choice(struct menu *menu) | ||||||
| { | { | ||||||
| 	const char *prompt = _(menu_get_prompt(menu)); | 	const char *prompt = menu_get_prompt(menu); | ||||||
| 	struct menu *child; | 	struct menu *child; | ||||||
| 	struct symbol *active; | 	struct symbol *active; | ||||||
| 	struct property *prop; | 	struct property *prop; | ||||||
| @@ -811,9 +811,9 @@ static void conf_choice(struct menu *menu) | |||||||
| 			if (!menu_is_visible(child)) | 			if (!menu_is_visible(child)) | ||||||
| 				continue; | 				continue; | ||||||
| 			if (child->sym) | 			if (child->sym) | ||||||
| 				item_make("%s", _(menu_get_prompt(child))); | 				item_make("%s", menu_get_prompt(child)); | ||||||
| 			else { | 			else { | ||||||
| 				item_make("*** %s ***", _(menu_get_prompt(child))); | 				item_make("*** %s ***", menu_get_prompt(child)); | ||||||
| 				item_set_tag(':'); | 				item_set_tag(':'); | ||||||
| 			} | 			} | ||||||
| 			item_set_data(child); | 			item_set_data(child); | ||||||
| @@ -823,8 +823,8 @@ static void conf_choice(struct menu *menu) | |||||||
| 				item_set_tag('X'); | 				item_set_tag('X'); | ||||||
| 		} | 		} | ||||||
| 		dialog_clear(); | 		dialog_clear(); | ||||||
| 		res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), | 		res = dialog_checklist(prompt ? prompt : "Main Menu", | ||||||
| 					_(radiolist_instructions), | 					radiolist_instructions, | ||||||
| 					MENUBOX_HEIGTH_MIN, | 					MENUBOX_HEIGTH_MIN, | ||||||
| 					MENUBOX_WIDTH_MIN, | 					MENUBOX_WIDTH_MIN, | ||||||
| 					CHECKLIST_HEIGTH_MIN); | 					CHECKLIST_HEIGTH_MIN); | ||||||
| @@ -874,26 +874,26 @@ static void conf_string(struct menu *menu) | |||||||
|  |  | ||||||
| 		switch (sym_get_type(menu->sym)) { | 		switch (sym_get_type(menu->sym)) { | ||||||
| 		case S_INT: | 		case S_INT: | ||||||
| 			heading = _(inputbox_instructions_int); | 			heading = inputbox_instructions_int; | ||||||
| 			break; | 			break; | ||||||
| 		case S_HEX: | 		case S_HEX: | ||||||
| 			heading = _(inputbox_instructions_hex); | 			heading = inputbox_instructions_hex; | ||||||
| 			break; | 			break; | ||||||
| 		case S_STRING: | 		case S_STRING: | ||||||
| 			heading = _(inputbox_instructions_string); | 			heading = inputbox_instructions_string; | ||||||
| 			break; | 			break; | ||||||
| 		default: | 		default: | ||||||
| 			heading = _("Internal mconf error!"); | 			heading = "Internal mconf error!"; | ||||||
| 		} | 		} | ||||||
| 		dialog_clear(); | 		dialog_clear(); | ||||||
| 		res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"), | 		res = dialog_inputbox(prompt ? prompt : "Main Menu", | ||||||
| 				      heading, 10, 75, | 				      heading, 10, 75, | ||||||
| 				      sym_get_string_value(menu->sym)); | 				      sym_get_string_value(menu->sym)); | ||||||
| 		switch (res) { | 		switch (res) { | ||||||
| 		case 0: | 		case 0: | ||||||
| 			if (sym_set_string_value(menu->sym, dialog_input_result)) | 			if (sym_set_string_value(menu->sym, dialog_input_result)) | ||||||
| 				return; | 				return; | ||||||
| 			show_textbox(NULL, _("You have made an invalid entry."), 5, 43); | 			show_textbox(NULL, "You have made an invalid entry.", 5, 43); | ||||||
| 			break; | 			break; | ||||||
| 		case 1: | 		case 1: | ||||||
| 			show_help(menu); | 			show_help(menu); | ||||||
| @@ -921,10 +921,10 @@ static void conf_load(void) | |||||||
| 				sym_set_change_count(1); | 				sym_set_change_count(1); | ||||||
| 				return; | 				return; | ||||||
| 			} | 			} | ||||||
| 			show_textbox(NULL, _("File does not exist!"), 5, 38); | 			show_textbox(NULL, "File does not exist!", 5, 38); | ||||||
| 			break; | 			break; | ||||||
| 		case 1: | 		case 1: | ||||||
| 			show_helptext(_("Load Alternate Configuration"), load_config_help); | 			show_helptext("Load Alternate Configuration", load_config_help); | ||||||
| 			break; | 			break; | ||||||
| 		case KEY_ESC: | 		case KEY_ESC: | ||||||
| 			return; | 			return; | ||||||
| @@ -947,10 +947,10 @@ static void conf_save(void) | |||||||
| 				set_config_filename(dialog_input_result); | 				set_config_filename(dialog_input_result); | ||||||
| 				return; | 				return; | ||||||
| 			} | 			} | ||||||
| 			show_textbox(NULL, _("Can't create file!  Probably a nonexistent directory."), 5, 60); | 			show_textbox(NULL, "Can't create file!", 5, 60); | ||||||
| 			break; | 			break; | ||||||
| 		case 1: | 		case 1: | ||||||
| 			show_helptext(_("Save Alternate Configuration"), save_config_help); | 			show_helptext("Save Alternate Configuration", save_config_help); | ||||||
| 			break; | 			break; | ||||||
| 		case KEY_ESC: | 		case KEY_ESC: | ||||||
| 			return; | 			return; | ||||||
| @@ -967,8 +967,8 @@ static int handle_exit(void) | |||||||
| 	dialog_clear(); | 	dialog_clear(); | ||||||
| 	if (conf_get_changed()) | 	if (conf_get_changed()) | ||||||
| 		res = dialog_yesno(NULL, | 		res = dialog_yesno(NULL, | ||||||
| 				   _("Do you wish to save your new configuration?\n" | 				   "Do you wish to save your new configuration?\n" | ||||||
| 				     "(Press <ESC><ESC> to continue kernel configuration.)"), | 				     "(Press <ESC><ESC> to continue kernel configuration.)", | ||||||
| 				   6, 60); | 				   6, 60); | ||||||
| 	else | 	else | ||||||
| 		res = -1; | 		res = -1; | ||||||
| @@ -978,26 +978,27 @@ static int handle_exit(void) | |||||||
| 	switch (res) { | 	switch (res) { | ||||||
| 	case 0: | 	case 0: | ||||||
| 		if (conf_write(filename)) { | 		if (conf_write(filename)) { | ||||||
| 			fprintf(stderr, _("\n\n" | 			fprintf(stderr, "\n\n" | ||||||
| 					  "Error while writing of the configuration.\n" | 					  "Error while writing of the configuration.\n" | ||||||
| 					  "Your configuration changes were NOT saved." | 					  "Your configuration changes were NOT saved." | ||||||
| 					  "\n\n")); | 					  "\n\n"); | ||||||
| 			return 1; | 			return 1; | ||||||
| 		} | 		} | ||||||
|  | 		conf_write_autoconf(0); | ||||||
| 		/* fall through */ | 		/* fall through */ | ||||||
| 	case -1: | 	case -1: | ||||||
| 		if (!silent) | 		if (!silent) | ||||||
| 			printf(_("\n\n" | 			printf("\n\n" | ||||||
| 				 "*** End of the configuration.\n" | 				 "*** End of the configuration.\n" | ||||||
| 				 "*** Execute 'make' to start the build or try 'make help'." | 				 "*** Execute 'make' to start the build or try 'make help'." | ||||||
| 				 "\n\n")); | 				 "\n\n"); | ||||||
| 		res = 0; | 		res = 0; | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		if (!silent) | 		if (!silent) | ||||||
| 			fprintf(stderr, _("\n\n" | 			fprintf(stderr, "\n\n" | ||||||
| 					  "Your configuration changes were NOT saved." | 					  "Your configuration changes were NOT saved." | ||||||
| 					  "\n\n")); | 					  "\n\n"); | ||||||
| 		if (res != KEY_ESC) | 		if (res != KEY_ESC) | ||||||
| 			res = 0; | 			res = 0; | ||||||
| 	} | 	} | ||||||
| @@ -1015,10 +1016,6 @@ int main(int ac, char **av) | |||||||
| 	char *mode; | 	char *mode; | ||||||
| 	int res; | 	int res; | ||||||
|  |  | ||||||
| 	setlocale(LC_ALL, ""); |  | ||||||
| 	bindtextdomain(PACKAGE, LOCALEDIR); |  | ||||||
| 	textdomain(PACKAGE); |  | ||||||
|  |  | ||||||
| 	signal(SIGINT, sig_handler); | 	signal(SIGINT, sig_handler); | ||||||
|  |  | ||||||
| 	if (ac > 1 && strcmp(av[1], "-s") == 0) { | 	if (ac > 1 && strcmp(av[1], "-s") == 0) { | ||||||
| @@ -1037,8 +1034,8 @@ int main(int ac, char **av) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (init_dialog(NULL)) { | 	if (init_dialog(NULL)) { | ||||||
| 		fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); | 		fprintf(stderr, "Your display is too small to run Menuconfig!\n"); | ||||||
| 		fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); | 		fprintf(stderr, "It must be at least 19 lines by 80 columns.\n"); | ||||||
| 		return 1; | 		return 1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0 | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  * Released under the terms of the GNU GPL v2.0. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
| @@ -62,13 +62,8 @@ void menu_add_entry(struct symbol *sym) | |||||||
| 		menu_add_symbol(P_SYMBOL, sym, NULL); | 		menu_add_symbol(P_SYMBOL, sym, NULL); | ||||||
| } | } | ||||||
|  |  | ||||||
| void menu_end_entry(void) |  | ||||||
| { |  | ||||||
| } |  | ||||||
|  |  | ||||||
| struct menu *menu_add_menu(void) | struct menu *menu_add_menu(void) | ||||||
| { | { | ||||||
| 	menu_end_entry(); |  | ||||||
| 	last_entry_ptr = ¤t_entry->list; | 	last_entry_ptr = ¤t_entry->list; | ||||||
| 	return current_menu = current_entry; | 	return current_menu = current_entry; | ||||||
| } | } | ||||||
| @@ -79,19 +74,23 @@ void menu_end_menu(void) | |||||||
| 	current_menu = current_menu->parent; | 	current_menu = current_menu->parent; | ||||||
| } | } | ||||||
|  |  | ||||||
| static struct expr *menu_check_dep(struct expr *e) | /* | ||||||
|  |  * Rewrites 'm' to 'm' && MODULES, so that it evaluates to 'n' when running | ||||||
|  |  * without modules | ||||||
|  |  */ | ||||||
|  | static struct expr *rewrite_m(struct expr *e) | ||||||
| { | { | ||||||
| 	if (!e) | 	if (!e) | ||||||
| 		return e; | 		return e; | ||||||
|  |  | ||||||
| 	switch (e->type) { | 	switch (e->type) { | ||||||
| 	case E_NOT: | 	case E_NOT: | ||||||
| 		e->left.expr = menu_check_dep(e->left.expr); | 		e->left.expr = rewrite_m(e->left.expr); | ||||||
| 		break; | 		break; | ||||||
| 	case E_OR: | 	case E_OR: | ||||||
| 	case E_AND: | 	case E_AND: | ||||||
| 		e->left.expr = menu_check_dep(e->left.expr); | 		e->left.expr = rewrite_m(e->left.expr); | ||||||
| 		e->right.expr = menu_check_dep(e->right.expr); | 		e->right.expr = rewrite_m(e->right.expr); | ||||||
| 		break; | 		break; | ||||||
| 	case E_SYMBOL: | 	case E_SYMBOL: | ||||||
| 		/* change 'm' into 'm' && MODULES */ | 		/* change 'm' into 'm' && MODULES */ | ||||||
| @@ -106,7 +105,7 @@ static struct expr *menu_check_dep(struct expr *e) | |||||||
|  |  | ||||||
| void menu_add_dep(struct expr *dep) | void menu_add_dep(struct expr *dep) | ||||||
| { | { | ||||||
| 	current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); | 	current_entry->dep = expr_alloc_and(current_entry->dep, dep); | ||||||
| } | } | ||||||
|  |  | ||||||
| void menu_set_type(int type) | void menu_set_type(int type) | ||||||
| @@ -125,25 +124,49 @@ void menu_set_type(int type) | |||||||
| 		sym_type_name(sym->type), sym_type_name(type)); | 		sym_type_name(sym->type), sym_type_name(type)); | ||||||
| } | } | ||||||
|  |  | ||||||
| struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) | struct property *menu_add_prop(enum prop_type type, struct expr *expr, | ||||||
|  | 			       struct expr *dep) | ||||||
| { | { | ||||||
| 	struct property *prop = prop_alloc(type, current_entry->sym); | 	struct property *prop; | ||||||
|  |  | ||||||
|  | 	prop = xmalloc(sizeof(*prop)); | ||||||
|  | 	memset(prop, 0, sizeof(*prop)); | ||||||
|  | 	prop->type = type; | ||||||
|  | 	prop->file = current_file; | ||||||
|  | 	prop->lineno = zconf_lineno(); | ||||||
| 	prop->menu = current_entry; | 	prop->menu = current_entry; | ||||||
| 	prop->expr = expr; | 	prop->expr = expr; | ||||||
| 	prop->visible.expr = menu_check_dep(dep); | 	prop->visible.expr = dep; | ||||||
|  |  | ||||||
|  | 	/* append property to the prop list of symbol */ | ||||||
|  | 	if (current_entry->sym) { | ||||||
|  | 		struct property **propp; | ||||||
|  |  | ||||||
|  | 		for (propp = ¤t_entry->sym->prop; | ||||||
|  | 		     *propp; | ||||||
|  | 		     propp = &(*propp)->next) | ||||||
|  | 			; | ||||||
|  | 		*propp = prop; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return prop; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct property *menu_add_prompt(enum prop_type type, char *prompt, | ||||||
|  | 				 struct expr *dep) | ||||||
|  | { | ||||||
|  | 	struct property *prop = menu_add_prop(type, NULL, dep); | ||||||
|  |  | ||||||
| 	if (prompt) { |  | ||||||
| 	if (isspace(*prompt)) { | 	if (isspace(*prompt)) { | ||||||
| 		prop_warn(prop, "leading whitespace ignored"); | 		prop_warn(prop, "leading whitespace ignored"); | ||||||
| 		while (isspace(*prompt)) | 		while (isspace(*prompt)) | ||||||
| 			prompt++; | 			prompt++; | ||||||
| 	} | 	} | ||||||
| 		if (current_entry->prompt && current_entry != &rootmenu) | 	if (current_entry->prompt) | ||||||
| 		prop_warn(prop, "prompt redefined"); | 		prop_warn(prop, "prompt redefined"); | ||||||
|  |  | ||||||
| 	/* Apply all upper menus' visibilities to actual prompts. */ | 	/* Apply all upper menus' visibilities to actual prompts. */ | ||||||
| 		if(type == P_PROMPT) { | 	if (type == P_PROMPT) { | ||||||
| 		struct menu *menu = current_entry; | 		struct menu *menu = current_entry; | ||||||
|  |  | ||||||
| 		while ((menu = menu->parent) != NULL) { | 		while ((menu = menu->parent) != NULL) { | ||||||
| @@ -152,34 +175,25 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e | |||||||
| 			if (!menu->visibility) | 			if (!menu->visibility) | ||||||
| 				continue; | 				continue; | ||||||
| 			/* | 			/* | ||||||
| 				 * Do not add a reference to the | 			 * Do not add a reference to the menu's visibility | ||||||
| 				 * menu's visibility expression but | 			 * expression but use a copy of it. Otherwise the | ||||||
| 				 * use a copy of it.  Otherwise the | 			 * expression reduction functions will modify | ||||||
| 				 * expression reduction functions | 			 * expressions that have multiple references which | ||||||
| 				 * will modify expressions that have | 			 * can cause unwanted side effects. | ||||||
| 				 * multiple references which can |  | ||||||
| 				 * cause unwanted side effects. |  | ||||||
| 			 */ | 			 */ | ||||||
| 			dup_expr = expr_copy(menu->visibility); | 			dup_expr = expr_copy(menu->visibility); | ||||||
|  |  | ||||||
| 				prop->visible.expr | 			prop->visible.expr = expr_alloc_and(prop->visible.expr, | ||||||
| 					= expr_alloc_and(prop->visible.expr, |  | ||||||
| 							    dup_expr); | 							    dup_expr); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	current_entry->prompt = prop; | 	current_entry->prompt = prop; | ||||||
| 	} |  | ||||||
| 	prop->text = prompt; | 	prop->text = prompt; | ||||||
|  |  | ||||||
| 	return prop; | 	return prop; | ||||||
| } | } | ||||||
|  |  | ||||||
| struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) |  | ||||||
| { |  | ||||||
| 	return menu_add_prop(type, prompt, NULL, dep); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void menu_add_visibility(struct expr *expr) | void menu_add_visibility(struct expr *expr) | ||||||
| { | { | ||||||
| 	current_entry->visibility = expr_alloc_and(current_entry->visibility, | 	current_entry->visibility = expr_alloc_and(current_entry->visibility, | ||||||
| @@ -188,39 +202,34 @@ void menu_add_visibility(struct expr *expr) | |||||||
|  |  | ||||||
| void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) | void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) | ||||||
| { | { | ||||||
| 	menu_add_prop(type, NULL, expr, dep); | 	menu_add_prop(type, expr, dep); | ||||||
| } | } | ||||||
|  |  | ||||||
| void menu_add_symbol(enum prop_type type, struct symbol *sym, struct 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); | 	menu_add_prop(type, expr_alloc_symbol(sym), dep); | ||||||
| } | } | ||||||
|  |  | ||||||
| void menu_add_option(int token, char *arg) | void menu_add_option_modules(void) | ||||||
| { | { | ||||||
| 	switch (token) { |  | ||||||
| 	case T_OPT_MODULES: |  | ||||||
| 	if (modules_sym) | 	if (modules_sym) | ||||||
| 			zconf_error("symbol '%s' redefines option 'modules'" | 		zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'", | ||||||
| 				    " already defined by symbol '%s'", | 			    current_entry->sym->name, modules_sym->name); | ||||||
| 				    current_entry->sym->name, |  | ||||||
| 				    modules_sym->name |  | ||||||
| 				    ); |  | ||||||
| 	modules_sym = current_entry->sym; | 	modules_sym = current_entry->sym; | ||||||
| 		break; | } | ||||||
| 	case T_OPT_DEFCONFIG_LIST: |  | ||||||
|  | void menu_add_option_defconfig_list(void) | ||||||
|  | { | ||||||
| 	if (!sym_defconfig_list) | 	if (!sym_defconfig_list) | ||||||
| 		sym_defconfig_list = current_entry->sym; | 		sym_defconfig_list = current_entry->sym; | ||||||
| 	else if (sym_defconfig_list != current_entry->sym) | 	else if (sym_defconfig_list != current_entry->sym) | ||||||
| 		zconf_error("trying to redefine defconfig symbol"); | 		zconf_error("trying to redefine defconfig symbol"); | ||||||
| 		break; | 	sym_defconfig_list->flags |= SYMBOL_NO_WRITE; | ||||||
| 	case T_OPT_ENV: | } | ||||||
| 		prop_add_env(arg); |  | ||||||
| 		break; | void menu_add_option_allnoconfig_y(void) | ||||||
| 	case T_OPT_ALLNOCONFIG_Y: | { | ||||||
| 	current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y; | 	current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y; | ||||||
| 		break; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static int menu_validate_number(struct symbol *sym, struct symbol *sym2) | static int menu_validate_number(struct symbol *sym, struct symbol *sym2) | ||||||
| @@ -233,6 +242,8 @@ static void sym_check_prop(struct symbol *sym) | |||||||
| { | { | ||||||
| 	struct property *prop; | 	struct property *prop; | ||||||
| 	struct symbol *sym2; | 	struct symbol *sym2; | ||||||
|  | 	char *use; | ||||||
|  |  | ||||||
| 	for (prop = sym->prop; prop; prop = prop->next) { | 	for (prop = sym->prop; prop; prop = prop->next) { | ||||||
| 		switch (prop->type) { | 		switch (prop->type) { | ||||||
| 		case P_DEFAULT: | 		case P_DEFAULT: | ||||||
| @@ -250,20 +261,32 @@ static void sym_check_prop(struct symbol *sym) | |||||||
| 					    "'%s': number is invalid", | 					    "'%s': number is invalid", | ||||||
| 					    sym->name); | 					    sym->name); | ||||||
| 			} | 			} | ||||||
|  | 			if (sym_is_choice(sym)) { | ||||||
|  | 				struct property *choice_prop = | ||||||
|  | 					sym_get_choice_prop(sym2); | ||||||
|  |  | ||||||
|  | 				if (!choice_prop || | ||||||
|  | 				    prop_get_symbol(choice_prop) != sym) | ||||||
|  | 					prop_warn(prop, | ||||||
|  | 						  "choice default symbol '%s' is not contained in the choice", | ||||||
|  | 						  sym2->name); | ||||||
|  | 			} | ||||||
| 			break; | 			break; | ||||||
| 		case P_SELECT: | 		case P_SELECT: | ||||||
|  | 		case P_IMPLY: | ||||||
|  | 			use = prop->type == P_SELECT ? "select" : "imply"; | ||||||
| 			sym2 = prop_get_symbol(prop); | 			sym2 = prop_get_symbol(prop); | ||||||
| 			if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) | 			if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) | ||||||
| 				prop_warn(prop, | 				prop_warn(prop, | ||||||
| 				    "config symbol '%s' uses select, but is " | 				    "config symbol '%s' uses %s, but is " | ||||||
| 				    "not boolean or tristate", sym->name); | 				    "not bool or tristate", sym->name, use); | ||||||
| 			else if (sym2->type != S_UNKNOWN && | 			else if (sym2->type != S_UNKNOWN && | ||||||
| 				 sym2->type != S_BOOLEAN && | 				 sym2->type != S_BOOLEAN && | ||||||
| 				 sym2->type != S_TRISTATE) | 				 sym2->type != S_TRISTATE) | ||||||
| 				prop_warn(prop, | 				prop_warn(prop, | ||||||
| 				    "'%s' has wrong type. 'select' only " | 				    "'%s' has wrong type. '%s' only " | ||||||
| 				    "accept arguments of boolean and " | 				    "accept arguments of bool and " | ||||||
| 				    "tristate type", sym2->name); | 				    "tristate type", sym2->name, use); | ||||||
| 			break; | 			break; | ||||||
| 		case P_RANGE: | 		case P_RANGE: | ||||||
| 			if (sym->type != S_INT && sym->type != S_HEX) | 			if (sym->type != S_INT && sym->type != S_HEX) | ||||||
| @@ -288,6 +311,11 @@ void menu_finalize(struct menu *parent) | |||||||
|  |  | ||||||
| 	sym = parent->sym; | 	sym = parent->sym; | ||||||
| 	if (parent->list) { | 	if (parent->list) { | ||||||
|  | 		/* | ||||||
|  | 		 * This menu node has children. We (recursively) process them | ||||||
|  | 		 * and propagate parent dependencies before moving on. | ||||||
|  | 		 */ | ||||||
|  |  | ||||||
| 		if (sym && sym_is_choice(sym)) { | 		if (sym && sym_is_choice(sym)) { | ||||||
| 			if (sym->type == S_UNKNOWN) { | 			if (sym->type == S_UNKNOWN) { | ||||||
| 				/* find the first choice value to find out choice type */ | 				/* find the first choice value to find out choice type */ | ||||||
| @@ -305,65 +333,167 @@ void menu_finalize(struct menu *parent) | |||||||
| 				if (menu->sym && menu->sym->type == S_UNKNOWN) | 				if (menu->sym && menu->sym->type == S_UNKNOWN) | ||||||
| 					menu_set_type(sym->type); | 					menu_set_type(sym->type); | ||||||
| 			} | 			} | ||||||
| 			parentdep = expr_alloc_symbol(sym); |  | ||||||
| 		} else if (parent->prompt) |  | ||||||
| 			parentdep = parent->prompt->visible.expr; |  | ||||||
| 		else |  | ||||||
| 			parentdep = parent->dep; |  | ||||||
|  |  | ||||||
|  | 			/* | ||||||
|  | 			 * Use the choice itself as the parent dependency of | ||||||
|  | 			 * the contained items. This turns the mode of the | ||||||
|  | 			 * choice into an upper bound on the visibility of the | ||||||
|  | 			 * choice value symbols. | ||||||
|  | 			 */ | ||||||
|  | 			parentdep = expr_alloc_symbol(sym); | ||||||
|  | 		} else { | ||||||
|  | 			/* Menu node for 'menu', 'if' */ | ||||||
|  | 			parentdep = parent->dep; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		/* For each child menu node... */ | ||||||
| 		for (menu = parent->list; menu; menu = menu->next) { | 		for (menu = parent->list; menu; menu = menu->next) { | ||||||
| 			basedep = expr_transform(menu->dep); | 			/* | ||||||
|  | 			 * Propagate parent dependencies to the child menu | ||||||
|  | 			 * node, also rewriting and simplifying expressions | ||||||
|  | 			 */ | ||||||
|  | 			basedep = rewrite_m(menu->dep); | ||||||
|  | 			basedep = expr_transform(basedep); | ||||||
| 			basedep = expr_alloc_and(expr_copy(parentdep), basedep); | 			basedep = expr_alloc_and(expr_copy(parentdep), basedep); | ||||||
| 			basedep = expr_eliminate_dups(basedep); | 			basedep = expr_eliminate_dups(basedep); | ||||||
| 			menu->dep = basedep; | 			menu->dep = basedep; | ||||||
|  |  | ||||||
| 			if (menu->sym) | 			if (menu->sym) | ||||||
|  | 				/* | ||||||
|  | 				 * Note: For symbols, all prompts are included | ||||||
|  | 				 * too in the symbol's own property list | ||||||
|  | 				 */ | ||||||
| 				prop = menu->sym->prop; | 				prop = menu->sym->prop; | ||||||
| 			else | 			else | ||||||
|  | 				/* | ||||||
|  | 				 * For non-symbol menu nodes, we just need to | ||||||
|  | 				 * handle the prompt | ||||||
|  | 				 */ | ||||||
| 				prop = menu->prompt; | 				prop = menu->prompt; | ||||||
|  |  | ||||||
|  | 			/* For each property... */ | ||||||
| 			for (; prop; prop = prop->next) { | 			for (; prop; prop = prop->next) { | ||||||
| 				if (prop->menu != menu) | 				if (prop->menu != menu) | ||||||
|  | 					/* | ||||||
|  | 					 * Two possibilities: | ||||||
|  | 					 * | ||||||
|  | 					 * 1. The property lacks dependencies | ||||||
|  | 					 *    and so isn't location-specific, | ||||||
|  | 					 *    e.g. an 'option' | ||||||
|  | 					 * | ||||||
|  | 					 * 2. The property belongs to a symbol | ||||||
|  | 					 *    defined in multiple locations and | ||||||
|  | 					 *    is from some other location. It | ||||||
|  | 					 *    will be handled there in that | ||||||
|  | 					 *    case. | ||||||
|  | 					 * | ||||||
|  | 					 * Skip the property. | ||||||
|  | 					 */ | ||||||
| 					continue; | 					continue; | ||||||
| 				dep = expr_transform(prop->visible.expr); |  | ||||||
|  | 				/* | ||||||
|  | 				 * Propagate parent dependencies to the | ||||||
|  | 				 * property's condition, rewriting and | ||||||
|  | 				 * simplifying expressions at the same time | ||||||
|  | 				 */ | ||||||
|  | 				dep = rewrite_m(prop->visible.expr); | ||||||
|  | 				dep = expr_transform(dep); | ||||||
| 				dep = expr_alloc_and(expr_copy(basedep), dep); | 				dep = expr_alloc_and(expr_copy(basedep), dep); | ||||||
| 				dep = expr_eliminate_dups(dep); | 				dep = expr_eliminate_dups(dep); | ||||||
| 				if (menu->sym && menu->sym->type != S_TRISTATE) | 				if (menu->sym && menu->sym->type != S_TRISTATE) | ||||||
| 					dep = expr_trans_bool(dep); | 					dep = expr_trans_bool(dep); | ||||||
| 				prop->visible.expr = dep; | 				prop->visible.expr = dep; | ||||||
|  |  | ||||||
|  | 				/* | ||||||
|  | 				 * Handle selects and implies, which modify the | ||||||
|  | 				 * dependencies of the selected/implied symbol | ||||||
|  | 				 */ | ||||||
| 				if (prop->type == P_SELECT) { | 				if (prop->type == P_SELECT) { | ||||||
| 					struct symbol *es = prop_get_symbol(prop); | 					struct symbol *es = prop_get_symbol(prop); | ||||||
| 					es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, | 					es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, | ||||||
| 							expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); | 							expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); | ||||||
|  | 				} else if (prop->type == P_IMPLY) { | ||||||
|  | 					struct symbol *es = prop_get_symbol(prop); | ||||||
|  | 					es->implied.expr = expr_alloc_or(es->implied.expr, | ||||||
|  | 							expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		if (sym && sym_is_choice(sym)) | ||||||
|  | 			expr_free(parentdep); | ||||||
|  |  | ||||||
|  | 		/* | ||||||
|  | 		 * Recursively process children in the same fashion before | ||||||
|  | 		 * moving on | ||||||
|  | 		 */ | ||||||
| 		for (menu = parent->list; menu; menu = menu->next) | 		for (menu = parent->list; menu; menu = menu->next) | ||||||
| 			menu_finalize(menu); | 			menu_finalize(menu); | ||||||
| 	} else if (sym) { | 	} else if (sym) { | ||||||
|  | 		/* | ||||||
|  | 		 * Automatic submenu creation. If sym is a symbol and A, B, C, | ||||||
|  | 		 * ... are consecutive items (symbols, menus, ifs, etc.) that | ||||||
|  | 		 * all depend on sym, then the following menu structure is | ||||||
|  | 		 * created: | ||||||
|  | 		 * | ||||||
|  | 		 *	sym | ||||||
|  | 		 *	 +-A | ||||||
|  | 		 *	 +-B | ||||||
|  | 		 *	 +-C | ||||||
|  | 		 *	 ... | ||||||
|  | 		 * | ||||||
|  | 		 * This also works recursively, giving the following structure | ||||||
|  | 		 * if A is a symbol and B depends on A: | ||||||
|  | 		 * | ||||||
|  | 		 *	sym | ||||||
|  | 		 *	 +-A | ||||||
|  | 		 *	 | +-B | ||||||
|  | 		 *	 +-C | ||||||
|  | 		 *	 ... | ||||||
|  | 		 */ | ||||||
|  |  | ||||||
| 		basedep = parent->prompt ? parent->prompt->visible.expr : NULL; | 		basedep = parent->prompt ? parent->prompt->visible.expr : NULL; | ||||||
| 		basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); | 		basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); | ||||||
| 		basedep = expr_eliminate_dups(expr_transform(basedep)); | 		basedep = expr_eliminate_dups(expr_transform(basedep)); | ||||||
|  |  | ||||||
|  | 		/* Examine consecutive elements after sym */ | ||||||
| 		last_menu = NULL; | 		last_menu = NULL; | ||||||
| 		for (menu = parent->next; menu; menu = menu->next) { | 		for (menu = parent->next; menu; menu = menu->next) { | ||||||
| 			dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; | 			dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; | ||||||
| 			if (!expr_contains_symbol(dep, sym)) | 			if (!expr_contains_symbol(dep, sym)) | ||||||
|  | 				/* No dependency, quit */ | ||||||
| 				break; | 				break; | ||||||
| 			if (expr_depends_symbol(dep, sym)) | 			if (expr_depends_symbol(dep, sym)) | ||||||
|  | 				/* Absolute dependency, put in submenu */ | ||||||
| 				goto next; | 				goto next; | ||||||
|  |  | ||||||
|  | 			/* | ||||||
|  | 			 * Also consider it a dependency on sym if our | ||||||
|  | 			 * dependencies contain sym and are a "superset" of | ||||||
|  | 			 * sym's dependencies, e.g. '(sym || Q) && R' when sym | ||||||
|  | 			 * depends on R. | ||||||
|  | 			 * | ||||||
|  | 			 * Note that 'R' might be from an enclosing menu or if, | ||||||
|  | 			 * making this a more common case than it might seem. | ||||||
|  | 			 */ | ||||||
| 			dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); | 			dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); | ||||||
| 			dep = expr_eliminate_dups(expr_transform(dep)); | 			dep = expr_eliminate_dups(expr_transform(dep)); | ||||||
| 			dep2 = expr_copy(basedep); | 			dep2 = expr_copy(basedep); | ||||||
| 			expr_eliminate_eq(&dep, &dep2); | 			expr_eliminate_eq(&dep, &dep2); | ||||||
| 			expr_free(dep); | 			expr_free(dep); | ||||||
| 			if (!expr_is_yes(dep2)) { | 			if (!expr_is_yes(dep2)) { | ||||||
|  | 				/* Not superset, quit */ | ||||||
| 				expr_free(dep2); | 				expr_free(dep2); | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  | 			/* Superset, put in submenu */ | ||||||
| 			expr_free(dep2); | 			expr_free(dep2); | ||||||
| 		next: | 		next: | ||||||
| 			menu_finalize(menu); | 			menu_finalize(menu); | ||||||
| 			menu->parent = parent; | 			menu->parent = parent; | ||||||
| 			last_menu = menu; | 			last_menu = menu; | ||||||
| 		} | 		} | ||||||
|  | 		expr_free(basedep); | ||||||
| 		if (last_menu) { | 		if (last_menu) { | ||||||
| 			parent->list = parent->next; | 			parent->list = parent->next; | ||||||
| 			parent->next = last_menu->next; | 			parent->next = last_menu->next; | ||||||
| @@ -412,6 +542,35 @@ void menu_finalize(struct menu *parent) | |||||||
| 			*ep = expr_alloc_one(E_LIST, NULL); | 			*ep = expr_alloc_one(E_LIST, NULL); | ||||||
| 			(*ep)->right.sym = menu->sym; | 			(*ep)->right.sym = menu->sym; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		/* | ||||||
|  | 		 * This code serves two purposes: | ||||||
|  | 		 * | ||||||
|  | 		 * (1) Flattening 'if' blocks, which do not specify a submenu | ||||||
|  | 		 *     and only add dependencies. | ||||||
|  | 		 * | ||||||
|  | 		 *     (Automatic submenu creation might still create a submenu | ||||||
|  | 		 *     from an 'if' before this code runs.) | ||||||
|  | 		 * | ||||||
|  | 		 * (2) "Undoing" any automatic submenus created earlier below | ||||||
|  | 		 *     promptless symbols. | ||||||
|  | 		 * | ||||||
|  | 		 * Before: | ||||||
|  | 		 * | ||||||
|  | 		 *	A | ||||||
|  | 		 *	if ... (or promptless symbol) | ||||||
|  | 		 *	 +-B | ||||||
|  | 		 *	 +-C | ||||||
|  | 		 *	D | ||||||
|  | 		 * | ||||||
|  | 		 * After: | ||||||
|  | 		 * | ||||||
|  | 		 *	A | ||||||
|  | 		 *	if ... (or promptless symbol) | ||||||
|  | 		 *	B | ||||||
|  | 		 *	C | ||||||
|  | 		 *	D | ||||||
|  | 		 */ | ||||||
| 		if (menu->list && (!menu->prompt || !menu->prompt->text)) { | 		if (menu->list && (!menu->prompt || !menu->prompt->text)) { | ||||||
| 			for (last_menu = menu->list; ; last_menu = last_menu->next) { | 			for (last_menu = menu->list; ; last_menu = last_menu->next) { | ||||||
| 				last_menu->parent = parent; | 				last_menu->parent = parent; | ||||||
| @@ -436,6 +595,15 @@ void menu_finalize(struct menu *parent) | |||||||
| 		sym->flags |= SYMBOL_WARNED; | 		sym->flags |= SYMBOL_WARNED; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * For non-optional choices, add a reverse dependency (corresponding to | ||||||
|  | 	 * a select) of '<visibility> && m'. This prevents the user from | ||||||
|  | 	 * setting the choice mode to 'n' when the choice is visible. | ||||||
|  | 	 * | ||||||
|  | 	 * This would also work for non-choice symbols, but only non-optional | ||||||
|  | 	 * choices clear SYMBOL_OPTIONAL as of writing. Choices are implemented | ||||||
|  | 	 * as a type of symbol. | ||||||
|  | 	 */ | ||||||
| 	if (sym && !sym_is_optional(sym) && parent->prompt) { | 	if (sym && !sym_is_optional(sym) && parent->prompt) { | ||||||
| 		sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, | 		sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, | ||||||
| 				expr_alloc_and(parent->prompt->visible.expr, | 				expr_alloc_and(parent->prompt->visible.expr, | ||||||
| @@ -543,6 +711,21 @@ const char *menu_get_help(struct menu *menu) | |||||||
| 		return ""; | 		return ""; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void get_def_str(struct gstr *r, struct menu *menu) | ||||||
|  | { | ||||||
|  | 	str_printf(r, "Defined at %s:%d\n", | ||||||
|  | 		   menu->file->name, menu->lineno); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix) | ||||||
|  | { | ||||||
|  | 	if (!expr_is_yes(expr)) { | ||||||
|  | 		str_append(r, prefix); | ||||||
|  | 		expr_gstr_print(expr, r); | ||||||
|  | 		str_append(r, "\n"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| static void get_prompt_str(struct gstr *r, struct property *prop, | static void get_prompt_str(struct gstr *r, struct property *prop, | ||||||
| 			   struct list_head *head) | 			   struct list_head *head) | ||||||
| { | { | ||||||
| @@ -550,7 +733,20 @@ static void get_prompt_str(struct gstr *r, struct property *prop, | |||||||
| 	struct menu *submenu[8], *menu, *location = NULL; | 	struct menu *submenu[8], *menu, *location = NULL; | ||||||
| 	struct jump_key *jump = NULL; | 	struct jump_key *jump = NULL; | ||||||
|  |  | ||||||
| 	str_printf(r, _("Prompt: %s\n"), _(prop->text)); | 	str_printf(r, "  Prompt: %s\n", prop->text); | ||||||
|  |  | ||||||
|  | 	get_dep_str(r, prop->menu->dep, "  Depends on: "); | ||||||
|  | 	/* | ||||||
|  | 	 * Most prompts in Linux have visibility that exactly matches their | ||||||
|  | 	 * dependencies. For these, we print only the dependencies to improve | ||||||
|  | 	 * readability. However, prompts with inline "if" expressions and | ||||||
|  | 	 * prompts with a parent that has a "visible if" expression have | ||||||
|  | 	 * differing dependencies and visibility. In these rare cases, we | ||||||
|  | 	 * print both. | ||||||
|  | 	 */ | ||||||
|  | 	if (!expr_eq(prop->menu->dep, prop->visible.expr)) | ||||||
|  | 		get_dep_str(r, prop->visible.expr, "  Visible if: "); | ||||||
|  |  | ||||||
| 	menu = prop->menu->parent; | 	menu = prop->menu->parent; | ||||||
| 	for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) { | 	for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) { | ||||||
| 		bool accessible = menu_is_visible(menu); | 		bool accessible = menu_is_visible(menu); | ||||||
| @@ -583,16 +779,16 @@ static void get_prompt_str(struct gstr *r, struct property *prop, | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (i > 0) { | 	if (i > 0) { | ||||||
| 		str_printf(r, _("  Location:\n")); | 		str_printf(r, "  Location:\n"); | ||||||
| 		for (j = 4; --i >= 0; j += 2) { | 		for (j = 4; --i >= 0; j += 2) { | ||||||
| 			menu = submenu[i]; | 			menu = submenu[i]; | ||||||
| 			if (jump && menu == location) | 			if (jump && menu == location) | ||||||
| 				jump->offset = strlen(r->s); | 				jump->offset = strlen(r->s); | ||||||
| 			str_printf(r, "%*c-> %s", j, ' ', | 			str_printf(r, "%*c-> %s", j, ' ', | ||||||
| 				   _(menu_get_prompt(menu))); | 				   menu_get_prompt(menu)); | ||||||
| 			if (menu->sym) { | 			if (menu->sym) { | ||||||
| 				str_printf(r, " (%s [=%s])", menu->sym->name ? | 				str_printf(r, " (%s [=%s])", menu->sym->name ? | ||||||
| 					menu->sym->name : _("<choice>"), | 					menu->sym->name : "<choice>", | ||||||
| 					sym_get_string_value(menu->sym)); | 					sym_get_string_value(menu->sym)); | ||||||
| 			} | 			} | ||||||
| 			str_append(r, "\n"); | 			str_append(r, "\n"); | ||||||
| @@ -600,16 +796,22 @@ static void get_prompt_str(struct gstr *r, struct property *prop, | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | static void get_symbol_props_str(struct gstr *r, struct symbol *sym, | ||||||
|  * get property of type P_SYMBOL | 				 enum prop_type tok, const char *prefix) | ||||||
|  */ |  | ||||||
| static struct property *get_symbol_prop(struct symbol *sym) |  | ||||||
| { | { | ||||||
| 	struct property *prop = NULL; | 	bool hit = false; | ||||||
|  | 	struct property *prop; | ||||||
|  |  | ||||||
| 	for_all_properties(sym, prop, P_SYMBOL) | 	for_all_properties(sym, prop, tok) { | ||||||
| 		break; | 		if (!hit) { | ||||||
| 	return prop; | 			str_append(r, prefix); | ||||||
|  | 			hit = true; | ||||||
|  | 		} else | ||||||
|  | 			str_printf(r, " && "); | ||||||
|  | 		expr_gstr_print(prop->expr, r); | ||||||
|  | 	} | ||||||
|  | 	if (hit) | ||||||
|  | 		str_append(r, "\n"); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -618,7 +820,6 @@ static struct property *get_symbol_prop(struct symbol *sym) | |||||||
| static void get_symbol_str(struct gstr *r, struct symbol *sym, | static void get_symbol_str(struct gstr *r, struct symbol *sym, | ||||||
| 		    struct list_head *head) | 		    struct list_head *head) | ||||||
| { | { | ||||||
| 	bool hit; |  | ||||||
| 	struct property *prop; | 	struct property *prop; | ||||||
|  |  | ||||||
| 	if (sym && sym->name) { | 	if (sym && sym->name) { | ||||||
| @@ -634,36 +835,36 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym, | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	for_all_prompts(sym, prop) |  | ||||||
| 		get_prompt_str(r, prop, head); |  | ||||||
|  |  | ||||||
| 	prop = get_symbol_prop(sym); | 	/* Print the definitions with prompts before the ones without */ | ||||||
| 	if (prop) { | 	for_all_properties(sym, prop, P_SYMBOL) { | ||||||
| 		str_printf(r, _("  Defined at %s:%d\n"), prop->menu->file->name, | 		if (prop->menu->prompt) { | ||||||
| 			prop->menu->lineno); | 			get_def_str(r, prop->menu); | ||||||
| 		if (!expr_is_yes(prop->visible.expr)) { | 			get_prompt_str(r, prop->menu->prompt, head); | ||||||
| 			str_append(r, _("  Depends on: ")); |  | ||||||
| 			expr_gstr_print(prop->visible.expr, r); |  | ||||||
| 			str_append(r, "\n"); |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hit = false; | 	for_all_properties(sym, prop, P_SYMBOL) { | ||||||
| 	for_all_properties(sym, prop, P_SELECT) { | 		if (!prop->menu->prompt) { | ||||||
| 		if (!hit) { | 			get_def_str(r, prop->menu); | ||||||
| 			str_append(r, "  Selects: "); | 			get_dep_str(r, prop->menu->dep, "  Depends on: "); | ||||||
| 			hit = true; |  | ||||||
| 		} else |  | ||||||
| 			str_printf(r, " && "); |  | ||||||
| 		expr_gstr_print(prop->expr, r); |  | ||||||
| 		} | 		} | ||||||
| 	if (hit) | 	} | ||||||
| 		str_append(r, "\n"); |  | ||||||
|  | 	get_symbol_props_str(r, sym, P_SELECT, "Selects: "); | ||||||
| 	if (sym->rev_dep.expr) { | 	if (sym->rev_dep.expr) { | ||||||
| 		str_append(r, _("  Selected by: ")); | 		expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, "Selected by [y]:\n"); | ||||||
| 		expr_gstr_print(sym->rev_dep.expr, r); | 		expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, "Selected by [m]:\n"); | ||||||
| 		str_append(r, "\n"); | 		expr_gstr_print_revdep(sym->rev_dep.expr, r, no, "Selected by [n]:\n"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	get_symbol_props_str(r, sym, P_IMPLY, "Implies: "); | ||||||
|  | 	if (sym->implied.expr) { | ||||||
|  | 		expr_gstr_print_revdep(sym->implied.expr, r, yes, "Implied by [y]:\n"); | ||||||
|  | 		expr_gstr_print_revdep(sym->implied.expr, r, mod, "Implied by [m]:\n"); | ||||||
|  | 		expr_gstr_print_revdep(sym->implied.expr, r, no, "Implied by [n]:\n"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	str_append(r, "\n\n"); | 	str_append(r, "\n\n"); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -676,7 +877,7 @@ struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head) | |||||||
| 	for (i = 0; sym_arr && (sym = sym_arr[i]); i++) | 	for (i = 0; sym_arr && (sym = sym_arr[i]); i++) | ||||||
| 		get_symbol_str(&res, sym, head); | 		get_symbol_str(&res, sym, head); | ||||||
| 	if (!i) | 	if (!i) | ||||||
| 		str_append(&res, _("No matches found.\n")); | 		str_append(&res, "No matches found.\n"); | ||||||
| 	return res; | 	return res; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -691,7 +892,7 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help) | |||||||
| 			str_printf(help, "%s%s:\n\n", CONFIG_, sym->name); | 			str_printf(help, "%s%s:\n\n", CONFIG_, sym->name); | ||||||
| 		help_text = menu_get_help(menu); | 		help_text = menu_get_help(menu); | ||||||
| 	} | 	} | ||||||
| 	str_printf(help, "%s\n", _(help_text)); | 	str_printf(help, "%s\n", help_text); | ||||||
| 	if (sym) | 	if (sym) | ||||||
| 		get_symbol_str(help, sym, NULL); | 		get_symbol_str(help, sym, NULL); | ||||||
| } | } | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										129
									
								
								scripts/config/parser.tab.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								scripts/config/parser.tab.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | |||||||
|  | /* A Bison parser, made by GNU Bison 3.1.  */ | ||||||
|  |  | ||||||
|  | /* Bison interface for Yacc-like parsers in C | ||||||
|  |  | ||||||
|  |    Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc. | ||||||
|  |  | ||||||
|  |    This program is free software: you can redistribute it and/or modify | ||||||
|  |    it under the terms of the GNU General Public License as published by | ||||||
|  |    the Free Software Foundation, either version 3 of the License, or | ||||||
|  |    (at your option) any later version. | ||||||
|  |  | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |    You should have received a copy of the GNU General Public License | ||||||
|  |    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | ||||||
|  |  | ||||||
|  | /* As a special exception, you may create a larger work that contains | ||||||
|  |    part or all of the Bison parser skeleton and distribute that work | ||||||
|  |    under terms of your choice, so long as that work isn't itself a | ||||||
|  |    parser generator using the skeleton or a modified version thereof | ||||||
|  |    as a parser skeleton.  Alternatively, if you modify or redistribute | ||||||
|  |    the parser skeleton itself, you may (at your option) remove this | ||||||
|  |    special exception, which will cause the skeleton and the resulting | ||||||
|  |    Bison output files to be licensed under the GNU General Public | ||||||
|  |    License without this special exception. | ||||||
|  |  | ||||||
|  |    This special exception was added by the Free Software Foundation in | ||||||
|  |    version 2.2 of Bison.  */ | ||||||
|  |  | ||||||
|  | #ifndef YY_YY_PARSER_TAB_H_INCLUDED | ||||||
|  | # define YY_YY_PARSER_TAB_H_INCLUDED | ||||||
|  | /* Debug traces.  */ | ||||||
|  | #ifndef YYDEBUG | ||||||
|  | # define YYDEBUG 0 | ||||||
|  | #endif | ||||||
|  | #if YYDEBUG | ||||||
|  | extern int yydebug; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* Token type.  */ | ||||||
|  | #ifndef YYTOKENTYPE | ||||||
|  | # define YYTOKENTYPE | ||||||
|  |   enum yytokentype | ||||||
|  |   { | ||||||
|  |     T_HELPTEXT = 258, | ||||||
|  |     T_WORD = 259, | ||||||
|  |     T_WORD_QUOTE = 260, | ||||||
|  |     T_ALLNOCONFIG_Y = 261, | ||||||
|  |     T_BOOL = 262, | ||||||
|  |     T_CHOICE = 263, | ||||||
|  |     T_CLOSE_PAREN = 264, | ||||||
|  |     T_COLON_EQUAL = 265, | ||||||
|  |     T_COMMENT = 266, | ||||||
|  |     T_CONFIG = 267, | ||||||
|  |     T_DEFAULT = 268, | ||||||
|  |     T_DEFCONFIG_LIST = 269, | ||||||
|  |     T_DEF_BOOL = 270, | ||||||
|  |     T_DEF_TRISTATE = 271, | ||||||
|  |     T_DEPENDS = 272, | ||||||
|  |     T_ENDCHOICE = 273, | ||||||
|  |     T_ENDIF = 274, | ||||||
|  |     T_ENDMENU = 275, | ||||||
|  |     T_HELP = 276, | ||||||
|  |     T_HEX = 277, | ||||||
|  |     T_IF = 278, | ||||||
|  |     T_IMPLY = 279, | ||||||
|  |     T_INT = 280, | ||||||
|  |     T_MAINMENU = 281, | ||||||
|  |     T_MENU = 282, | ||||||
|  |     T_MENUCONFIG = 283, | ||||||
|  |     T_MODULES = 284, | ||||||
|  |     T_ON = 285, | ||||||
|  |     T_OPEN_PAREN = 286, | ||||||
|  |     T_OPTION = 287, | ||||||
|  |     T_OPTIONAL = 288, | ||||||
|  |     T_PLUS_EQUAL = 289, | ||||||
|  |     T_PROMPT = 290, | ||||||
|  |     T_RANGE = 291, | ||||||
|  |     T_RESET = 292, | ||||||
|  |     T_SELECT = 293, | ||||||
|  |     T_SOURCE = 294, | ||||||
|  |     T_STRING = 295, | ||||||
|  |     T_TRISTATE = 296, | ||||||
|  |     T_VISIBLE = 297, | ||||||
|  |     T_EOL = 298, | ||||||
|  |     T_ASSIGN_VAL = 299, | ||||||
|  |     T_OR = 300, | ||||||
|  |     T_AND = 301, | ||||||
|  |     T_EQUAL = 302, | ||||||
|  |     T_UNEQUAL = 303, | ||||||
|  |     T_LESS = 304, | ||||||
|  |     T_LESS_EQUAL = 305, | ||||||
|  |     T_GREATER = 306, | ||||||
|  |     T_GREATER_EQUAL = 307, | ||||||
|  |     T_NOT = 308 | ||||||
|  |   }; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* Value type.  */ | ||||||
|  | #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED | ||||||
|  |  | ||||||
|  | union YYSTYPE | ||||||
|  | { | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	char *string; | ||||||
|  | 	struct symbol *symbol; | ||||||
|  | 	struct expr *expr; | ||||||
|  | 	struct menu *menu; | ||||||
|  | 	enum symbol_type type; | ||||||
|  | 	enum variable_flavor flavor; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef union YYSTYPE YYSTYPE; | ||||||
|  | # define YYSTYPE_IS_TRIVIAL 1 | ||||||
|  | # define YYSTYPE_IS_DECLARED 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | extern YYSTYPE yylval; | ||||||
|  |  | ||||||
|  | int yyparse (void); | ||||||
|  |  | ||||||
|  | #endif /* !YY_YY_PARSER_TAB_H_INCLUDED  */ | ||||||
| @@ -1,8 +1,8 @@ | |||||||
| %{ | /* SPDX-License-Identifier: GPL-2.0 */ | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  * Released under the terms of the GNU GPL v2.0. |  | ||||||
|  */ |  */ | ||||||
|  | %{ | ||||||
| 
 | 
 | ||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
| @@ -20,63 +20,70 @@ | |||||||
| 
 | 
 | ||||||
| int cdebug = PRINTD; | int cdebug = PRINTD; | ||||||
| 
 | 
 | ||||||
| extern int zconflex(void); | static void yyerror(const char *err); | ||||||
| static void zconfprint(const char *err, ...); | static void zconfprint(const char *err, ...); | ||||||
| static void zconf_error(const char *err, ...); | static void zconf_error(const char *err, ...); | ||||||
| static void zconferror(const char *err); | static bool zconf_endtoken(const char *tokenname, | ||||||
| static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken); | 			   const char *expected_tokenname); | ||||||
| 
 | 
 | ||||||
| struct symbol *symbol_hash[SYMBOL_HASHSIZE]; | struct symbol *symbol_hash[SYMBOL_HASHSIZE]; | ||||||
| 
 | 
 | ||||||
| static struct menu *current_menu, *current_entry; | static struct menu *current_menu, *current_entry; | ||||||
| 
 | 
 | ||||||
| %} | %} | ||||||
| %expect 30 |  | ||||||
| 
 | 
 | ||||||
| %union | %union | ||||||
| { | { | ||||||
| 	char *string; | 	char *string; | ||||||
| 	struct file *file; |  | ||||||
| 	struct symbol *symbol; | 	struct symbol *symbol; | ||||||
| 	struct expr *expr; | 	struct expr *expr; | ||||||
| 	struct menu *menu; | 	struct menu *menu; | ||||||
| 	const struct kconf_id *id; | 	enum symbol_type type; | ||||||
|  | 	enum variable_flavor flavor; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| %token <id>T_MAINMENU |  | ||||||
| %token <id>T_MENU |  | ||||||
| %token <id>T_ENDMENU |  | ||||||
| %token <id>T_SOURCE |  | ||||||
| %token <id>T_CHOICE |  | ||||||
| %token <id>T_ENDCHOICE |  | ||||||
| %token <id>T_COMMENT |  | ||||||
| %token <id>T_CONFIG |  | ||||||
| %token <id>T_MENUCONFIG |  | ||||||
| %token <id>T_HELP |  | ||||||
| %token <string> T_HELPTEXT | %token <string> T_HELPTEXT | ||||||
| %token <id>T_IF |  | ||||||
| %token <id>T_ENDIF |  | ||||||
| %token <id>T_DEPENDS |  | ||||||
| %token <id>T_OPTIONAL |  | ||||||
| %token <id>T_PROMPT |  | ||||||
| %token <id>T_TYPE |  | ||||||
| %token <id>T_DEFAULT |  | ||||||
| %token <id>T_SELECT |  | ||||||
| %token <id>T_RANGE |  | ||||||
| %token <id>T_VISIBLE |  | ||||||
| %token <id>T_OPTION |  | ||||||
| %token <id>T_ON |  | ||||||
| %token <id>T_RESET |  | ||||||
| %token <string> T_WORD | %token <string> T_WORD | ||||||
| %token <string> T_WORD_QUOTE | %token <string> T_WORD_QUOTE | ||||||
| %token T_UNEQUAL | %token T_ALLNOCONFIG_Y | ||||||
| %token T_LESS | %token T_BOOL | ||||||
| %token T_LESS_EQUAL | %token T_CHOICE | ||||||
| %token T_GREATER |  | ||||||
| %token T_GREATER_EQUAL |  | ||||||
| %token T_CLOSE_PAREN | %token T_CLOSE_PAREN | ||||||
|  | %token T_COLON_EQUAL | ||||||
|  | %token T_COMMENT | ||||||
|  | %token T_CONFIG | ||||||
|  | %token T_DEFAULT | ||||||
|  | %token T_DEFCONFIG_LIST | ||||||
|  | %token T_DEF_BOOL | ||||||
|  | %token T_DEF_TRISTATE | ||||||
|  | %token T_DEPENDS | ||||||
|  | %token T_ENDCHOICE | ||||||
|  | %token T_ENDIF | ||||||
|  | %token T_ENDMENU | ||||||
|  | %token T_HELP | ||||||
|  | %token T_HEX | ||||||
|  | %token T_IF | ||||||
|  | %token T_IMPLY | ||||||
|  | %token T_INT | ||||||
|  | %token T_MAINMENU | ||||||
|  | %token T_MENU | ||||||
|  | %token T_MENUCONFIG | ||||||
|  | %token T_MODULES | ||||||
|  | %token T_ON | ||||||
| %token T_OPEN_PAREN | %token T_OPEN_PAREN | ||||||
|  | %token T_OPTION | ||||||
|  | %token T_OPTIONAL | ||||||
|  | %token T_PLUS_EQUAL | ||||||
|  | %token T_PROMPT | ||||||
|  | %token T_RANGE | ||||||
|  | %token T_RESET | ||||||
|  | %token T_SELECT | ||||||
|  | %token T_SOURCE | ||||||
|  | %token T_STRING | ||||||
|  | %token T_TRISTATE | ||||||
|  | %token T_VISIBLE | ||||||
| %token T_EOL | %token T_EOL | ||||||
|  | %token <string> T_ASSIGN_VAL | ||||||
| 
 | 
 | ||||||
| %left T_OR | %left T_OR | ||||||
| %left T_AND | %left T_AND | ||||||
| @@ -84,14 +91,15 @@ static struct menu *current_menu, *current_entry; | |||||||
| %left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL | %left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL | ||||||
| %nonassoc T_NOT | %nonassoc T_NOT | ||||||
| 
 | 
 | ||||||
| %type <string> prompt | %type <symbol> nonconst_symbol | ||||||
| %type <symbol> symbol | %type <symbol> symbol | ||||||
|  | %type <type> type logic_type default | ||||||
| %type <expr> expr | %type <expr> expr | ||||||
| %type <expr> if_expr | %type <expr> if_expr | ||||||
| %type <id> end | %type <string> end | ||||||
| %type <id> option_name |  | ||||||
| %type <menu> if_entry menu_entry choice_entry | %type <menu> if_entry menu_entry choice_entry | ||||||
| %type <string> symbol_option_arg word_opt | %type <string> word_opt assign_val | ||||||
|  | %type <flavor> assign_op | ||||||
| 
 | 
 | ||||||
| %destructor { | %destructor { | ||||||
| 	fprintf(stderr, "%s:%d: missing end statement for this entry\n", | 	fprintf(stderr, "%s:%d: missing end statement for this entry\n", | ||||||
| @@ -100,71 +108,53 @@ static struct menu *current_menu, *current_entry; | |||||||
| 		menu_end_menu(); | 		menu_end_menu(); | ||||||
| } if_entry menu_entry choice_entry | } if_entry menu_entry choice_entry | ||||||
| 
 | 
 | ||||||
| %{ |  | ||||||
| /* Include zconf.hash.c here so it can see the token constants. */ |  | ||||||
| #include "zconf.hash.c" |  | ||||||
| %} |  | ||||||
| 
 |  | ||||||
| %% | %% | ||||||
| input: nl start | start; | input: mainmenu_stmt stmt_list | stmt_list; | ||||||
| 
 | 
 | ||||||
| start: mainmenu_stmt stmt_list | stmt_list; | /* mainmenu entry */ | ||||||
|  | 
 | ||||||
|  | mainmenu_stmt: T_MAINMENU T_WORD_QUOTE T_EOL | ||||||
|  | { | ||||||
|  | 	menu_add_prompt(P_MENU, $2, NULL); | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| stmt_list: | stmt_list: | ||||||
| 	  /* empty */ | 	  /* empty */ | ||||||
| 	| stmt_list common_stmt | 	| stmt_list common_stmt | ||||||
| 	| stmt_list choice_stmt | 	| stmt_list choice_stmt | ||||||
| 	| stmt_list menu_stmt | 	| stmt_list menu_stmt | ||||||
| 	| stmt_list end			{ zconf_error("unexpected end statement"); } |  | ||||||
| 	| stmt_list T_WORD error T_EOL	{ zconf_error("unknown statement \"%s\"", $2); } | 	| stmt_list T_WORD error T_EOL	{ zconf_error("unknown statement \"%s\"", $2); } | ||||||
| 	| stmt_list option_name error T_EOL |  | ||||||
| { |  | ||||||
| 	zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name); |  | ||||||
| } |  | ||||||
| 	| stmt_list error T_EOL		{ zconf_error("invalid statement"); } | 	| stmt_list error T_EOL		{ zconf_error("invalid statement"); } | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
| option_name: |  | ||||||
| 	T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE | T_RESET |  | ||||||
| ; |  | ||||||
| 
 |  | ||||||
| common_stmt: | common_stmt: | ||||||
| 	  T_EOL | 	  if_stmt | ||||||
| 	| if_stmt |  | ||||||
| 	| comment_stmt | 	| comment_stmt | ||||||
| 	| config_stmt | 	| config_stmt | ||||||
| 	| menuconfig_stmt | 	| menuconfig_stmt | ||||||
| 	| source_stmt | 	| source_stmt | ||||||
|  | 	| assignment_stmt | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
| option_error: |  | ||||||
| 	  T_WORD error T_EOL		{ zconf_error("unknown option \"%s\"", $1); } |  | ||||||
| 	| error T_EOL			{ zconf_error("invalid option"); } |  | ||||||
| ; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /* config/menuconfig entry */ | /* config/menuconfig entry */ | ||||||
| 
 | 
 | ||||||
| config_entry_start: T_CONFIG T_WORD T_EOL | config_entry_start: T_CONFIG nonconst_symbol T_EOL | ||||||
| { | { | ||||||
| 	struct symbol *sym = sym_lookup($2, 0); | 	$2->flags |= SYMBOL_OPTIONAL; | ||||||
| 	sym->flags |= SYMBOL_OPTIONAL; | 	menu_add_entry($2); | ||||||
| 	menu_add_entry(sym); | 	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2->name); | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2); |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| config_stmt: config_entry_start config_option_list | config_stmt: config_entry_start config_option_list | ||||||
| { | { | ||||||
| 	menu_end_entry(); |  | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); | 	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL | menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL | ||||||
| { | { | ||||||
| 	struct symbol *sym = sym_lookup($2, 0); | 	$2->flags |= SYMBOL_OPTIONAL; | ||||||
| 	sym->flags |= SYMBOL_OPTIONAL; | 	menu_add_entry($2); | ||||||
| 	menu_add_entry(sym); | 	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2->name); | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2); |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| menuconfig_stmt: menuconfig_entry_start config_option_list | menuconfig_stmt: menuconfig_entry_start config_option_list | ||||||
| @@ -173,84 +163,82 @@ menuconfig_stmt: menuconfig_entry_start config_option_list | |||||||
| 		current_entry->prompt->type = P_MENU; | 		current_entry->prompt->type = P_MENU; | ||||||
| 	else | 	else | ||||||
| 		zconfprint("warning: menuconfig statement without prompt"); | 		zconfprint("warning: menuconfig statement without prompt"); | ||||||
| 	menu_end_entry(); |  | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); | 	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| config_option_list: | config_option_list: | ||||||
| 	  /* empty */ | 	  /* empty */ | ||||||
| 	| config_option_list config_option | 	| config_option_list config_option | ||||||
| 	| config_option_list symbol_option |  | ||||||
| 	| config_option_list depends | 	| config_option_list depends | ||||||
| 	| config_option_list help | 	| config_option_list help | ||||||
| 	| config_option_list option_error |  | ||||||
| 	| config_option_list T_EOL |  | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
| config_option: T_TYPE prompt_stmt_opt T_EOL | config_option: type prompt_stmt_opt T_EOL | ||||||
| { | { | ||||||
| 	menu_set_type($1->stype); | 	menu_set_type($1); | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:type(%u)\n", | 	printd(DEBUG_PARSE, "%s:%d:type(%u)\n", | ||||||
| 		zconf_curname(), zconf_lineno(), | 		zconf_curname(), zconf_lineno(), | ||||||
| 		$1->stype); | 		$1); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| config_option: T_PROMPT prompt if_expr T_EOL | config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL | ||||||
| { | { | ||||||
| 	menu_add_prompt(P_PROMPT, $2, $3); | 	menu_add_prompt(P_PROMPT, $2, $3); | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); | 	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| config_option: T_DEFAULT expr if_expr T_EOL | config_option: default expr if_expr T_EOL | ||||||
| { | { | ||||||
| 	menu_add_expr(P_DEFAULT, $2, $3); | 	menu_add_expr(P_DEFAULT, $2, $3); | ||||||
| 	if ($1->stype != S_UNKNOWN) | 	if ($1 != S_UNKNOWN) | ||||||
| 		menu_set_type($1->stype); | 		menu_set_type($1); | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:default(%u)\n", | 	printd(DEBUG_PARSE, "%s:%d:default(%u)\n", | ||||||
| 		zconf_curname(), zconf_lineno(), | 		zconf_curname(), zconf_lineno(), | ||||||
| 		$1->stype); | 		$1); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| config_option: T_SELECT T_WORD if_expr T_EOL | config_option: T_SELECT nonconst_symbol if_expr T_EOL | ||||||
| { | { | ||||||
| 	menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3); | 	menu_add_symbol(P_SELECT, $2, $3); | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); | 	printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | config_option: T_IMPLY nonconst_symbol if_expr T_EOL | ||||||
|  | { | ||||||
|  | 	menu_add_symbol(P_IMPLY, $2, $3); | ||||||
|  | 	printd(DEBUG_PARSE, "%s:%d:imply\n", zconf_curname(), zconf_lineno()); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| config_option: T_RANGE symbol symbol if_expr T_EOL | config_option: T_RANGE symbol symbol if_expr T_EOL | ||||||
| { | { | ||||||
| 	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4); | 	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4); | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); | 	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| symbol_option: T_OPTION symbol_option_list T_EOL | config_option: T_OPTION T_MODULES T_EOL | ||||||
| ; |  | ||||||
| 
 |  | ||||||
| symbol_option_list: |  | ||||||
| 	  /* empty */ |  | ||||||
| 	| symbol_option_list T_WORD symbol_option_arg |  | ||||||
| { | { | ||||||
| 	const struct kconf_id *id = kconf_id_lookup($2, strlen($2)); | 	menu_add_option_modules(); | ||||||
| 	if (id && id->flags & TF_OPTION) |  | ||||||
| 		menu_add_option(id->token, $3); |  | ||||||
| 	else |  | ||||||
| 		zconfprint("warning: ignoring unknown option %s", $2); |  | ||||||
| 	free($2); |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| symbol_option_arg: | config_option: T_OPTION T_DEFCONFIG_LIST T_EOL | ||||||
| 	  /* empty */		{ $$ = NULL; } | { | ||||||
| 	| T_EQUAL prompt	{ $$ = $2; } | 	menu_add_option_defconfig_list(); | ||||||
| ; | }; | ||||||
|  | 
 | ||||||
|  | config_option: T_OPTION T_ALLNOCONFIG_Y T_EOL | ||||||
|  | { | ||||||
|  | 	menu_add_option_allnoconfig_y(); | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| /* choice entry */ | /* choice entry */ | ||||||
| 
 | 
 | ||||||
| choice: T_CHOICE word_opt T_EOL | choice: T_CHOICE word_opt T_EOL | ||||||
| { | { | ||||||
| 	struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); | 	struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); | ||||||
| 	sym->flags |= SYMBOL_AUTO; | 	sym->flags |= SYMBOL_NO_WRITE; | ||||||
| 	menu_add_entry(sym); | 	menu_add_entry(sym); | ||||||
| 	menu_add_expr(P_CHOICE, NULL, NULL); | 	menu_add_expr(P_CHOICE, NULL, NULL); | ||||||
|  | 	free($2); | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); | 	printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @@ -261,7 +249,7 @@ choice_entry: choice choice_option_list | |||||||
| 
 | 
 | ||||||
| choice_end: end | choice_end: end | ||||||
| { | { | ||||||
| 	if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) { | 	if (zconf_endtoken($1, "choice")) { | ||||||
| 		menu_end_menu(); | 		menu_end_menu(); | ||||||
| 		printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); | 		printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); | ||||||
| 	} | 	} | ||||||
| @@ -275,25 +263,19 @@ choice_option_list: | |||||||
| 	| choice_option_list choice_option | 	| choice_option_list choice_option | ||||||
| 	| choice_option_list depends | 	| choice_option_list depends | ||||||
| 	| choice_option_list help | 	| choice_option_list help | ||||||
| 	| choice_option_list T_EOL |  | ||||||
| 	| choice_option_list option_error |  | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
| choice_option: T_PROMPT prompt if_expr T_EOL | choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL | ||||||
| { | { | ||||||
| 	menu_add_prompt(P_PROMPT, $2, $3); | 	menu_add_prompt(P_PROMPT, $2, $3); | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); | 	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| choice_option: T_TYPE prompt_stmt_opt T_EOL | choice_option: logic_type prompt_stmt_opt T_EOL | ||||||
| { | { | ||||||
| 	if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) { | 	menu_set_type($1); | ||||||
| 		menu_set_type($1->stype); |  | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:type(%u)\n", | 	printd(DEBUG_PARSE, "%s:%d:type(%u)\n", | ||||||
| 			zconf_curname(), zconf_lineno(), | 	       zconf_curname(), zconf_lineno(), $1); | ||||||
| 			$1->stype); |  | ||||||
| 	} else |  | ||||||
| 		YYERROR; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| choice_option: T_OPTIONAL T_EOL | choice_option: T_OPTIONAL T_EOL | ||||||
| @@ -304,19 +286,31 @@ choice_option: T_OPTIONAL T_EOL | |||||||
| 
 | 
 | ||||||
| choice_option: T_RESET if_expr T_EOL | choice_option: T_RESET if_expr T_EOL | ||||||
| { | { | ||||||
| 	menu_add_prop(P_RESET, NULL, NULL, $2); | 	menu_add_prop(P_RESET, NULL, $2); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| choice_option: T_DEFAULT T_WORD if_expr T_EOL | choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL | ||||||
| { | { | ||||||
| 	if ($1->stype == S_UNKNOWN) { | 	menu_add_symbol(P_DEFAULT, $2, $3); | ||||||
| 		menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3); |  | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:default\n", | 	printd(DEBUG_PARSE, "%s:%d:default\n", | ||||||
| 	       zconf_curname(), zconf_lineno()); | 	       zconf_curname(), zconf_lineno()); | ||||||
| 	} else |  | ||||||
| 		YYERROR; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | type: | ||||||
|  | 	  logic_type | ||||||
|  | 	| T_INT			{ $$ = S_INT; } | ||||||
|  | 	| T_HEX			{ $$ = S_HEX; } | ||||||
|  | 	| T_STRING		{ $$ = S_STRING; } | ||||||
|  | 
 | ||||||
|  | logic_type: | ||||||
|  | 	  T_BOOL		{ $$ = S_BOOLEAN; } | ||||||
|  | 	| T_TRISTATE		{ $$ = S_TRISTATE; } | ||||||
|  | 
 | ||||||
|  | default: | ||||||
|  | 	  T_DEFAULT		{ $$ = S_UNKNOWN; } | ||||||
|  | 	| T_DEF_BOOL		{ $$ = S_BOOLEAN; } | ||||||
|  | 	| T_DEF_TRISTATE	{ $$ = S_TRISTATE; } | ||||||
|  | 
 | ||||||
| choice_block: | choice_block: | ||||||
| 	  /* empty */ | 	  /* empty */ | ||||||
| 	| choice_block common_stmt | 	| choice_block common_stmt | ||||||
| @@ -324,7 +318,7 @@ choice_block: | |||||||
| 
 | 
 | ||||||
| /* if entry */ | /* if entry */ | ||||||
| 
 | 
 | ||||||
| if_entry: T_IF expr nl | if_entry: T_IF expr T_EOL | ||||||
| { | { | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); | 	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); | ||||||
| 	menu_add_entry(NULL); | 	menu_add_entry(NULL); | ||||||
| @@ -334,80 +328,69 @@ if_entry: T_IF expr nl | |||||||
| 
 | 
 | ||||||
| if_end: end | if_end: end | ||||||
| { | { | ||||||
| 	if (zconf_endtoken($1, T_IF, T_ENDIF)) { | 	if (zconf_endtoken($1, "if")) { | ||||||
| 		menu_end_menu(); | 		menu_end_menu(); | ||||||
| 		printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); | 		printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| if_stmt: if_entry if_block if_end | if_stmt: if_entry stmt_list if_end | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
| if_block: |  | ||||||
| 	  /* empty */ |  | ||||||
| 	| if_block common_stmt |  | ||||||
| 	| if_block menu_stmt |  | ||||||
| 	| if_block choice_stmt |  | ||||||
| ; |  | ||||||
| 
 |  | ||||||
| /* mainmenu entry */ |  | ||||||
| 
 |  | ||||||
| mainmenu_stmt: T_MAINMENU prompt nl |  | ||||||
| { |  | ||||||
| 	menu_add_prompt(P_MENU, $2, NULL); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /* menu entry */ | /* menu entry */ | ||||||
| 
 | 
 | ||||||
| menu: T_MENU prompt T_EOL | menu: T_MENU T_WORD_QUOTE T_EOL | ||||||
| { | { | ||||||
| 	menu_add_entry(NULL); | 	menu_add_entry(NULL); | ||||||
| 	menu_add_prompt(P_MENU, $2, NULL); | 	menu_add_prompt(P_MENU, $2, NULL); | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); | 	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| menu_entry: menu visibility_list depends_list | menu_entry: menu menu_option_list | ||||||
| { | { | ||||||
| 	$$ = menu_add_menu(); | 	$$ = menu_add_menu(); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| menu_end: end | menu_end: end | ||||||
| { | { | ||||||
| 	if (zconf_endtoken($1, T_MENU, T_ENDMENU)) { | 	if (zconf_endtoken($1, "menu")) { | ||||||
| 		menu_end_menu(); | 		menu_end_menu(); | ||||||
| 		printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); | 		printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| menu_stmt: menu_entry menu_block menu_end | menu_stmt: menu_entry stmt_list menu_end | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
| menu_block: | menu_option_list: | ||||||
| 	  /* empty */ | 	  /* empty */ | ||||||
| 	| menu_block common_stmt | 	| menu_option_list visible | ||||||
| 	| menu_block menu_stmt | 	| menu_option_list depends | ||||||
| 	| menu_block choice_stmt |  | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
| source_stmt: T_SOURCE prompt T_EOL | source_stmt: T_SOURCE T_WORD_QUOTE T_EOL | ||||||
| { | { | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); | 	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); | ||||||
| 	zconf_nextfile($2); | 	zconf_nextfile($2); | ||||||
|  | 	free($2); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* comment entry */ | /* comment entry */ | ||||||
| 
 | 
 | ||||||
| comment: T_COMMENT prompt T_EOL | comment: T_COMMENT T_WORD_QUOTE T_EOL | ||||||
| { | { | ||||||
| 	menu_add_entry(NULL); | 	menu_add_entry(NULL); | ||||||
| 	menu_add_prompt(P_COMMENT, $2, NULL); | 	menu_add_prompt(P_COMMENT, $2, NULL); | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); | 	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| comment_stmt: comment depends_list | comment_stmt: comment comment_option_list | ||||||
| { | ; | ||||||
| 	menu_end_entry(); | 
 | ||||||
| }; | comment_option_list: | ||||||
|  | 	  /* empty */ | ||||||
|  | 	| comment_option_list depends | ||||||
|  | ; | ||||||
| 
 | 
 | ||||||
| /* help option */ | /* help option */ | ||||||
| 
 | 
 | ||||||
| @@ -419,37 +402,24 @@ help_start: T_HELP T_EOL | |||||||
| 
 | 
 | ||||||
| help: help_start T_HELPTEXT | help: help_start T_HELPTEXT | ||||||
| { | { | ||||||
|  | 	/* Is the help text empty or all whitespace? */ | ||||||
|  | 	if ($2[strspn($2, " \f\n\r\t\v")] == '\0') | ||||||
|  | 		zconfprint("warning: '%s' defined with blank help text", | ||||||
|  | 			   current_entry->sym->name ?: "<choice>"); | ||||||
|  | 
 | ||||||
| 	current_entry->help = $2; | 	current_entry->help = $2; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* depends option */ | /* depends option */ | ||||||
| 
 | 
 | ||||||
| depends_list: |  | ||||||
| 	  /* empty */ |  | ||||||
| 	| depends_list depends |  | ||||||
| 	| depends_list T_EOL |  | ||||||
| 	| depends_list option_error |  | ||||||
| ; |  | ||||||
| 
 |  | ||||||
| depends: T_DEPENDS T_ON expr T_EOL | depends: T_DEPENDS T_ON expr T_EOL | ||||||
| { | { | ||||||
| 	menu_add_dep($3); | 	menu_add_dep($3); | ||||||
| 	printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); | 	printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); | ||||||
| } | T_DEPENDS expr T_EOL |  | ||||||
| { |  | ||||||
| 	menu_add_dep($2); |  | ||||||
| 	zconfprint("warning: deprecated 'depends' syntax, use 'depends on' instead."); |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* visibility option */ | /* visibility option */ | ||||||
| 
 | visible: T_VISIBLE if_expr T_EOL | ||||||
| visibility_list: |  | ||||||
| 	  /* empty */ |  | ||||||
| 	| visibility_list visible |  | ||||||
| 	| visibility_list T_EOL |  | ||||||
| ; |  | ||||||
| 
 |  | ||||||
| visible: T_VISIBLE if_expr |  | ||||||
| { | { | ||||||
| 	menu_add_visibility($2); | 	menu_add_visibility($2); | ||||||
| }; | }; | ||||||
| @@ -458,23 +428,14 @@ visible: T_VISIBLE if_expr | |||||||
| 
 | 
 | ||||||
| prompt_stmt_opt: | prompt_stmt_opt: | ||||||
| 	  /* empty */ | 	  /* empty */ | ||||||
| 	| prompt if_expr | 	| T_WORD_QUOTE if_expr | ||||||
| { | { | ||||||
| 	menu_add_prompt(P_PROMPT, $1, $2); | 	menu_add_prompt(P_PROMPT, $1, $2); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| prompt:	  T_WORD | end:	  T_ENDMENU T_EOL	{ $$ = "menu"; } | ||||||
| 	| T_WORD_QUOTE | 	| T_ENDCHOICE T_EOL	{ $$ = "choice"; } | ||||||
| ; | 	| T_ENDIF T_EOL		{ $$ = "if"; } | ||||||
| 
 |  | ||||||
| end:	  T_ENDMENU T_EOL	{ $$ = $1; } |  | ||||||
| 	| T_ENDCHOICE T_EOL	{ $$ = $1; } |  | ||||||
| 	| T_ENDIF T_EOL		{ $$ = $1; } |  | ||||||
| ; |  | ||||||
| 
 |  | ||||||
| nl: |  | ||||||
| 	  T_EOL |  | ||||||
| 	| nl T_EOL |  | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
| if_expr:  /* empty */			{ $$ = NULL; } | if_expr:  /* empty */			{ $$ = NULL; } | ||||||
| @@ -494,13 +455,31 @@ expr:	  symbol				{ $$ = expr_alloc_symbol($1); } | |||||||
| 	| expr T_AND expr			{ $$ = expr_alloc_two(E_AND, $1, $3); } | 	| expr T_AND expr			{ $$ = expr_alloc_two(E_AND, $1, $3); } | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
| symbol:	  T_WORD	{ $$ = sym_lookup($1, 0); free($1); } | /* For symbol definitions, selects, etc., where quotes are not accepted */ | ||||||
|  | nonconst_symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }; | ||||||
|  | 
 | ||||||
|  | symbol:	  nonconst_symbol | ||||||
| 	| T_WORD_QUOTE	{ $$ = sym_lookup($1, SYMBOL_CONST); free($1); } | 	| T_WORD_QUOTE	{ $$ = sym_lookup($1, SYMBOL_CONST); free($1); } | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
| word_opt: /* empty */			{ $$ = NULL; } | word_opt: /* empty */			{ $$ = NULL; } | ||||||
| 	| T_WORD | 	| T_WORD | ||||||
| 
 | 
 | ||||||
|  | /* assignment statement */ | ||||||
|  | 
 | ||||||
|  | assignment_stmt:  T_WORD assign_op assign_val T_EOL	{ variable_add($1, $3, $2); free($1); free($3); } | ||||||
|  | 
 | ||||||
|  | assign_op: | ||||||
|  | 	  T_EQUAL	{ $$ = VAR_RECURSIVE; } | ||||||
|  | 	| T_COLON_EQUAL	{ $$ = VAR_SIMPLE; } | ||||||
|  | 	| T_PLUS_EQUAL	{ $$ = VAR_APPEND; } | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | assign_val: | ||||||
|  | 	/* empty */		{ $$ = xstrdup(""); }; | ||||||
|  | 	| T_ASSIGN_VAL | ||||||
|  | ; | ||||||
|  | 
 | ||||||
| %% | %% | ||||||
| 
 | 
 | ||||||
| void conf_parse(const char *name) | void conf_parse(const char *name) | ||||||
| @@ -510,63 +489,53 @@ void conf_parse(const char *name) | |||||||
| 
 | 
 | ||||||
| 	zconf_initscan(name); | 	zconf_initscan(name); | ||||||
| 
 | 
 | ||||||
| 	sym_init(); |  | ||||||
| 	_menu_init(); | 	_menu_init(); | ||||||
| 	rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); |  | ||||||
| 
 | 
 | ||||||
| #if YYDEBUG | #if YYDEBUG | ||||||
| 	if (getenv("ZCONF_DEBUG")) | 	if (getenv("ZCONF_DEBUG")) | ||||||
| 		zconfdebug = 1; | 		yydebug = 1; | ||||||
| #endif | #endif | ||||||
| 	zconfparse(); | 	yyparse(); | ||||||
| 	if (zconfnerrs) | 
 | ||||||
|  | 	/* Variables are expanded in the parse phase. We can free them here. */ | ||||||
|  | 	variable_all_del(); | ||||||
|  | 
 | ||||||
|  | 	if (yynerrs) | ||||||
| 		exit(1); | 		exit(1); | ||||||
| 	if (!modules_sym) | 	if (!modules_sym) | ||||||
| 		modules_sym = sym_find( "n" ); | 		modules_sym = sym_find( "n" ); | ||||||
| 
 | 
 | ||||||
| 	rootmenu.prompt->text = _(rootmenu.prompt->text); | 	if (!menu_has_prompt(&rootmenu)) { | ||||||
| 	rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); | 		current_entry = &rootmenu; | ||||||
|  | 		menu_add_prompt(P_MENU, "Main menu", NULL); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	menu_finalize(&rootmenu); | 	menu_finalize(&rootmenu); | ||||||
| 	for_all_symbols(i, sym) { | 	for_all_symbols(i, sym) { | ||||||
| 		if (sym_check_deps(sym)) | 		if (sym_check_deps(sym)) | ||||||
| 			zconfnerrs++; | 			yynerrs++; | ||||||
| 	} | 	} | ||||||
| 	if (zconfnerrs) | 	if (yynerrs) | ||||||
| 		exit(1); | 		exit(1); | ||||||
| 	sym_set_change_count(1); | 	sym_set_change_count(1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const char *zconf_tokenname(int token) | static bool zconf_endtoken(const char *tokenname, | ||||||
|  | 			   const char *expected_tokenname) | ||||||
| { | { | ||||||
| 	switch (token) { | 	if (strcmp(tokenname, expected_tokenname)) { | ||||||
| 	case T_MENU:		return "menu"; |  | ||||||
| 	case T_ENDMENU:		return "endmenu"; |  | ||||||
| 	case T_CHOICE:		return "choice"; |  | ||||||
| 	case T_ENDCHOICE:	return "endchoice"; |  | ||||||
| 	case T_IF:		return "if"; |  | ||||||
| 	case T_ENDIF:		return "endif"; |  | ||||||
| 	case T_DEPENDS:		return "depends"; |  | ||||||
| 	case T_VISIBLE:		return "visible"; |  | ||||||
| 	} |  | ||||||
| 	return "<token>"; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken) |  | ||||||
| { |  | ||||||
| 	if (id->token != endtoken) { |  | ||||||
| 		zconf_error("unexpected '%s' within %s block", | 		zconf_error("unexpected '%s' within %s block", | ||||||
| 			kconf_id_strings + id->name, zconf_tokenname(starttoken)); | 			    tokenname, expected_tokenname); | ||||||
| 		zconfnerrs++; | 		yynerrs++; | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 	if (current_menu->file != current_file) { | 	if (current_menu->file != current_file) { | ||||||
| 		zconf_error("'%s' in different file than '%s'", | 		zconf_error("'%s' in different file than '%s'", | ||||||
| 			kconf_id_strings + id->name, zconf_tokenname(starttoken)); | 			    tokenname, expected_tokenname); | ||||||
| 		fprintf(stderr, "%s:%d: location of the '%s'\n", | 		fprintf(stderr, "%s:%d: location of the '%s'\n", | ||||||
| 			current_menu->file->name, current_menu->lineno, | 			current_menu->file->name, current_menu->lineno, | ||||||
| 			zconf_tokenname(starttoken)); | 			expected_tokenname); | ||||||
| 		zconfnerrs++; | 		yynerrs++; | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 	return true; | 	return true; | ||||||
| @@ -587,7 +556,7 @@ static void zconf_error(const char *err, ...) | |||||||
| { | { | ||||||
| 	va_list ap; | 	va_list ap; | ||||||
| 
 | 
 | ||||||
| 	zconfnerrs++; | 	yynerrs++; | ||||||
| 	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); | 	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); | ||||||
| 	va_start(ap, err); | 	va_start(ap, err); | ||||||
| 	vfprintf(stderr, err, ap); | 	vfprintf(stderr, err, ap); | ||||||
| @@ -595,7 +564,7 @@ static void zconf_error(const char *err, ...) | |||||||
| 	fprintf(stderr, "\n"); | 	fprintf(stderr, "\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void zconferror(const char *err) | static void yyerror(const char *err) | ||||||
| { | { | ||||||
| 	fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); | 	fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); | ||||||
| } | } | ||||||
| @@ -628,7 +597,7 @@ static void print_symbol(FILE *out, struct menu *menu) | |||||||
| 		fprintf(out, "\nconfig %s\n", sym->name); | 		fprintf(out, "\nconfig %s\n", sym->name); | ||||||
| 	switch (sym->type) { | 	switch (sym->type) { | ||||||
| 	case S_BOOLEAN: | 	case S_BOOLEAN: | ||||||
| 		fputs("  boolean\n", out); | 		fputs("  bool\n", out); | ||||||
| 		break; | 		break; | ||||||
| 	case S_TRISTATE: | 	case S_TRISTATE: | ||||||
| 		fputs("  tristate\n", out); | 		fputs("  tristate\n", out); | ||||||
| @@ -676,6 +645,11 @@ static void print_symbol(FILE *out, struct menu *menu) | |||||||
| 			expr_fprint(prop->expr, out); | 			expr_fprint(prop->expr, out); | ||||||
| 			fputc('\n', out); | 			fputc('\n', out); | ||||||
| 			break; | 			break; | ||||||
|  | 		case P_IMPLY: | ||||||
|  | 			fputs( "  imply ", out); | ||||||
|  | 			expr_fprint(prop->expr, out); | ||||||
|  | 			fputc('\n', out); | ||||||
|  | 			break; | ||||||
| 		case P_RANGE: | 		case P_RANGE: | ||||||
| 			fputs( "  range ", out); | 			fputs( "  range ", out); | ||||||
| 			expr_fprint(prop->expr, out); | 			expr_fprint(prop->expr, out); | ||||||
| @@ -686,6 +660,10 @@ static void print_symbol(FILE *out, struct menu *menu) | |||||||
| 			print_quoted_string(out, prop->text); | 			print_quoted_string(out, prop->text); | ||||||
| 			fputc('\n', out); | 			fputc('\n', out); | ||||||
| 			break; | 			break; | ||||||
|  | 		case P_SYMBOL: | ||||||
|  | 			fputs( "  symbol ", out); | ||||||
|  | 			fprintf(out, "%s\n", prop->menu->sym->name); | ||||||
|  | 			break; | ||||||
| 		default: | 		default: | ||||||
| 			fprintf(out, "  unknown prop %d!\n", prop->type); | 			fprintf(out, "  unknown prop %d!\n", prop->type); | ||||||
| 			break; | 			break; | ||||||
| @@ -746,9 +724,4 @@ void zconfdump(FILE *out) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #include "zconf.lex.c" |  | ||||||
| #include "util.c" |  | ||||||
| #include "confdata.c" |  | ||||||
| #include "expr.c" |  | ||||||
| #include "symbol.c" |  | ||||||
| #include "menu.c" | #include "menu.c" | ||||||
							
								
								
									
										575
									
								
								scripts/config/preprocess.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										575
									
								
								scripts/config/preprocess.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,575 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0 | ||||||
|  | // | ||||||
|  | // Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com> | ||||||
|  |  | ||||||
|  | #include <ctype.h> | ||||||
|  | #include <stdarg.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | #include "list.h" | ||||||
|  | #include "lkc.h" | ||||||
|  |  | ||||||
|  | #define ARRAY_SIZE(arr)		(sizeof(arr) / sizeof((arr)[0])) | ||||||
|  |  | ||||||
|  | static char *expand_string_with_args(const char *in, int argc, char *argv[]); | ||||||
|  | static char *expand_string(const char *in); | ||||||
|  |  | ||||||
|  | static void __attribute__((noreturn)) pperror(const char *format, ...) | ||||||
|  | { | ||||||
|  | 	va_list ap; | ||||||
|  |  | ||||||
|  | 	fprintf(stderr, "%s:%d: ", current_file->name, yylineno); | ||||||
|  | 	va_start(ap, format); | ||||||
|  | 	vfprintf(stderr, format, ap); | ||||||
|  | 	va_end(ap); | ||||||
|  | 	fprintf(stderr, "\n"); | ||||||
|  |  | ||||||
|  | 	exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Environment variables | ||||||
|  |  */ | ||||||
|  | static LIST_HEAD(env_list); | ||||||
|  |  | ||||||
|  | struct env { | ||||||
|  | 	char *name; | ||||||
|  | 	char *value; | ||||||
|  | 	struct list_head node; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static void env_add(const char *name, const char *value) | ||||||
|  | { | ||||||
|  | 	struct env *e; | ||||||
|  |  | ||||||
|  | 	e = xmalloc(sizeof(*e)); | ||||||
|  | 	e->name = xstrdup(name); | ||||||
|  | 	e->value = xstrdup(value); | ||||||
|  |  | ||||||
|  | 	list_add_tail(&e->node, &env_list); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void env_del(struct env *e) | ||||||
|  | { | ||||||
|  | 	list_del(&e->node); | ||||||
|  | 	free(e->name); | ||||||
|  | 	free(e->value); | ||||||
|  | 	free(e); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* The returned pointer must be freed when done */ | ||||||
|  | static char *env_expand(const char *name) | ||||||
|  | { | ||||||
|  | 	struct env *e; | ||||||
|  | 	const char *value; | ||||||
|  |  | ||||||
|  | 	if (!*name) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	list_for_each_entry(e, &env_list, node) { | ||||||
|  | 		if (!strcmp(name, e->name)) | ||||||
|  | 			return xstrdup(e->value); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	value = getenv(name); | ||||||
|  | 	if (!value) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * We need to remember all referenced environment variables. | ||||||
|  | 	 * They will be written out to include/config/auto.conf.cmd | ||||||
|  | 	 */ | ||||||
|  | 	env_add(name, value); | ||||||
|  |  | ||||||
|  | 	return xstrdup(value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void env_write_dep(FILE *f, const char *autoconfig_name) | ||||||
|  | { | ||||||
|  | 	struct env *e, *tmp; | ||||||
|  |  | ||||||
|  | 	list_for_each_entry_safe(e, tmp, &env_list, node) { | ||||||
|  | 		fprintf(f, "ifneq \"$(%s)\" \"%s\"\n", e->name, e->value); | ||||||
|  | 		fprintf(f, "%s: FORCE\n", autoconfig_name); | ||||||
|  | 		fprintf(f, "endif\n"); | ||||||
|  | 		env_del(e); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Built-in functions | ||||||
|  |  */ | ||||||
|  | struct function { | ||||||
|  | 	const char *name; | ||||||
|  | 	unsigned int min_args; | ||||||
|  | 	unsigned int max_args; | ||||||
|  | 	char *(*func)(int argc, char *argv[]); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static char *do_error_if(int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	if (!strcmp(argv[0], "y")) | ||||||
|  | 		pperror("%s", argv[1]); | ||||||
|  |  | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *do_filename(int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	return xstrdup(current_file->name); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *do_info(int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	printf("%s\n", argv[0]); | ||||||
|  |  | ||||||
|  | 	return xstrdup(""); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *do_lineno(int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	char buf[16]; | ||||||
|  |  | ||||||
|  | 	sprintf(buf, "%d", yylineno); | ||||||
|  |  | ||||||
|  | 	return xstrdup(buf); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *do_shell(int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	FILE *p; | ||||||
|  | 	char buf[256]; | ||||||
|  | 	char *cmd; | ||||||
|  | 	size_t nread; | ||||||
|  | 	int i; | ||||||
|  |  | ||||||
|  | 	cmd = argv[0]; | ||||||
|  |  | ||||||
|  | 	p = popen(cmd, "r"); | ||||||
|  | 	if (!p) { | ||||||
|  | 		perror(cmd); | ||||||
|  | 		exit(1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	nread = fread(buf, 1, sizeof(buf), p); | ||||||
|  | 	if (nread == sizeof(buf)) | ||||||
|  | 		nread--; | ||||||
|  |  | ||||||
|  | 	/* remove trailing new lines */ | ||||||
|  | 	while (nread > 0 && buf[nread - 1] == '\n') | ||||||
|  | 		nread--; | ||||||
|  |  | ||||||
|  | 	buf[nread] = 0; | ||||||
|  |  | ||||||
|  | 	/* replace a new line with a space */ | ||||||
|  | 	for (i = 0; i < nread; i++) { | ||||||
|  | 		if (buf[i] == '\n') | ||||||
|  | 			buf[i] = ' '; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (pclose(p) == -1) { | ||||||
|  | 		perror(cmd); | ||||||
|  | 		exit(1); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return xstrdup(buf); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *do_warning_if(int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	if (!strcmp(argv[0], "y")) | ||||||
|  | 		fprintf(stderr, "%s:%d: %s\n", | ||||||
|  | 			current_file->name, yylineno, argv[1]); | ||||||
|  |  | ||||||
|  | 	return xstrdup(""); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static const struct function function_table[] = { | ||||||
|  | 	/* Name		MIN	MAX	Function */ | ||||||
|  | 	{ "error-if",	2,	2,	do_error_if }, | ||||||
|  | 	{ "filename",	0,	0,	do_filename }, | ||||||
|  | 	{ "info",	1,	1,	do_info }, | ||||||
|  | 	{ "lineno",	0,	0,	do_lineno }, | ||||||
|  | 	{ "shell",	1,	1,	do_shell }, | ||||||
|  | 	{ "warning-if",	2,	2,	do_warning_if }, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define FUNCTION_MAX_ARGS		16 | ||||||
|  |  | ||||||
|  | static char *function_expand(const char *name, int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	const struct function *f; | ||||||
|  | 	int i; | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < ARRAY_SIZE(function_table); i++) { | ||||||
|  | 		f = &function_table[i]; | ||||||
|  | 		if (strcmp(f->name, name)) | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		if (argc < f->min_args) | ||||||
|  | 			pperror("too few function arguments passed to '%s'", | ||||||
|  | 				name); | ||||||
|  |  | ||||||
|  | 		if (argc > f->max_args) | ||||||
|  | 			pperror("too many function arguments passed to '%s'", | ||||||
|  | 				name); | ||||||
|  |  | ||||||
|  | 		return f->func(argc, argv); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Variables (and user-defined functions) | ||||||
|  |  */ | ||||||
|  | static LIST_HEAD(variable_list); | ||||||
|  |  | ||||||
|  | struct variable { | ||||||
|  | 	char *name; | ||||||
|  | 	char *value; | ||||||
|  | 	enum variable_flavor flavor; | ||||||
|  | 	int exp_count; | ||||||
|  | 	struct list_head node; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static struct variable *variable_lookup(const char *name) | ||||||
|  | { | ||||||
|  | 	struct variable *v; | ||||||
|  |  | ||||||
|  | 	list_for_each_entry(v, &variable_list, node) { | ||||||
|  | 		if (!strcmp(name, v->name)) | ||||||
|  | 			return v; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *variable_expand(const char *name, int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	struct variable *v; | ||||||
|  | 	char *res; | ||||||
|  |  | ||||||
|  | 	v = variable_lookup(name); | ||||||
|  | 	if (!v) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	if (argc == 0 && v->exp_count) | ||||||
|  | 		pperror("Recursive variable '%s' references itself (eventually)", | ||||||
|  | 			name); | ||||||
|  |  | ||||||
|  | 	if (v->exp_count > 1000) | ||||||
|  | 		pperror("Too deep recursive expansion"); | ||||||
|  |  | ||||||
|  | 	v->exp_count++; | ||||||
|  |  | ||||||
|  | 	if (v->flavor == VAR_RECURSIVE) | ||||||
|  | 		res = expand_string_with_args(v->value, argc, argv); | ||||||
|  | 	else | ||||||
|  | 		res = xstrdup(v->value); | ||||||
|  |  | ||||||
|  | 	v->exp_count--; | ||||||
|  |  | ||||||
|  | 	return res; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void variable_add(const char *name, const char *value, | ||||||
|  | 		  enum variable_flavor flavor) | ||||||
|  | { | ||||||
|  | 	struct variable *v; | ||||||
|  | 	char *new_value; | ||||||
|  | 	bool append = false; | ||||||
|  |  | ||||||
|  | 	v = variable_lookup(name); | ||||||
|  | 	if (v) { | ||||||
|  | 		/* For defined variables, += inherits the existing flavor */ | ||||||
|  | 		if (flavor == VAR_APPEND) { | ||||||
|  | 			flavor = v->flavor; | ||||||
|  | 			append = true; | ||||||
|  | 		} else { | ||||||
|  | 			free(v->value); | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		/* For undefined variables, += assumes the recursive flavor */ | ||||||
|  | 		if (flavor == VAR_APPEND) | ||||||
|  | 			flavor = VAR_RECURSIVE; | ||||||
|  |  | ||||||
|  | 		v = xmalloc(sizeof(*v)); | ||||||
|  | 		v->name = xstrdup(name); | ||||||
|  | 		v->exp_count = 0; | ||||||
|  | 		list_add_tail(&v->node, &variable_list); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	v->flavor = flavor; | ||||||
|  |  | ||||||
|  | 	if (flavor == VAR_SIMPLE) | ||||||
|  | 		new_value = expand_string(value); | ||||||
|  | 	else | ||||||
|  | 		new_value = xstrdup(value); | ||||||
|  |  | ||||||
|  | 	if (append) { | ||||||
|  | 		v->value = xrealloc(v->value, | ||||||
|  | 				    strlen(v->value) + strlen(new_value) + 2); | ||||||
|  | 		strcat(v->value, " "); | ||||||
|  | 		strcat(v->value, new_value); | ||||||
|  | 		free(new_value); | ||||||
|  | 	} else { | ||||||
|  | 		v->value = new_value; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void variable_del(struct variable *v) | ||||||
|  | { | ||||||
|  | 	list_del(&v->node); | ||||||
|  | 	free(v->name); | ||||||
|  | 	free(v->value); | ||||||
|  | 	free(v); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void variable_all_del(void) | ||||||
|  | { | ||||||
|  | 	struct variable *v, *tmp; | ||||||
|  |  | ||||||
|  | 	list_for_each_entry_safe(v, tmp, &variable_list, node) | ||||||
|  | 		variable_del(v); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Evaluate a clause with arguments.  argc/argv are arguments from the upper | ||||||
|  |  * function call. | ||||||
|  |  * | ||||||
|  |  * Returned string must be freed when done | ||||||
|  |  */ | ||||||
|  | static char *eval_clause(const char *str, size_t len, int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	char *tmp, *name, *res, *endptr, *prev, *p; | ||||||
|  | 	int new_argc = 0; | ||||||
|  | 	char *new_argv[FUNCTION_MAX_ARGS]; | ||||||
|  | 	int nest = 0; | ||||||
|  | 	int i; | ||||||
|  | 	unsigned long n; | ||||||
|  |  | ||||||
|  | 	tmp = xstrndup(str, len); | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * If variable name is '1', '2', etc.  It is generally an argument | ||||||
|  | 	 * from a user-function call (i.e. local-scope variable).  If not | ||||||
|  | 	 * available, then look-up global-scope variables. | ||||||
|  | 	 */ | ||||||
|  | 	n = strtoul(tmp, &endptr, 10); | ||||||
|  | 	if (!*endptr && n > 0 && n <= argc) { | ||||||
|  | 		res = xstrdup(argv[n - 1]); | ||||||
|  | 		goto free_tmp; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	prev = p = tmp; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Split into tokens | ||||||
|  | 	 * The function name and arguments are separated by a comma. | ||||||
|  | 	 * For example, if the function call is like this: | ||||||
|  | 	 *   $(foo,$(x),$(y)) | ||||||
|  | 	 * | ||||||
|  | 	 * The input string for this helper should be: | ||||||
|  | 	 *   foo,$(x),$(y) | ||||||
|  | 	 * | ||||||
|  | 	 * and split into: | ||||||
|  | 	 *   new_argv[0] = 'foo' | ||||||
|  | 	 *   new_argv[1] = '$(x)' | ||||||
|  | 	 *   new_argv[2] = '$(y)' | ||||||
|  | 	 */ | ||||||
|  | 	while (*p) { | ||||||
|  | 		if (nest == 0 && *p == ',') { | ||||||
|  | 			*p = 0; | ||||||
|  | 			if (new_argc >= FUNCTION_MAX_ARGS) | ||||||
|  | 				pperror("too many function arguments"); | ||||||
|  | 			new_argv[new_argc++] = prev; | ||||||
|  | 			prev = p + 1; | ||||||
|  | 		} else if (*p == '(') { | ||||||
|  | 			nest++; | ||||||
|  | 		} else if (*p == ')') { | ||||||
|  | 			nest--; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		p++; | ||||||
|  | 	} | ||||||
|  | 	new_argv[new_argc++] = prev; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Shift arguments | ||||||
|  | 	 * new_argv[0] represents a function name or a variable name.  Put it | ||||||
|  | 	 * into 'name', then shift the rest of the arguments.  This simplifies | ||||||
|  | 	 * 'const' handling. | ||||||
|  | 	 */ | ||||||
|  | 	name = expand_string_with_args(new_argv[0], argc, argv); | ||||||
|  | 	new_argc--; | ||||||
|  | 	for (i = 0; i < new_argc; i++) | ||||||
|  | 		new_argv[i] = expand_string_with_args(new_argv[i + 1], | ||||||
|  | 						      argc, argv); | ||||||
|  |  | ||||||
|  | 	/* Search for variables */ | ||||||
|  | 	res = variable_expand(name, new_argc, new_argv); | ||||||
|  | 	if (res) | ||||||
|  | 		goto free; | ||||||
|  |  | ||||||
|  | 	/* Look for built-in functions */ | ||||||
|  | 	res = function_expand(name, new_argc, new_argv); | ||||||
|  | 	if (res) | ||||||
|  | 		goto free; | ||||||
|  |  | ||||||
|  | 	/* Last, try environment variable */ | ||||||
|  | 	if (new_argc == 0) { | ||||||
|  | 		res = env_expand(name); | ||||||
|  | 		if (res) | ||||||
|  | 			goto free; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	res = xstrdup(""); | ||||||
|  | free: | ||||||
|  | 	for (i = 0; i < new_argc; i++) | ||||||
|  | 		free(new_argv[i]); | ||||||
|  | 	free(name); | ||||||
|  | free_tmp: | ||||||
|  | 	free(tmp); | ||||||
|  |  | ||||||
|  | 	return res; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Expand a string that follows '$' | ||||||
|  |  * | ||||||
|  |  * For example, if the input string is | ||||||
|  |  *     ($(FOO)$($(BAR)))$(BAZ) | ||||||
|  |  * this helper evaluates | ||||||
|  |  *     $($(FOO)$($(BAR))) | ||||||
|  |  * and returns a new string containing the expansion (note that the string is | ||||||
|  |  * recursively expanded), also advancing 'str' to point to the next character | ||||||
|  |  * after the corresponding closing parenthesis, in this case, *str will be | ||||||
|  |  *     $(BAR) | ||||||
|  |  */ | ||||||
|  | static char *expand_dollar_with_args(const char **str, int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	const char *p = *str; | ||||||
|  | 	const char *q; | ||||||
|  | 	int nest = 0; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * In Kconfig, variable/function references always start with "$(". | ||||||
|  | 	 * Neither single-letter variables as in $A nor curly braces as in ${CC} | ||||||
|  | 	 * are supported.  '$' not followed by '(' loses its special meaning. | ||||||
|  | 	 */ | ||||||
|  | 	if (*p != '(') { | ||||||
|  | 		*str = p; | ||||||
|  | 		return xstrdup("$"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	p++; | ||||||
|  | 	q = p; | ||||||
|  | 	while (*q) { | ||||||
|  | 		if (*q == '(') { | ||||||
|  | 			nest++; | ||||||
|  | 		} else if (*q == ')') { | ||||||
|  | 			if (nest-- == 0) | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 		q++; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!*q) | ||||||
|  | 		pperror("unterminated reference to '%s': missing ')'", p); | ||||||
|  |  | ||||||
|  | 	/* Advance 'str' to after the expanded initial portion of the string */ | ||||||
|  | 	*str = q + 1; | ||||||
|  |  | ||||||
|  | 	return eval_clause(p, q - p, argc, argv); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *expand_dollar(const char **str) | ||||||
|  | { | ||||||
|  | 	return expand_dollar_with_args(str, 0, NULL); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *__expand_string(const char **str, bool (*is_end)(char c), | ||||||
|  | 			     int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	const char *in, *p; | ||||||
|  | 	char *expansion, *out; | ||||||
|  | 	size_t in_len, out_len; | ||||||
|  |  | ||||||
|  | 	out = xmalloc(1); | ||||||
|  | 	*out = 0; | ||||||
|  | 	out_len = 1; | ||||||
|  |  | ||||||
|  | 	p = in = *str; | ||||||
|  |  | ||||||
|  | 	while (1) { | ||||||
|  | 		if (*p == '$') { | ||||||
|  | 			in_len = p - in; | ||||||
|  | 			p++; | ||||||
|  | 			expansion = expand_dollar_with_args(&p, argc, argv); | ||||||
|  | 			out_len += in_len + strlen(expansion); | ||||||
|  | 			out = xrealloc(out, out_len); | ||||||
|  | 			strncat(out, in, in_len); | ||||||
|  | 			strcat(out, expansion); | ||||||
|  | 			free(expansion); | ||||||
|  | 			in = p; | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (is_end(*p)) | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 		p++; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	in_len = p - in; | ||||||
|  | 	out_len += in_len; | ||||||
|  | 	out = xrealloc(out, out_len); | ||||||
|  | 	strncat(out, in, in_len); | ||||||
|  |  | ||||||
|  | 	/* Advance 'str' to the end character */ | ||||||
|  | 	*str = p; | ||||||
|  |  | ||||||
|  | 	return out; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static bool is_end_of_str(char c) | ||||||
|  | { | ||||||
|  | 	return !c; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Expand variables and functions in the given string.  Undefined variables | ||||||
|  |  * expand to an empty string. | ||||||
|  |  * The returned string must be freed when done. | ||||||
|  |  */ | ||||||
|  | static char *expand_string_with_args(const char *in, int argc, char *argv[]) | ||||||
|  | { | ||||||
|  | 	return __expand_string(&in, is_end_of_str, argc, argv); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *expand_string(const char *in) | ||||||
|  | { | ||||||
|  | 	return expand_string_with_args(in, 0, NULL); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static bool is_end_of_token(char c) | ||||||
|  | { | ||||||
|  | 	/* Why are '.' and '/' valid characters for symbols? */ | ||||||
|  | 	return !(isalnum(c) || c == '_' || c == '-' || c == '.' || c == '/'); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Expand variables in a token.  The parsing stops when a token separater | ||||||
|  |  * (in most cases, it is a whitespace) is encountered.  'str' is updated to | ||||||
|  |  * point to the next character. | ||||||
|  |  * | ||||||
|  |  * The returned string must be freed when done. | ||||||
|  |  */ | ||||||
|  | char *expand_one_token(const char **str) | ||||||
|  | { | ||||||
|  | 	return __expand_string(str, is_end_of_token, 0, NULL); | ||||||
|  | } | ||||||
							
								
								
									
										32
									
								
								scripts/config/qconf-cfg.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										32
									
								
								scripts/config/qconf-cfg.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | #!/bin/sh | ||||||
|  | # SPDX-License-Identifier: GPL-2.0 | ||||||
|  |  | ||||||
|  | PKG="Qt5Core Qt5Gui Qt5Widgets" | ||||||
|  | PKG2="QtCore QtGui" | ||||||
|  |  | ||||||
|  | if [ -z "$(command -v pkg-config)" ]; then | ||||||
|  | 	echo >&2 "*" | ||||||
|  | 	echo >&2 "* 'make xconfig' requires 'pkg-config'. Please install it." | ||||||
|  | 	echo >&2 "*" | ||||||
|  | 	exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | if pkg-config --exists $PKG; then | ||||||
|  | 	echo cflags=\"-std=c++11 -fPIC $(pkg-config --cflags Qt5Core Qt5Gui Qt5Widgets)\" | ||||||
|  | 	echo libs=\"$(pkg-config --libs $PKG)\" | ||||||
|  | 	echo moc=\"$(pkg-config --variable=host_bins Qt5Core)/moc\" | ||||||
|  | 	exit 0 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | if pkg-config --exists $PKG2; then | ||||||
|  | 	echo cflags=\"$(pkg-config --cflags $PKG2)\" | ||||||
|  | 	echo libs=\"$(pkg-config --libs $PKG2)\" | ||||||
|  | 	echo moc=\"$(pkg-config --variable=moc_location QtCore)\" | ||||||
|  | 	exit 0 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | echo >&2 "*" | ||||||
|  | echo >&2 "* Could not find Qt via pkg-config." | ||||||
|  | echo >&2 "* Please install either Qt 4.8 or 5.x. and make sure it's in PKG_CONFIG_PATH" | ||||||
|  | echo >&2 "*" | ||||||
|  | exit 1 | ||||||
| @@ -1,7 +1,7 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0 | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  * Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com> |  * Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com> | ||||||
|  * Released under the terms of the GNU GPL v2.0. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <qglobal.h> | #include <qglobal.h> | ||||||
| @@ -32,12 +32,8 @@ | |||||||
| #include "qconf.h" | #include "qconf.h" | ||||||
|  |  | ||||||
| #include "qconf.moc" | #include "qconf.moc" | ||||||
| #include "images.c" | #include "images.h" | ||||||
|  |  | ||||||
| #ifdef _ |  | ||||||
| # undef _ |  | ||||||
| # define _ qgettext |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| static QApplication *configApp; | static QApplication *configApp; | ||||||
| static ConfigSettings *configSettings; | static ConfigSettings *configSettings; | ||||||
| @@ -46,12 +42,7 @@ QAction *ConfigMainWindow::saveAction; | |||||||
|  |  | ||||||
| static inline QString qgettext(const char* str) | static inline QString qgettext(const char* str) | ||||||
| { | { | ||||||
| 	return QString::fromLocal8Bit(gettext(str)); | 	return QString::fromLocal8Bit(str); | ||||||
| } |  | ||||||
|  |  | ||||||
| static inline QString qgettext(const QString& str) |  | ||||||
| { |  | ||||||
| 	return QString::fromLocal8Bit(gettext(str.toLatin1())); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| ConfigSettings::ConfigSettings() | ConfigSettings::ConfigSettings() | ||||||
| @@ -65,12 +56,20 @@ ConfigSettings::ConfigSettings() | |||||||
| QList<int> ConfigSettings::readSizes(const QString& key, bool *ok) | QList<int> ConfigSettings::readSizes(const QString& key, bool *ok) | ||||||
| { | { | ||||||
| 	QList<int> result; | 	QList<int> result; | ||||||
|  |  | ||||||
|  | 	if (contains(key)) | ||||||
|  | 	{ | ||||||
| 		QStringList entryList = value(key).toStringList(); | 		QStringList entryList = value(key).toStringList(); | ||||||
| 		QStringList::Iterator it; | 		QStringList::Iterator it; | ||||||
|  |  | ||||||
| 		for (it = entryList.begin(); it != entryList.end(); ++it) | 		for (it = entryList.begin(); it != entryList.end(); ++it) | ||||||
| 			result.push_back((*it).toInt()); | 			result.push_back((*it).toInt()); | ||||||
|  |  | ||||||
|  | 		*ok = true; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 		*ok = false; | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -119,7 +118,7 @@ void ConfigItem::updateMenu(void) | |||||||
|  |  | ||||||
| 	sym = menu->sym; | 	sym = menu->sym; | ||||||
| 	prop = menu->prompt; | 	prop = menu->prompt; | ||||||
| 	prompt = _(menu_get_prompt(menu)); | 	prompt = qgettext(menu_get_prompt(menu)); | ||||||
|  |  | ||||||
| 	if (prop) switch (prop->type) { | 	if (prop) switch (prop->type) { | ||||||
| 	case P_MENU: | 	case P_MENU: | ||||||
| @@ -153,7 +152,7 @@ void ConfigItem::updateMenu(void) | |||||||
| 	case S_TRISTATE: | 	case S_TRISTATE: | ||||||
| 		char ch; | 		char ch; | ||||||
|  |  | ||||||
| 		if (!sym_is_changable(sym) && list->optMode == normalOpt) { | 		if (!sym_is_changeable(sym) && list->optMode == normalOpt) { | ||||||
| 			setPixmap(promptColIdx, QIcon()); | 			setPixmap(promptColIdx, QIcon()); | ||||||
| 			setText(noColIdx, QString::null); | 			setText(noColIdx, QString::null); | ||||||
| 			setText(modColIdx, QString::null); | 			setText(modColIdx, QString::null); | ||||||
| @@ -208,7 +207,7 @@ void ConfigItem::updateMenu(void) | |||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	if (!sym_has_value(sym) && visible) | 	if (!sym_has_value(sym) && visible) | ||||||
| 		prompt += _(" (NEW)"); | 		prompt += " (NEW)"; | ||||||
| set_prompt: | set_prompt: | ||||||
| 	setText(promptColIdx, prompt); | 	setText(promptColIdx, prompt); | ||||||
| } | } | ||||||
| @@ -319,7 +318,7 @@ ConfigList::ConfigList(ConfigView* p, const char *name) | |||||||
| 	setVerticalScrollMode(ScrollPerPixel); | 	setVerticalScrollMode(ScrollPerPixel); | ||||||
| 	setHorizontalScrollMode(ScrollPerPixel); | 	setHorizontalScrollMode(ScrollPerPixel); | ||||||
|  |  | ||||||
| 	setHeaderLabels(QStringList() << _("Option") << _("Name") << "N" << "M" << "Y" << _("Value")); | 	setHeaderLabels(QStringList() << "Option" << "Name" << "N" << "M" << "Y" << "Value"); | ||||||
|  |  | ||||||
| 	connect(this, SIGNAL(itemSelectionChanged(void)), | 	connect(this, SIGNAL(itemSelectionChanged(void)), | ||||||
| 		SLOT(updateSelection(void))); | 		SLOT(updateSelection(void))); | ||||||
| @@ -875,7 +874,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e) | |||||||
| 			QAction *action; | 			QAction *action; | ||||||
|  |  | ||||||
| 			headerPopup = new QMenu(this); | 			headerPopup = new QMenu(this); | ||||||
| 			action = new QAction(_("Show Name"), this); | 			action = new QAction("Show Name", this); | ||||||
| 			  action->setCheckable(true); | 			  action->setCheckable(true); | ||||||
| 			  connect(action, SIGNAL(toggled(bool)), | 			  connect(action, SIGNAL(toggled(bool)), | ||||||
| 				  parent(), SLOT(setShowName(bool))); | 				  parent(), SLOT(setShowName(bool))); | ||||||
| @@ -883,7 +882,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e) | |||||||
| 				  action, SLOT(setOn(bool))); | 				  action, SLOT(setOn(bool))); | ||||||
| 			  action->setChecked(showName); | 			  action->setChecked(showName); | ||||||
| 			  headerPopup->addAction(action); | 			  headerPopup->addAction(action); | ||||||
| 			action = new QAction(_("Show Range"), this); | 			action = new QAction("Show Range", this); | ||||||
| 			  action->setCheckable(true); | 			  action->setCheckable(true); | ||||||
| 			  connect(action, SIGNAL(toggled(bool)), | 			  connect(action, SIGNAL(toggled(bool)), | ||||||
| 				  parent(), SLOT(setShowRange(bool))); | 				  parent(), SLOT(setShowRange(bool))); | ||||||
| @@ -891,7 +890,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e) | |||||||
| 				  action, SLOT(setOn(bool))); | 				  action, SLOT(setOn(bool))); | ||||||
| 			  action->setChecked(showRange); | 			  action->setChecked(showRange); | ||||||
| 			  headerPopup->addAction(action); | 			  headerPopup->addAction(action); | ||||||
| 			action = new QAction(_("Show Data"), this); | 			action = new QAction("Show Data", this); | ||||||
| 			  action->setCheckable(true); | 			  action->setCheckable(true); | ||||||
| 			  connect(action, SIGNAL(toggled(bool)), | 			  connect(action, SIGNAL(toggled(bool)), | ||||||
| 				  parent(), SLOT(setShowData(bool))); | 				  parent(), SLOT(setShowData(bool))); | ||||||
| @@ -1014,7 +1013,7 @@ ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name) | |||||||
|  |  | ||||||
| 	if (!objectName().isEmpty()) { | 	if (!objectName().isEmpty()) { | ||||||
| 		configSettings->beginGroup(objectName()); | 		configSettings->beginGroup(objectName()); | ||||||
| 		_showDebug = configSettings->value("/showDebug", false).toBool(); | 		setShowDebug(configSettings->value("/showDebug", false).toBool()); | ||||||
| 		configSettings->endGroup(); | 		configSettings->endGroup(); | ||||||
| 		connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); | 		connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); | ||||||
| 	} | 	} | ||||||
| @@ -1078,7 +1077,7 @@ void ConfigInfoView::menuInfo(void) | |||||||
| 	if (sym) { | 	if (sym) { | ||||||
| 		if (_menu->prompt) { | 		if (_menu->prompt) { | ||||||
| 			head += "<big><b>"; | 			head += "<big><b>"; | ||||||
| 			head += print_filter(_(_menu->prompt->text)); | 			head += print_filter(_menu->prompt->text); | ||||||
| 			head += "</b></big>"; | 			head += "</b></big>"; | ||||||
| 			if (sym->name) { | 			if (sym->name) { | ||||||
| 				head += " ("; | 				head += " ("; | ||||||
| @@ -1109,7 +1108,7 @@ void ConfigInfoView::menuInfo(void) | |||||||
| 		str_free(&help_gstr); | 		str_free(&help_gstr); | ||||||
| 	} else if (_menu->prompt) { | 	} else if (_menu->prompt) { | ||||||
| 		head += "<big><b>"; | 		head += "<big><b>"; | ||||||
| 		head += print_filter(_(_menu->prompt->text)); | 		head += print_filter(_menu->prompt->text); | ||||||
| 		head += "</b></big><br><br>"; | 		head += "</b></big><br><br>"; | ||||||
| 		if (showDebug()) { | 		if (showDebug()) { | ||||||
| 			if (_menu->prompt->visible.expr) { | 			if (_menu->prompt->visible.expr) { | ||||||
| @@ -1144,13 +1143,12 @@ QString ConfigInfoView::debug_info(struct symbol *sym) | |||||||
| 		case P_PROMPT: | 		case P_PROMPT: | ||||||
| 		case P_MENU: | 		case P_MENU: | ||||||
| 			debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu); | 			debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu); | ||||||
| 			debug += print_filter(_(prop->text)); | 			debug += print_filter(prop->text); | ||||||
| 			debug += "</a><br>"; | 			debug += "</a><br>"; | ||||||
| 			break; | 			break; | ||||||
| 		case P_DEFAULT: | 		case P_DEFAULT: | ||||||
| 		case P_SELECT: | 		case P_SELECT: | ||||||
| 		case P_RANGE: | 		case P_RANGE: | ||||||
| 		case P_ENV: |  | ||||||
| 			debug += prop_get_type_name(prop->type); | 			debug += prop_get_type_name(prop->type); | ||||||
| 			debug += ": "; | 			debug += ": "; | ||||||
| 			expr_print(prop->expr, expr_print_help, &debug, E_NONE); | 			expr_print(prop->expr, expr_print_help, &debug, E_NONE); | ||||||
| @@ -1226,7 +1224,7 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char | |||||||
| QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos) | QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos) | ||||||
| { | { | ||||||
| 	QMenu* popup = Parent::createStandardContextMenu(pos); | 	QMenu* popup = Parent::createStandardContextMenu(pos); | ||||||
| 	QAction* action = new QAction(_("Show Debug Info"), popup); | 	QAction* action = new QAction("Show Debug Info", popup); | ||||||
| 	  action->setCheckable(true); | 	  action->setCheckable(true); | ||||||
| 	  connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); | 	  connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); | ||||||
| 	  connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool))); | 	  connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool))); | ||||||
| @@ -1253,11 +1251,11 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *nam | |||||||
| 	QHBoxLayout* layout2 = new QHBoxLayout(0); | 	QHBoxLayout* layout2 = new QHBoxLayout(0); | ||||||
| 	layout2->setContentsMargins(0, 0, 0, 0); | 	layout2->setContentsMargins(0, 0, 0, 0); | ||||||
| 	layout2->setSpacing(6); | 	layout2->setSpacing(6); | ||||||
| 	layout2->addWidget(new QLabel(_("Find:"), this)); | 	layout2->addWidget(new QLabel("Find:", this)); | ||||||
| 	editField = new QLineEdit(this); | 	editField = new QLineEdit(this); | ||||||
| 	connect(editField, SIGNAL(returnPressed()), SLOT(search())); | 	connect(editField, SIGNAL(returnPressed()), SLOT(search())); | ||||||
| 	layout2->addWidget(editField); | 	layout2->addWidget(editField); | ||||||
| 	searchButton = new QPushButton(_("Search"), this); | 	searchButton = new QPushButton("Search", this); | ||||||
| 	searchButton->setAutoDefault(false); | 	searchButton->setAutoDefault(false); | ||||||
| 	connect(searchButton, SIGNAL(clicked()), SLOT(search())); | 	connect(searchButton, SIGNAL(clicked()), SLOT(search())); | ||||||
| 	layout2->addWidget(searchButton); | 	layout2->addWidget(searchButton); | ||||||
| @@ -1379,44 +1377,46 @@ ConfigMainWindow::ConfigMainWindow(void) | |||||||
| 	toolBar = new QToolBar("Tools", this); | 	toolBar = new QToolBar("Tools", this); | ||||||
| 	addToolBar(toolBar); | 	addToolBar(toolBar); | ||||||
|  |  | ||||||
| 	backAction = new QAction(QPixmap(xpm_back), _("Back"), this); | 	backAction = new QAction(QPixmap(xpm_back), "Back", this); | ||||||
| 	  connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack())); | 	  connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack())); | ||||||
| 	  backAction->setEnabled(false); | 	  backAction->setEnabled(false); | ||||||
| 	QAction *quitAction = new QAction(_("&Quit"), this); | 	QAction *quitAction = new QAction("&Quit", this); | ||||||
| 	quitAction->setShortcut(Qt::CTRL + Qt::Key_Q); | 	quitAction->setShortcut(Qt::CTRL + Qt::Key_Q); | ||||||
| 	  connect(quitAction, SIGNAL(triggered(bool)), SLOT(close())); | 	  connect(quitAction, SIGNAL(triggered(bool)), SLOT(close())); | ||||||
| 	QAction *loadAction = new QAction(QPixmap(xpm_load), _("&Load"), this); | 	QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this); | ||||||
| 	loadAction->setShortcut(Qt::CTRL + Qt::Key_L); | 	loadAction->setShortcut(Qt::CTRL + Qt::Key_L); | ||||||
| 	  connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig())); | 	  connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig())); | ||||||
| 	saveAction = new QAction(QPixmap(xpm_save), _("&Save"), this); | 	saveAction = new QAction(QPixmap(xpm_save), "&Save", this); | ||||||
| 	saveAction->setShortcut(Qt::CTRL + Qt::Key_S); | 	saveAction->setShortcut(Qt::CTRL + Qt::Key_S); | ||||||
| 	  connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig())); | 	  connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig())); | ||||||
| 	conf_set_changed_callback(conf_changed); | 	conf_set_changed_callback(conf_changed); | ||||||
| 	// Set saveAction's initial state | 	// Set saveAction's initial state | ||||||
| 	conf_changed(); | 	conf_changed(); | ||||||
| 	QAction *saveAsAction = new QAction(_("Save &As..."), this); | 	configname = xstrdup(conf_get_configname()); | ||||||
|  |  | ||||||
|  | 	QAction *saveAsAction = new QAction("Save &As...", this); | ||||||
| 	  connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs())); | 	  connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs())); | ||||||
| 	QAction *searchAction = new QAction(_("&Find"), this); | 	QAction *searchAction = new QAction("&Find", this); | ||||||
| 	searchAction->setShortcut(Qt::CTRL + Qt::Key_F); | 	searchAction->setShortcut(Qt::CTRL + Qt::Key_F); | ||||||
| 	  connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig())); | 	  connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig())); | ||||||
| 	singleViewAction = new QAction(QPixmap(xpm_single_view), _("Single View"), this); | 	singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this); | ||||||
| 	singleViewAction->setCheckable(true); | 	singleViewAction->setCheckable(true); | ||||||
| 	  connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView())); | 	  connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView())); | ||||||
| 	splitViewAction = new QAction(QPixmap(xpm_split_view), _("Split View"), this); | 	splitViewAction = new QAction(QPixmap(xpm_split_view), "Split View", this); | ||||||
| 	splitViewAction->setCheckable(true); | 	splitViewAction->setCheckable(true); | ||||||
| 	  connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView())); | 	  connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView())); | ||||||
| 	fullViewAction = new QAction(QPixmap(xpm_tree_view), _("Full View"), this); | 	fullViewAction = new QAction(QPixmap(xpm_tree_view), "Full View", this); | ||||||
| 	fullViewAction->setCheckable(true); | 	fullViewAction->setCheckable(true); | ||||||
| 	  connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView())); | 	  connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView())); | ||||||
|  |  | ||||||
| 	QAction *showNameAction = new QAction(_("Show Name"), this); | 	QAction *showNameAction = new QAction("Show Name", this); | ||||||
| 	  showNameAction->setCheckable(true); | 	  showNameAction->setCheckable(true); | ||||||
| 	  connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); | 	  connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); | ||||||
| 	  showNameAction->setChecked(configView->showName()); | 	  showNameAction->setChecked(configView->showName()); | ||||||
| 	QAction *showRangeAction = new QAction(_("Show Range"), this); | 	QAction *showRangeAction = new QAction("Show Range", this); | ||||||
| 	  showRangeAction->setCheckable(true); | 	  showRangeAction->setCheckable(true); | ||||||
| 	  connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); | 	  connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); | ||||||
| 	QAction *showDataAction = new QAction(_("Show Data"), this); | 	QAction *showDataAction = new QAction("Show Data", this); | ||||||
| 	  showDataAction->setCheckable(true); | 	  showDataAction->setCheckable(true); | ||||||
| 	  connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); | 	  connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); | ||||||
|  |  | ||||||
| @@ -1427,21 +1427,21 @@ ConfigMainWindow::ConfigMainWindow(void) | |||||||
| 	connect(optGroup, SIGNAL(triggered(QAction *)), menuView, | 	connect(optGroup, SIGNAL(triggered(QAction *)), menuView, | ||||||
| 		SLOT(setOptionMode(QAction *))); | 		SLOT(setOptionMode(QAction *))); | ||||||
|  |  | ||||||
| 	configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup); | 	configView->showNormalAction = new QAction("Show Normal Options", optGroup); | ||||||
| 	configView->showAllAction = new QAction(_("Show All Options"), optGroup); | 	configView->showAllAction = new QAction("Show All Options", optGroup); | ||||||
| 	configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup); | 	configView->showPromptAction = new QAction("Show Prompt Options", optGroup); | ||||||
| 	configView->showNormalAction->setCheckable(true); | 	configView->showNormalAction->setCheckable(true); | ||||||
| 	configView->showAllAction->setCheckable(true); | 	configView->showAllAction->setCheckable(true); | ||||||
| 	configView->showPromptAction->setCheckable(true); | 	configView->showPromptAction->setCheckable(true); | ||||||
|  |  | ||||||
| 	QAction *showDebugAction = new QAction( _("Show Debug Info"), this); | 	QAction *showDebugAction = new QAction("Show Debug Info", this); | ||||||
| 	  showDebugAction->setCheckable(true); | 	  showDebugAction->setCheckable(true); | ||||||
| 	  connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); | 	  connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); | ||||||
| 	  showDebugAction->setChecked(helpText->showDebug()); | 	  showDebugAction->setChecked(helpText->showDebug()); | ||||||
|  |  | ||||||
| 	QAction *showIntroAction = new QAction( _("Introduction"), this); | 	QAction *showIntroAction = new QAction("Introduction", this); | ||||||
| 	  connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro())); | 	  connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro())); | ||||||
| 	QAction *showAboutAction = new QAction( _("About"), this); | 	QAction *showAboutAction = new QAction("About", this); | ||||||
| 	  connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout())); | 	  connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout())); | ||||||
|  |  | ||||||
| 	// init tool bar | 	// init tool bar | ||||||
| @@ -1455,7 +1455,7 @@ ConfigMainWindow::ConfigMainWindow(void) | |||||||
| 	toolBar->addAction(fullViewAction); | 	toolBar->addAction(fullViewAction); | ||||||
|  |  | ||||||
| 	// create config menu | 	// create config menu | ||||||
| 	QMenu* config = menu->addMenu(_("&File")); | 	QMenu* config = menu->addMenu("&File"); | ||||||
| 	config->addAction(loadAction); | 	config->addAction(loadAction); | ||||||
| 	config->addAction(saveAction); | 	config->addAction(saveAction); | ||||||
| 	config->addAction(saveAsAction); | 	config->addAction(saveAsAction); | ||||||
| @@ -1463,21 +1463,22 @@ ConfigMainWindow::ConfigMainWindow(void) | |||||||
| 	config->addAction(quitAction); | 	config->addAction(quitAction); | ||||||
|  |  | ||||||
| 	// create edit menu | 	// create edit menu | ||||||
| 	QMenu* editMenu = menu->addMenu(_("&Edit")); | 	QMenu* editMenu = menu->addMenu("&Edit"); | ||||||
| 	editMenu->addAction(searchAction); | 	editMenu->addAction(searchAction); | ||||||
|  |  | ||||||
| 	// create options menu | 	// create options menu | ||||||
| 	QMenu* optionMenu = menu->addMenu(_("&Option")); | 	QMenu* optionMenu = menu->addMenu("&Option"); | ||||||
| 	optionMenu->addAction(showNameAction); | 	optionMenu->addAction(showNameAction); | ||||||
| 	optionMenu->addAction(showRangeAction); | 	optionMenu->addAction(showRangeAction); | ||||||
| 	optionMenu->addAction(showDataAction); | 	optionMenu->addAction(showDataAction); | ||||||
| 	optionMenu->addSeparator(); | 	optionMenu->addSeparator(); | ||||||
| 	optionMenu->addActions(optGroup->actions()); | 	optionMenu->addActions(optGroup->actions()); | ||||||
| 	optionMenu->addSeparator(); | 	optionMenu->addSeparator(); | ||||||
|  | 	optionMenu->addAction(showDebugAction); | ||||||
|  |  | ||||||
| 	// create help menu | 	// create help menu | ||||||
| 	menu->addSeparator(); | 	menu->addSeparator(); | ||||||
| 	QMenu* helpMenu = menu->addMenu(_("&Help")); | 	QMenu* helpMenu = menu->addMenu("&Help"); | ||||||
| 	helpMenu->addAction(showIntroAction); | 	helpMenu->addAction(showIntroAction); | ||||||
| 	helpMenu->addAction(showAboutAction); | 	helpMenu->addAction(showAboutAction); | ||||||
|  |  | ||||||
| @@ -1521,29 +1522,57 @@ ConfigMainWindow::ConfigMainWindow(void) | |||||||
|  |  | ||||||
| void ConfigMainWindow::loadConfig(void) | void ConfigMainWindow::loadConfig(void) | ||||||
| { | { | ||||||
| 	QString s = QFileDialog::getOpenFileName(this, "", conf_get_configname()); | 	QString str; | ||||||
| 	if (s.isNull()) | 	QByteArray ba; | ||||||
|  | 	const char *name; | ||||||
|  |  | ||||||
|  | 	str = QFileDialog::getOpenFileName(this, "", configname); | ||||||
|  | 	if (str.isNull()) | ||||||
| 		return; | 		return; | ||||||
| 	if (conf_read(QFile::encodeName(s))) |  | ||||||
| 		QMessageBox::information(this, "qconf", _("Unable to load configuration!")); | 	ba = str.toLocal8Bit(); | ||||||
|  | 	name = ba.data(); | ||||||
|  |  | ||||||
|  | 	if (conf_read(name)) | ||||||
|  | 		QMessageBox::information(this, "qconf", "Unable to load configuration!"); | ||||||
|  |  | ||||||
|  | 	free(configname); | ||||||
|  | 	configname = xstrdup(name); | ||||||
|  |  | ||||||
| 	ConfigView::updateListAll(); | 	ConfigView::updateListAll(); | ||||||
| } | } | ||||||
|  |  | ||||||
| bool ConfigMainWindow::saveConfig(void) | bool ConfigMainWindow::saveConfig(void) | ||||||
| { | { | ||||||
| 	if (conf_write(NULL)) { | 	if (conf_write(configname)) { | ||||||
| 		QMessageBox::information(this, "qconf", _("Unable to save configuration!")); | 		QMessageBox::information(this, "qconf", "Unable to save configuration!"); | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  | 	conf_write_autoconf(0); | ||||||
|  |  | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void ConfigMainWindow::saveConfigAs(void) | void ConfigMainWindow::saveConfigAs(void) | ||||||
| { | { | ||||||
| 	QString s = QFileDialog::getSaveFileName(this, "", conf_get_configname()); | 	QString str; | ||||||
| 	if (s.isNull()) | 	QByteArray ba; | ||||||
|  | 	const char *name; | ||||||
|  |  | ||||||
|  | 	str = QFileDialog::getSaveFileName(this, "", configname); | ||||||
|  | 	if (str.isNull()) | ||||||
| 		return; | 		return; | ||||||
| 	saveConfig(); |  | ||||||
|  | 	ba = str.toLocal8Bit(); | ||||||
|  | 	name = ba.data(); | ||||||
|  |  | ||||||
|  | 	if (conf_write(name)) { | ||||||
|  | 		QMessageBox::information(this, "qconf", "Unable to save configuration!"); | ||||||
|  | 	} | ||||||
|  | 	conf_write_autoconf(0); | ||||||
|  |  | ||||||
|  | 	free(configname); | ||||||
|  | 	configname = xstrdup(name); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ConfigMainWindow::searchConfig(void) | void ConfigMainWindow::searchConfig(void) | ||||||
| @@ -1714,11 +1743,11 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e) | |||||||
| 		e->accept(); | 		e->accept(); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning, | 	QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning, | ||||||
| 			QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); | 			QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); | ||||||
| 	mb.setButtonText(QMessageBox::Yes, _("&Save Changes")); | 	mb.setButtonText(QMessageBox::Yes, "&Save Changes"); | ||||||
| 	mb.setButtonText(QMessageBox::No, _("&Discard Changes")); | 	mb.setButtonText(QMessageBox::No, "&Discard Changes"); | ||||||
| 	mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit")); | 	mb.setButtonText(QMessageBox::Cancel, "Cancel Exit"); | ||||||
| 	switch (mb.exec()) { | 	switch (mb.exec()) { | ||||||
| 	case QMessageBox::Yes: | 	case QMessageBox::Yes: | ||||||
| 		if (saveConfig()) | 		if (saveConfig()) | ||||||
| @@ -1737,7 +1766,7 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e) | |||||||
|  |  | ||||||
| void ConfigMainWindow::showIntro(void) | void ConfigMainWindow::showIntro(void) | ||||||
| { | { | ||||||
| 	static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n" | 	static const QString str = "Welcome to the qconf graphical configuration tool.\n\n" | ||||||
| 		"For each option, a blank box indicates the feature is disabled, a check\n" | 		"For each option, a blank box indicates the feature is disabled, a check\n" | ||||||
| 		"indicates it is enabled, and a dot indicates that it is to be compiled\n" | 		"indicates it is enabled, and a dot indicates that it is to be compiled\n" | ||||||
| 		"as a module.  Clicking on the box will cycle through the three states.\n\n" | 		"as a module.  Clicking on the box will cycle through the three states.\n\n" | ||||||
| @@ -1747,16 +1776,16 @@ void ConfigMainWindow::showIntro(void) | |||||||
| 		"options must be enabled to support the option you are interested in, you can\n" | 		"options must be enabled to support the option you are interested in, you can\n" | ||||||
| 		"still view the help of a grayed-out option.\n\n" | 		"still view the help of a grayed-out option.\n\n" | ||||||
| 		"Toggling Show Debug Info under the Options menu will show the dependencies,\n" | 		"Toggling Show Debug Info under the Options menu will show the dependencies,\n" | ||||||
| 		"which you can then match by examining other options.\n\n"); | 		"which you can then match by examining other options.\n\n"; | ||||||
|  |  | ||||||
| 	QMessageBox::information(this, "qconf", str); | 	QMessageBox::information(this, "qconf", str); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ConfigMainWindow::showAbout(void) | void ConfigMainWindow::showAbout(void) | ||||||
| { | { | ||||||
| 	static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n" | 	static const QString str = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n" | ||||||
| 		"Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n" | 		"Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n" | ||||||
| 		"Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"); | 		"Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"; | ||||||
|  |  | ||||||
| 	QMessageBox::information(this, "qconf", str); | 	QMessageBox::information(this, "qconf", str); | ||||||
| } | } | ||||||
| @@ -1817,7 +1846,7 @@ static const char *progname; | |||||||
|  |  | ||||||
| static void usage(void) | static void usage(void) | ||||||
| { | { | ||||||
| 	printf(_("%s [-s] <config>\n").toLatin1().constData(), progname); | 	printf("%s [-s] <config>\n", progname); | ||||||
| 	exit(0); | 	exit(0); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1826,9 +1855,6 @@ int main(int ac, char** av) | |||||||
| 	ConfigMainWindow* v; | 	ConfigMainWindow* v; | ||||||
| 	const char *name; | 	const char *name; | ||||||
|  |  | ||||||
| 	bindtextdomain(PACKAGE, LOCALEDIR); |  | ||||||
| 	textdomain(PACKAGE); |  | ||||||
|  |  | ||||||
| 	progname = av[0]; | 	progname = av[0]; | ||||||
| 	configApp = new QApplication(ac, av); | 	configApp = new QApplication(ac, av); | ||||||
| 	if (ac > 1 && av[1][0] == '-') { | 	if (ac > 1 && av[1][0] == '-') { | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
|  | /* SPDX-License-Identifier: GPL-2.0 */ | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  * Released under the terms of the GNU GPL v2.0. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <QTextBrowser> | #include <QTextBrowser> | ||||||
| @@ -291,6 +291,7 @@ protected: | |||||||
| class ConfigMainWindow : public QMainWindow { | class ConfigMainWindow : public QMainWindow { | ||||||
| 	Q_OBJECT | 	Q_OBJECT | ||||||
|  |  | ||||||
|  | 	char *configname; | ||||||
| 	static QAction *saveAction; | 	static QAction *saveAction; | ||||||
| 	static void conf_changed(void); | 	static void conf_changed(void); | ||||||
| public: | public: | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0 | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  * Released under the terms of the GNU GPL v2.0. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
| @@ -33,33 +33,6 @@ struct symbol *sym_defconfig_list; | |||||||
| struct symbol *modules_sym; | struct symbol *modules_sym; | ||||||
| tristate modules_val; | tristate modules_val; | ||||||
|  |  | ||||||
| struct expr *sym_env_list; |  | ||||||
|  |  | ||||||
| static void sym_add_default(struct symbol *sym, const char *def) |  | ||||||
| { |  | ||||||
| 	struct property *prop = prop_alloc(P_DEFAULT, sym); |  | ||||||
|  |  | ||||||
| 	prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void sym_init(void) |  | ||||||
| { |  | ||||||
| 	struct symbol *sym; |  | ||||||
| 	struct utsname uts; |  | ||||||
| 	static bool inited = false; |  | ||||||
|  |  | ||||||
| 	if (inited) |  | ||||||
| 		return; |  | ||||||
| 	inited = true; |  | ||||||
|  |  | ||||||
| 	uname(&uts); |  | ||||||
|  |  | ||||||
| 	sym = sym_lookup("UNAME_RELEASE", 0); |  | ||||||
| 	sym->type = S_STRING; |  | ||||||
| 	sym->flags |= SYMBOL_AUTO; |  | ||||||
| 	sym_add_default(sym, uts.release); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| enum symbol_type sym_get_type(struct symbol *sym) | enum symbol_type sym_get_type(struct symbol *sym) | ||||||
| { | { | ||||||
| 	enum symbol_type type = sym->type; | 	enum symbol_type type = sym->type; | ||||||
| @@ -77,7 +50,7 @@ const char *sym_type_name(enum symbol_type type) | |||||||
| { | { | ||||||
| 	switch (type) { | 	switch (type) { | ||||||
| 	case S_BOOLEAN: | 	case S_BOOLEAN: | ||||||
| 		return "boolean"; | 		return "bool"; | ||||||
| 	case S_TRISTATE: | 	case S_TRISTATE: | ||||||
| 		return "tristate"; | 		return "tristate"; | ||||||
| 	case S_INT: | 	case S_INT: | ||||||
| @@ -88,8 +61,6 @@ const char *sym_type_name(enum symbol_type type) | |||||||
| 		return "string"; | 		return "string"; | ||||||
| 	case S_UNKNOWN: | 	case S_UNKNOWN: | ||||||
| 		return "unknown"; | 		return "unknown"; | ||||||
| 	case S_OTHER: |  | ||||||
| 		break; |  | ||||||
| 	} | 	} | ||||||
| 	return "???"; | 	return "???"; | ||||||
| } | } | ||||||
| @@ -103,15 +74,6 @@ struct property *sym_get_choice_prop(struct symbol *sym) | |||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| struct property *sym_get_env_prop(struct symbol *sym) |  | ||||||
| { |  | ||||||
| 	struct property *prop; |  | ||||||
|  |  | ||||||
| 	for_all_properties(sym, prop, P_ENV) |  | ||||||
| 		return prop; |  | ||||||
| 	return NULL; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static struct property *sym_get_default_prop(struct symbol *sym) | static struct property *sym_get_default_prop(struct symbol *sym) | ||||||
| { | { | ||||||
| 	struct property *prop; | 	struct property *prop; | ||||||
| @@ -124,7 +86,7 @@ static struct property *sym_get_default_prop(struct symbol *sym) | |||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| static struct property *sym_get_range_prop(struct symbol *sym) | struct property *sym_get_range_prop(struct symbol *sym) | ||||||
| { | { | ||||||
| 	struct property *prop; | 	struct property *prop; | ||||||
|  |  | ||||||
| @@ -183,7 +145,7 @@ static void sym_validate_range(struct symbol *sym) | |||||||
| 		sprintf(str, "%lld", val2); | 		sprintf(str, "%lld", val2); | ||||||
| 	else | 	else | ||||||
| 		sprintf(str, "0x%llx", val2); | 		sprintf(str, "0x%llx", val2); | ||||||
| 	sym->curr.val = strdup(str); | 	sym->curr.val = xstrdup(str); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void sym_set_changed(struct symbol *sym) | static void sym_set_changed(struct symbol *sym) | ||||||
| @@ -243,7 +205,7 @@ static void sym_calc_visibility(struct symbol *sym) | |||||||
| 	tri = yes; | 	tri = yes; | ||||||
| 	if (sym->dir_dep.expr) | 	if (sym->dir_dep.expr) | ||||||
| 		tri = expr_calc_value(sym->dir_dep.expr); | 		tri = expr_calc_value(sym->dir_dep.expr); | ||||||
| 	if (tri == mod) | 	if (tri == mod && sym_get_type(sym) == S_BOOLEAN) | ||||||
| 		tri = yes; | 		tri = yes; | ||||||
| 	if (sym->dir_dep.tri != tri) { | 	if (sym->dir_dep.tri != tri) { | ||||||
| 		sym->dir_dep.tri = tri; | 		sym->dir_dep.tri = tri; | ||||||
| @@ -258,6 +220,15 @@ static void sym_calc_visibility(struct symbol *sym) | |||||||
| 		sym->rev_dep.tri = tri; | 		sym->rev_dep.tri = tri; | ||||||
| 		sym_set_changed(sym); | 		sym_set_changed(sym); | ||||||
| 	} | 	} | ||||||
|  | 	tri = no; | ||||||
|  | 	if (sym->implied.expr && sym->dir_dep.tri != no) | ||||||
|  | 		tri = expr_calc_value(sym->implied.expr); | ||||||
|  | 	if (tri == mod && sym_get_type(sym) == S_BOOLEAN) | ||||||
|  | 		tri = yes; | ||||||
|  | 	if (sym->implied.tri != tri) { | ||||||
|  | 		sym->implied.tri = tri; | ||||||
|  | 		sym_set_changed(sym); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -362,11 +333,13 @@ void sym_calc_value(struct symbol *sym) | |||||||
| 		sym->curr.tri = no; | 		sym->curr.tri = no; | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	if (!sym_is_choice_value(sym)) |  | ||||||
| 	sym->flags &= ~SYMBOL_WRITE; | 	sym->flags &= ~SYMBOL_WRITE; | ||||||
|  |  | ||||||
| 	sym_calc_visibility(sym); | 	sym_calc_visibility(sym); | ||||||
|  |  | ||||||
|  | 	if (sym->visible != no) | ||||||
|  | 		sym->flags |= SYMBOL_WRITE; | ||||||
|  |  | ||||||
| 	/* set default if recursively called */ | 	/* set default if recursively called */ | ||||||
| 	sym->curr = newval; | 	sym->curr = newval; | ||||||
|  |  | ||||||
| @@ -381,7 +354,6 @@ void sym_calc_value(struct symbol *sym) | |||||||
| 				/* if the symbol is visible use the user value | 				/* if the symbol is visible use the user value | ||||||
| 				 * if available, otherwise try the default value | 				 * if available, otherwise try the default value | ||||||
| 				 */ | 				 */ | ||||||
| 				sym->flags |= SYMBOL_WRITE; |  | ||||||
| 				if (sym_has_value(sym)) { | 				if (sym_has_value(sym)) { | ||||||
| 					newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, | 					newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, | ||||||
| 							      sym->visible); | 							      sym->visible); | ||||||
| @@ -397,27 +369,29 @@ void sym_calc_value(struct symbol *sym) | |||||||
| 					newval.tri = EXPR_AND(expr_calc_value(prop->expr), | 					newval.tri = EXPR_AND(expr_calc_value(prop->expr), | ||||||
| 							      prop->visible.tri); | 							      prop->visible.tri); | ||||||
| 				} | 				} | ||||||
|  | 				if (sym->implied.tri != no) { | ||||||
|  | 					sym->flags |= SYMBOL_WRITE; | ||||||
|  | 					newval.tri = EXPR_OR(newval.tri, sym->implied.tri); | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		calc_newval: | 		calc_newval: | ||||||
| 			if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) { | 			if (sym->dir_dep.tri < sym->rev_dep.tri) { | ||||||
| 				newval.tri = no; | 				newval.tri = no; | ||||||
| 			} else { | 			} else { | ||||||
| 				newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); | 				newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) | 		if (newval.tri == mod && | ||||||
|  | 		    (sym_get_type(sym) == S_BOOLEAN || sym->implied.tri == yes)) | ||||||
| 			newval.tri = yes; | 			newval.tri = yes; | ||||||
| 		break; | 		break; | ||||||
| 	case S_STRING: | 	case S_STRING: | ||||||
| 	case S_HEX: | 	case S_HEX: | ||||||
| 	case S_INT: | 	case S_INT: | ||||||
| 		if (sym->visible != no) { | 		if (sym->visible != no && sym_has_value(sym)) { | ||||||
| 			sym->flags |= SYMBOL_WRITE; |  | ||||||
| 			if (sym_has_value(sym)) { |  | ||||||
| 			newval.val = sym->def[S_DEF_USER].val; | 			newval.val = sym->def[S_DEF_USER].val; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		} |  | ||||||
| 		prop = sym_get_default_prop(sym); | 		prop = sym_get_default_prop(sym); | ||||||
| 		if (prop) { | 		if (prop) { | ||||||
| 			struct symbol *ds = prop_get_symbol(prop); | 			struct symbol *ds = prop_get_symbol(prop); | ||||||
| @@ -458,7 +432,7 @@ void sym_calc_value(struct symbol *sym) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (sym->flags & SYMBOL_AUTO) | 	if (sym->flags & SYMBOL_NO_WRITE) | ||||||
| 		sym->flags &= ~SYMBOL_WRITE; | 		sym->flags &= ~SYMBOL_WRITE; | ||||||
|  |  | ||||||
| 	if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) | 	if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) | ||||||
| @@ -490,6 +464,8 @@ bool sym_tristate_within_range(struct symbol *sym, tristate val) | |||||||
| 		return false; | 		return false; | ||||||
| 	if (sym->visible <= sym->rev_dep.tri) | 	if (sym->visible <= sym->rev_dep.tri) | ||||||
| 		return false; | 		return false; | ||||||
|  | 	if (sym->implied.tri == yes && val == mod) | ||||||
|  | 		return false; | ||||||
| 	if (sym_is_choice_value(sym) && sym->visible == yes) | 	if (sym_is_choice_value(sym) && sym->visible == yes) | ||||||
| 		return val == yes; | 		return val == yes; | ||||||
| 	return val >= sym->rev_dep.tri && val <= sym->visible; | 	return val >= sym->rev_dep.tri && val <= sym->visible; | ||||||
| @@ -742,6 +718,10 @@ const char *sym_get_string_default(struct symbol *sym) | |||||||
| 	if (sym->type == S_BOOLEAN && val == mod) | 	if (sym->type == S_BOOLEAN && val == mod) | ||||||
| 		val = yes; | 		val = yes; | ||||||
|  |  | ||||||
|  | 	/* adjust the default value if this symbol is implied by another */ | ||||||
|  | 	if (val < sym->implied.tri) | ||||||
|  | 		val = sym->implied.tri; | ||||||
|  |  | ||||||
| 	switch (sym->type) { | 	switch (sym->type) { | ||||||
| 	case S_BOOLEAN: | 	case S_BOOLEAN: | ||||||
| 	case S_TRISTATE: | 	case S_TRISTATE: | ||||||
| @@ -755,7 +735,6 @@ const char *sym_get_string_default(struct symbol *sym) | |||||||
| 		return str; | 		return str; | ||||||
| 	case S_STRING: | 	case S_STRING: | ||||||
| 		return str; | 		return str; | ||||||
| 	case S_OTHER: |  | ||||||
| 	case S_UNKNOWN: | 	case S_UNKNOWN: | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| @@ -786,7 +765,7 @@ const char *sym_get_string_value(struct symbol *sym) | |||||||
| 	return (const char *)sym->curr.val; | 	return (const char *)sym->curr.val; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool sym_is_changable(struct symbol *sym) | bool sym_is_changeable(struct symbol *sym) | ||||||
| { | { | ||||||
| 	return sym->visible > sym->rev_dep.tri; | 	return sym->visible > sym->rev_dep.tri; | ||||||
| } | } | ||||||
| @@ -823,7 +802,7 @@ struct symbol *sym_lookup(const char *name, int flags) | |||||||
| 				   : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) | 				   : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) | ||||||
| 				return symbol; | 				return symbol; | ||||||
| 		} | 		} | ||||||
| 		new_name = strdup(name); | 		new_name = xstrdup(name); | ||||||
| 	} else { | 	} else { | ||||||
| 		new_name = NULL; | 		new_name = NULL; | ||||||
| 		hash = 0; | 		hash = 0; | ||||||
| @@ -868,55 +847,6 @@ struct symbol *sym_find(const char *name) | |||||||
| 	return symbol; | 	return symbol; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Expand symbol's names embedded in the string given in argument. Symbols' |  | ||||||
|  * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to |  | ||||||
|  * the empty string. |  | ||||||
|  */ |  | ||||||
| const char *sym_expand_string_value(const char *in) |  | ||||||
| { |  | ||||||
| 	const char *src; |  | ||||||
| 	char *res; |  | ||||||
| 	size_t reslen; |  | ||||||
|  |  | ||||||
| 	reslen = strlen(in) + 1; |  | ||||||
| 	res = xmalloc(reslen); |  | ||||||
| 	res[0] = '\0'; |  | ||||||
|  |  | ||||||
| 	while ((src = strchr(in, '$'))) { |  | ||||||
| 		char *p, name[SYMBOL_MAXLENGTH]; |  | ||||||
| 		const char *symval = ""; |  | ||||||
| 		struct symbol *sym; |  | ||||||
| 		size_t newlen; |  | ||||||
|  |  | ||||||
| 		strncat(res, in, src - in); |  | ||||||
| 		src++; |  | ||||||
|  |  | ||||||
| 		p = name; |  | ||||||
| 		while (isalnum(*src) || *src == '_') |  | ||||||
| 			*p++ = *src++; |  | ||||||
| 		*p = '\0'; |  | ||||||
|  |  | ||||||
| 		sym = sym_find(name); |  | ||||||
| 		if (sym != NULL) { |  | ||||||
| 			sym_calc_value(sym); |  | ||||||
| 			symval = sym_get_string_value(sym); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		newlen = strlen(res) + strlen(symval) + strlen(src) + 1; |  | ||||||
| 		if (newlen > reslen) { |  | ||||||
| 			reslen = newlen; |  | ||||||
| 			res = realloc(res, reslen); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		strcat(res, symval); |  | ||||||
| 		in = src; |  | ||||||
| 	} |  | ||||||
| 	strcat(res, in); |  | ||||||
|  |  | ||||||
| 	return res; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const char *sym_escape_string_value(const char *in) | const char *sym_escape_string_value(const char *in) | ||||||
| { | { | ||||||
| 	const char *p; | 	const char *p; | ||||||
| @@ -1033,7 +963,7 @@ struct symbol **sym_re_search(const char *pattern) | |||||||
| 	} | 	} | ||||||
| 	if (sym_match_arr) { | 	if (sym_match_arr) { | ||||||
| 		qsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp); | 		qsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp); | ||||||
| 		sym_arr = malloc((cnt+1) * sizeof(struct symbol)); | 		sym_arr = malloc((cnt+1) * sizeof(struct symbol *)); | ||||||
| 		if (!sym_arr) | 		if (!sym_arr) | ||||||
| 			goto sym_re_search_free; | 			goto sym_re_search_free; | ||||||
| 		for (i = 0; i < cnt; i++) | 		for (i = 0; i < cnt; i++) | ||||||
| @@ -1058,7 +988,7 @@ static struct dep_stack { | |||||||
| 	struct dep_stack *prev, *next; | 	struct dep_stack *prev, *next; | ||||||
| 	struct symbol *sym; | 	struct symbol *sym; | ||||||
| 	struct property *prop; | 	struct property *prop; | ||||||
| 	struct expr *expr; | 	struct expr **expr; | ||||||
| } *check_top; | } *check_top; | ||||||
|  |  | ||||||
| static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym) | static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym) | ||||||
| @@ -1122,20 +1052,8 @@ static void sym_check_print_recursive(struct symbol *last_sym) | |||||||
| 		if (stack->sym == last_sym) | 		if (stack->sym == last_sym) | ||||||
| 			fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", | 			fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", | ||||||
| 				prop->file->name, prop->lineno); | 				prop->file->name, prop->lineno); | ||||||
| 			fprintf(stderr, "For a resolution refer to Documentation/kbuild/kconfig-language.txt\n"); |  | ||||||
| 			fprintf(stderr, "subsection \"Kconfig recursive dependency limitations\"\n"); | 		if (sym_is_choice(sym)) { | ||||||
| 		if (stack->expr) { |  | ||||||
| 			fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", |  | ||||||
| 				prop->file->name, prop->lineno, |  | ||||||
| 				sym->name ? sym->name : "<choice>", |  | ||||||
| 				prop_get_type_name(prop->type), |  | ||||||
| 				next_sym->name ? next_sym->name : "<choice>"); |  | ||||||
| 		} else if (stack->prop) { |  | ||||||
| 			fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", |  | ||||||
| 				prop->file->name, prop->lineno, |  | ||||||
| 				sym->name ? sym->name : "<choice>", |  | ||||||
| 				next_sym->name ? next_sym->name : "<choice>"); |  | ||||||
| 		} else if (sym_is_choice(sym)) { |  | ||||||
| 			fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", | 			fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", | ||||||
| 				menu->file->name, menu->lineno, | 				menu->file->name, menu->lineno, | ||||||
| 				sym->name ? sym->name : "<choice>", | 				sym->name ? sym->name : "<choice>", | ||||||
| @@ -1145,14 +1063,41 @@ static void sym_check_print_recursive(struct symbol *last_sym) | |||||||
| 				menu->file->name, menu->lineno, | 				menu->file->name, menu->lineno, | ||||||
| 				sym->name ? sym->name : "<choice>", | 				sym->name ? sym->name : "<choice>", | ||||||
| 				next_sym->name ? next_sym->name : "<choice>"); | 				next_sym->name ? next_sym->name : "<choice>"); | ||||||
| 		} else { | 		} else if (stack->expr == &sym->dir_dep.expr) { | ||||||
|  | 			fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", | ||||||
|  | 				prop->file->name, prop->lineno, | ||||||
|  | 				sym->name ? sym->name : "<choice>", | ||||||
|  | 				next_sym->name ? next_sym->name : "<choice>"); | ||||||
|  | 		} else if (stack->expr == &sym->rev_dep.expr) { | ||||||
| 			fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", | 			fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", | ||||||
| 				prop->file->name, prop->lineno, | 				prop->file->name, prop->lineno, | ||||||
| 				sym->name ? sym->name : "<choice>", | 				sym->name ? sym->name : "<choice>", | ||||||
| 				next_sym->name ? next_sym->name : "<choice>"); | 				next_sym->name ? next_sym->name : "<choice>"); | ||||||
|  | 		} else if (stack->expr == &sym->implied.expr) { | ||||||
|  | 			fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n", | ||||||
|  | 				prop->file->name, prop->lineno, | ||||||
|  | 				sym->name ? sym->name : "<choice>", | ||||||
|  | 				next_sym->name ? next_sym->name : "<choice>"); | ||||||
|  | 		} else if (stack->expr) { | ||||||
|  | 			fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", | ||||||
|  | 				prop->file->name, prop->lineno, | ||||||
|  | 				sym->name ? sym->name : "<choice>", | ||||||
|  | 				prop_get_type_name(prop->type), | ||||||
|  | 				next_sym->name ? next_sym->name : "<choice>"); | ||||||
|  | 		} else { | ||||||
|  | 			fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n", | ||||||
|  | 				prop->file->name, prop->lineno, | ||||||
|  | 				sym->name ? sym->name : "<choice>", | ||||||
|  | 				prop_get_type_name(prop->type), | ||||||
|  | 				next_sym->name ? next_sym->name : "<choice>"); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	fprintf(stderr, | ||||||
|  | 		"For a resolution refer to Documentation/kbuild/kconfig-language.rst\n" | ||||||
|  | 		"subsection \"Kconfig recursive dependency limitations\"\n" | ||||||
|  | 		"\n"); | ||||||
|  |  | ||||||
| 	if (check_top == &cv_stack) | 	if (check_top == &cv_stack) | ||||||
| 		dep_stack_remove(); | 		dep_stack_remove(); | ||||||
| } | } | ||||||
| @@ -1187,7 +1132,7 @@ static struct symbol *sym_check_expr_deps(struct expr *e) | |||||||
| 	default: | 	default: | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	printf("Oops! How to check %d?\n", e->type); | 	fprintf(stderr, "Oops! How to check %d?\n", e->type); | ||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1200,12 +1145,26 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym) | |||||||
|  |  | ||||||
| 	dep_stack_insert(&stack, sym); | 	dep_stack_insert(&stack, sym); | ||||||
|  |  | ||||||
|  | 	stack.expr = &sym->dir_dep.expr; | ||||||
|  | 	sym2 = sym_check_expr_deps(sym->dir_dep.expr); | ||||||
|  | 	if (sym2) | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	stack.expr = &sym->rev_dep.expr; | ||||||
| 	sym2 = sym_check_expr_deps(sym->rev_dep.expr); | 	sym2 = sym_check_expr_deps(sym->rev_dep.expr); | ||||||
| 	if (sym2) | 	if (sym2) | ||||||
| 		goto out; | 		goto out; | ||||||
|  |  | ||||||
|  | 	stack.expr = &sym->implied.expr; | ||||||
|  | 	sym2 = sym_check_expr_deps(sym->implied.expr); | ||||||
|  | 	if (sym2) | ||||||
|  | 		goto out; | ||||||
|  |  | ||||||
|  | 	stack.expr = NULL; | ||||||
|  |  | ||||||
| 	for (prop = sym->prop; prop; prop = prop->next) { | 	for (prop = sym->prop; prop; prop = prop->next) { | ||||||
| 		if (prop->type == P_CHOICE || prop->type == P_SELECT) | 		if (prop->type == P_CHOICE || prop->type == P_SELECT || | ||||||
|  | 		    prop->type == P_IMPLY) | ||||||
| 			continue; | 			continue; | ||||||
| 		stack.prop = prop; | 		stack.prop = prop; | ||||||
| 		sym2 = sym_check_expr_deps(prop->visible.expr); | 		sym2 = sym_check_expr_deps(prop->visible.expr); | ||||||
| @@ -1213,7 +1172,7 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym) | |||||||
| 			break; | 			break; | ||||||
| 		if (prop->type != P_DEFAULT || sym_is_choice(sym)) | 		if (prop->type != P_DEFAULT || sym_is_choice(sym)) | ||||||
| 			continue; | 			continue; | ||||||
| 		stack.expr = prop->expr; | 		stack.expr = &prop->expr; | ||||||
| 		sym2 = sym_check_expr_deps(prop->expr); | 		sym2 = sym_check_expr_deps(prop->expr); | ||||||
| 		if (sym2) | 		if (sym2) | ||||||
| 			break; | 			break; | ||||||
| @@ -1291,34 +1250,9 @@ struct symbol *sym_check_deps(struct symbol *sym) | |||||||
| 		sym->flags &= ~SYMBOL_CHECK; | 		sym->flags &= ~SYMBOL_CHECK; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (sym2 && sym2 == sym) |  | ||||||
| 		sym2 = NULL; |  | ||||||
|  |  | ||||||
| 	return sym2; | 	return sym2; | ||||||
| } | } | ||||||
|  |  | ||||||
| struct property *prop_alloc(enum prop_type type, struct symbol *sym) |  | ||||||
| { |  | ||||||
| 	struct property *prop; |  | ||||||
| 	struct property **propp; |  | ||||||
|  |  | ||||||
| 	prop = xmalloc(sizeof(*prop)); |  | ||||||
| 	memset(prop, 0, sizeof(*prop)); |  | ||||||
| 	prop->type = type; |  | ||||||
| 	prop->sym = sym; |  | ||||||
| 	prop->file = current_file; |  | ||||||
| 	prop->lineno = zconf_lineno(); |  | ||||||
|  |  | ||||||
| 	/* append property to the prop list of symbol */ |  | ||||||
| 	if (sym) { |  | ||||||
| 		for (propp = &sym->prop; *propp; propp = &(*propp)->next) |  | ||||||
| 			; |  | ||||||
| 		*propp = prop; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return prop; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| struct symbol *prop_get_symbol(struct property *prop) | struct symbol *prop_get_symbol(struct property *prop) | ||||||
| { | { | ||||||
| 	if (prop->expr && (prop->expr->type == E_SYMBOL || | 	if (prop->expr && (prop->expr->type == E_SYMBOL || | ||||||
| @@ -1332,8 +1266,6 @@ const char *prop_get_type_name(enum prop_type type) | |||||||
| 	switch (type) { | 	switch (type) { | ||||||
| 	case P_PROMPT: | 	case P_PROMPT: | ||||||
| 		return "prompt"; | 		return "prompt"; | ||||||
| 	case P_ENV: |  | ||||||
| 		return "env"; |  | ||||||
| 	case P_COMMENT: | 	case P_COMMENT: | ||||||
| 		return "comment"; | 		return "comment"; | ||||||
| 	case P_MENU: | 	case P_MENU: | ||||||
| @@ -1344,6 +1276,8 @@ const char *prop_get_type_name(enum prop_type type) | |||||||
| 		return "choice"; | 		return "choice"; | ||||||
| 	case P_SELECT: | 	case P_SELECT: | ||||||
| 		return "select"; | 		return "select"; | ||||||
|  | 	case P_IMPLY: | ||||||
|  | 		return "imply"; | ||||||
| 	case P_RANGE: | 	case P_RANGE: | ||||||
| 		return "range"; | 		return "range"; | ||||||
| 	case P_SYMBOL: | 	case P_SYMBOL: | ||||||
| @@ -1355,32 +1289,3 @@ const char *prop_get_type_name(enum prop_type type) | |||||||
| 	} | 	} | ||||||
| 	return "unknown"; | 	return "unknown"; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void prop_add_env(const char *env) |  | ||||||
| { |  | ||||||
| 	struct symbol *sym, *sym2; |  | ||||||
| 	struct property *prop; |  | ||||||
| 	char *p; |  | ||||||
|  |  | ||||||
| 	sym = current_entry->sym; |  | ||||||
| 	sym->flags |= SYMBOL_AUTO; |  | ||||||
| 	for_all_properties(sym, prop, P_ENV) { |  | ||||||
| 		sym2 = prop_get_symbol(prop); |  | ||||||
| 		if (strcmp(sym2->name, env)) |  | ||||||
| 			menu_warn(current_entry, "redefining environment symbol from %s", |  | ||||||
| 				  sym2->name); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	prop = prop_alloc(P_ENV, sym); |  | ||||||
| 	prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); |  | ||||||
|  |  | ||||||
| 	sym_env_list = expr_alloc_one(E_LIST, sym_env_list); |  | ||||||
| 	sym_env_list->right.sym = sym; |  | ||||||
|  |  | ||||||
| 	p = getenv(env); |  | ||||||
| 	if (p) |  | ||||||
| 		sym_add_default(sym, p); |  | ||||||
| 	else |  | ||||||
| 		menu_warn(current_entry, "environment variable %s undefined", env); |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -1,8 +1,7 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0 | ||||||
| /* | /* | ||||||
|  * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org> |  * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org> | ||||||
|  * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org> |  * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org> | ||||||
|  * |  | ||||||
|  * Released under the terms of the GNU GPL v2.0. |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
| @@ -14,69 +13,21 @@ | |||||||
| struct file *file_lookup(const char *name) | struct file *file_lookup(const char *name) | ||||||
| { | { | ||||||
| 	struct file *file; | 	struct file *file; | ||||||
| 	const char *file_name = sym_expand_string_value(name); |  | ||||||
|  |  | ||||||
| 	for (file = file_list; file; file = file->next) { | 	for (file = file_list; file; file = file->next) { | ||||||
| 		if (!strcmp(name, file->name)) { | 		if (!strcmp(name, file->name)) { | ||||||
| 			free((void *)file_name); |  | ||||||
| 			return file; | 			return file; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	file = xmalloc(sizeof(*file)); | 	file = xmalloc(sizeof(*file)); | ||||||
| 	memset(file, 0, sizeof(*file)); | 	memset(file, 0, sizeof(*file)); | ||||||
| 	file->name = file_name; | 	file->name = xstrdup(name); | ||||||
| 	file->next = file_list; | 	file->next = file_list; | ||||||
| 	file_list = file; | 	file_list = file; | ||||||
| 	return file; | 	return file; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* write a dependency file as used by kbuild to track dependencies */ |  | ||||||
| int file_write_dep(const char *name) |  | ||||||
| { |  | ||||||
| 	struct symbol *sym, *env_sym; |  | ||||||
| 	struct expr *e; |  | ||||||
| 	struct file *file; |  | ||||||
| 	FILE *out; |  | ||||||
|  |  | ||||||
| 	if (!name) |  | ||||||
| 		name = ".kconfig.d"; |  | ||||||
| 	out = fopen("..config.tmp", "w"); |  | ||||||
| 	if (!out) |  | ||||||
| 		return 1; |  | ||||||
| 	fprintf(out, "deps_config := \\\n"); |  | ||||||
| 	for (file = file_list; file; file = file->next) { |  | ||||||
| 		if (file->next) |  | ||||||
| 			fprintf(out, "\t%s \\\n", file->name); |  | ||||||
| 		else |  | ||||||
| 			fprintf(out, "\t%s\n", file->name); |  | ||||||
| 	} |  | ||||||
| 	fprintf(out, "\n%s: \\\n" |  | ||||||
| 		     "\t$(deps_config)\n\n", conf_get_autoconfig_name()); |  | ||||||
|  |  | ||||||
| 	expr_list_for_each_sym(sym_env_list, e, sym) { |  | ||||||
| 		struct property *prop; |  | ||||||
| 		const char *value; |  | ||||||
|  |  | ||||||
| 		prop = sym_get_env_prop(sym); |  | ||||||
| 		env_sym = prop_get_symbol(prop); |  | ||||||
| 		if (!env_sym) |  | ||||||
| 			continue; |  | ||||||
| 		value = getenv(env_sym->name); |  | ||||||
| 		if (!value) |  | ||||||
| 			value = ""; |  | ||||||
| 		fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value); |  | ||||||
| 		fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name()); |  | ||||||
| 		fprintf(out, "endif\n"); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	fprintf(out, "\n$(deps_config): ;\n"); |  | ||||||
| 	fclose(out); |  | ||||||
| 	rename("..config.tmp", name); |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Allocate initial growable string */ | /* Allocate initial growable string */ | ||||||
| struct gstr str_new(void) | struct gstr str_new(void) | ||||||
| { | { | ||||||
| @@ -104,7 +55,7 @@ void str_append(struct gstr *gs, const char *s) | |||||||
| 	if (s) { | 	if (s) { | ||||||
| 		l = strlen(gs->s) + strlen(s) + 1; | 		l = strlen(gs->s) + strlen(s) + 1; | ||||||
| 		if (l > gs->len) { | 		if (l > gs->len) { | ||||||
| 			gs->s   = realloc(gs->s, l); | 			gs->s = xrealloc(gs->s, l); | ||||||
| 			gs->len = l; | 			gs->len = l; | ||||||
| 		} | 		} | ||||||
| 		strcat(gs->s, s); | 		strcat(gs->s, s); | ||||||
| @@ -145,3 +96,34 @@ void *xcalloc(size_t nmemb, size_t size) | |||||||
| 	fprintf(stderr, "Out of memory.\n"); | 	fprintf(stderr, "Out of memory.\n"); | ||||||
| 	exit(1); | 	exit(1); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void *xrealloc(void *p, size_t size) | ||||||
|  | { | ||||||
|  | 	p = realloc(p, size); | ||||||
|  | 	if (p) | ||||||
|  | 		return p; | ||||||
|  | 	fprintf(stderr, "Out of memory.\n"); | ||||||
|  | 	exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *xstrdup(const char *s) | ||||||
|  | { | ||||||
|  | 	char *p; | ||||||
|  |  | ||||||
|  | 	p = strdup(s); | ||||||
|  | 	if (p) | ||||||
|  | 		return p; | ||||||
|  | 	fprintf(stderr, "Out of memory.\n"); | ||||||
|  | 	exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *xstrndup(const char *s, size_t n) | ||||||
|  | { | ||||||
|  | 	char *p; | ||||||
|  |  | ||||||
|  | 	p = strndup(s, n); | ||||||
|  | 	if (p) | ||||||
|  | 		return p; | ||||||
|  | 	fprintf(stderr, "Out of memory.\n"); | ||||||
|  | 	exit(1); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,49 +0,0 @@ | |||||||
| %language=ANSI-C |  | ||||||
| %define hash-function-name kconf_id_hash |  | ||||||
| %define lookup-function-name kconf_id_lookup |  | ||||||
| %define string-pool-name kconf_id_strings |  | ||||||
| %compare-strncmp |  | ||||||
| %enum |  | ||||||
| %pic |  | ||||||
| %struct-type |  | ||||||
|  |  | ||||||
| struct kconf_id; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| %% |  | ||||||
| mainmenu,	T_MAINMENU,	TF_COMMAND |  | ||||||
| menu,		T_MENU,		TF_COMMAND |  | ||||||
| endmenu,	T_ENDMENU,	TF_COMMAND |  | ||||||
| source,		T_SOURCE,	TF_COMMAND |  | ||||||
| choice,		T_CHOICE,	TF_COMMAND |  | ||||||
| endchoice,	T_ENDCHOICE,	TF_COMMAND |  | ||||||
| comment,	T_COMMENT,	TF_COMMAND |  | ||||||
| config,		T_CONFIG,	TF_COMMAND |  | ||||||
| menuconfig,	T_MENUCONFIG,	TF_COMMAND |  | ||||||
| help,		T_HELP,		TF_COMMAND |  | ||||||
| ---help---,	T_HELP,		TF_COMMAND |  | ||||||
| if,		T_IF,		TF_COMMAND|TF_PARAM |  | ||||||
| endif,		T_ENDIF,	TF_COMMAND |  | ||||||
| depends,	T_DEPENDS,	TF_COMMAND |  | ||||||
| optional,	T_OPTIONAL,	TF_COMMAND |  | ||||||
| default,	T_DEFAULT,	TF_COMMAND, S_UNKNOWN |  | ||||||
| prompt,		T_PROMPT,	TF_COMMAND |  | ||||||
| tristate,	T_TYPE,		TF_COMMAND, S_TRISTATE |  | ||||||
| def_tristate,	T_DEFAULT,	TF_COMMAND, S_TRISTATE |  | ||||||
| bool,		T_TYPE,		TF_COMMAND, S_BOOLEAN |  | ||||||
| boolean,	T_TYPE,		TF_COMMAND, S_BOOLEAN |  | ||||||
| def_bool,	T_DEFAULT,	TF_COMMAND, S_BOOLEAN |  | ||||||
| int,		T_TYPE,		TF_COMMAND, S_INT |  | ||||||
| hex,		T_TYPE,		TF_COMMAND, S_HEX |  | ||||||
| string,		T_TYPE,		TF_COMMAND, S_STRING |  | ||||||
| select,		T_SELECT,	TF_COMMAND |  | ||||||
| range,		T_RANGE,	TF_COMMAND |  | ||||||
| visible,	T_VISIBLE,	TF_COMMAND |  | ||||||
| option,		T_OPTION,	TF_COMMAND |  | ||||||
| on,		T_ON,		TF_PARAM |  | ||||||
| modules,	T_OPT_MODULES,	TF_OPTION |  | ||||||
| defconfig_list,	T_OPT_DEFCONFIG_LIST,TF_OPTION |  | ||||||
| env,		T_OPT_ENV,	TF_OPTION |  | ||||||
| allnoconfig_y,	T_OPT_ALLNOCONFIG_Y,TF_OPTION |  | ||||||
| reset,		T_RESET,	TF_COMMAND |  | ||||||
| %% |  | ||||||
| @@ -1,250 +0,0 @@ | |||||||
| /* ANSI-C code produced by gperf version 3.0.4 */ |  | ||||||
| /* Command-line: gperf  */ |  | ||||||
| /* Computed positions: -k'1,3' */ |  | ||||||
|  |  | ||||||
| #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ |  | ||||||
|       && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ |  | ||||||
|       && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ |  | ||||||
|       && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ |  | ||||||
|       && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ |  | ||||||
|       && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ |  | ||||||
|       && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ |  | ||||||
|       && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ |  | ||||||
|       && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ |  | ||||||
|       && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ |  | ||||||
|       && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ |  | ||||||
|       && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ |  | ||||||
|       && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ |  | ||||||
|       && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ |  | ||||||
|       && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ |  | ||||||
|       && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ |  | ||||||
|       && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ |  | ||||||
|       && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ |  | ||||||
|       && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ |  | ||||||
|       && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ |  | ||||||
|       && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ |  | ||||||
|       && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ |  | ||||||
|       && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) |  | ||||||
| /* The character set is not based on ISO-646.  */ |  | ||||||
| #error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>." |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| struct kconf_id; |  | ||||||
| /* maximum key range = 47, duplicates = 0 */ |  | ||||||
|  |  | ||||||
| #ifdef __GNUC__ |  | ||||||
| __inline |  | ||||||
| #else |  | ||||||
| #ifdef __cplusplus |  | ||||||
| inline |  | ||||||
| #endif |  | ||||||
| #endif |  | ||||||
| static unsigned int |  | ||||||
| kconf_id_hash (register const char *str, register unsigned int len) |  | ||||||
| { |  | ||||||
|   static unsigned char asso_values[] = |  | ||||||
|     { |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 10, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 20, 40,  5, |  | ||||||
|        0,  0,  5, 49,  5, 20, 49, 49,  5, 20, |  | ||||||
|        5,  0, 35, 49,  0, 15,  0, 10, 15, 49, |  | ||||||
|       25, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |  | ||||||
|       49, 49, 49, 49, 49, 49 |  | ||||||
|     }; |  | ||||||
|   register int hval = len; |  | ||||||
|  |  | ||||||
|   switch (hval) |  | ||||||
|     { |  | ||||||
|       default: |  | ||||||
|         hval += asso_values[(unsigned char)str[2]]; |  | ||||||
|       /*FALLTHROUGH*/ |  | ||||||
|       case 2: |  | ||||||
|       case 1: |  | ||||||
|         hval += asso_values[(unsigned char)str[0]]; |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|   return hval; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| struct kconf_id_strings_t |  | ||||||
|   { |  | ||||||
|     char kconf_id_strings_str2[sizeof("on")]; |  | ||||||
|     char kconf_id_strings_str5[sizeof("endif")]; |  | ||||||
|     char kconf_id_strings_str6[sizeof("option")]; |  | ||||||
|     char kconf_id_strings_str7[sizeof("endmenu")]; |  | ||||||
|     char kconf_id_strings_str8[sizeof("optional")]; |  | ||||||
|     char kconf_id_strings_str9[sizeof("endchoice")]; |  | ||||||
|     char kconf_id_strings_str10[sizeof("range")]; |  | ||||||
|     char kconf_id_strings_str11[sizeof("choice")]; |  | ||||||
|     char kconf_id_strings_str12[sizeof("default")]; |  | ||||||
|     char kconf_id_strings_str13[sizeof("def_bool")]; |  | ||||||
|     char kconf_id_strings_str14[sizeof("help")]; |  | ||||||
|     char kconf_id_strings_str16[sizeof("config")]; |  | ||||||
|     char kconf_id_strings_str17[sizeof("def_tristate")]; |  | ||||||
|     char kconf_id_strings_str18[sizeof("env")]; |  | ||||||
|     char kconf_id_strings_str19[sizeof("defconfig_list")]; |  | ||||||
|     char kconf_id_strings_str20[sizeof("reset")]; |  | ||||||
|     char kconf_id_strings_str21[sizeof("string")]; |  | ||||||
|     char kconf_id_strings_str22[sizeof("if")]; |  | ||||||
|     char kconf_id_strings_str23[sizeof("int")]; |  | ||||||
|     char kconf_id_strings_str26[sizeof("select")]; |  | ||||||
|     char kconf_id_strings_str27[sizeof("modules")]; |  | ||||||
|     char kconf_id_strings_str28[sizeof("tristate")]; |  | ||||||
|     char kconf_id_strings_str29[sizeof("menu")]; |  | ||||||
|     char kconf_id_strings_str30[sizeof("---help---")]; |  | ||||||
|     char kconf_id_strings_str31[sizeof("source")]; |  | ||||||
|     char kconf_id_strings_str32[sizeof("comment")]; |  | ||||||
|     char kconf_id_strings_str33[sizeof("hex")]; |  | ||||||
|     char kconf_id_strings_str35[sizeof("menuconfig")]; |  | ||||||
|     char kconf_id_strings_str37[sizeof("visible")]; |  | ||||||
|     char kconf_id_strings_str38[sizeof("allnoconfig_y")]; |  | ||||||
|     char kconf_id_strings_str41[sizeof("prompt")]; |  | ||||||
|     char kconf_id_strings_str42[sizeof("depends")]; |  | ||||||
|     char kconf_id_strings_str44[sizeof("bool")]; |  | ||||||
|     char kconf_id_strings_str47[sizeof("boolean")]; |  | ||||||
|     char kconf_id_strings_str48[sizeof("mainmenu")]; |  | ||||||
|   }; |  | ||||||
| static struct kconf_id_strings_t kconf_id_strings_contents = |  | ||||||
|   { |  | ||||||
|     "on", |  | ||||||
|     "endif", |  | ||||||
|     "option", |  | ||||||
|     "endmenu", |  | ||||||
|     "optional", |  | ||||||
|     "endchoice", |  | ||||||
|     "range", |  | ||||||
|     "choice", |  | ||||||
|     "default", |  | ||||||
|     "def_bool", |  | ||||||
|     "help", |  | ||||||
|     "config", |  | ||||||
|     "def_tristate", |  | ||||||
|     "env", |  | ||||||
|     "defconfig_list", |  | ||||||
|     "reset", |  | ||||||
|     "string", |  | ||||||
|     "if", |  | ||||||
|     "int", |  | ||||||
|     "select", |  | ||||||
|     "modules", |  | ||||||
|     "tristate", |  | ||||||
|     "menu", |  | ||||||
|     "---help---", |  | ||||||
|     "source", |  | ||||||
|     "comment", |  | ||||||
|     "hex", |  | ||||||
|     "menuconfig", |  | ||||||
|     "visible", |  | ||||||
|     "allnoconfig_y", |  | ||||||
|     "prompt", |  | ||||||
|     "depends", |  | ||||||
|     "bool", |  | ||||||
|     "boolean", |  | ||||||
|     "mainmenu" |  | ||||||
|   }; |  | ||||||
| #define kconf_id_strings ((const char *) &kconf_id_strings_contents) |  | ||||||
| #ifdef __GNUC__ |  | ||||||
| __inline |  | ||||||
| #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ |  | ||||||
| __attribute__ ((__gnu_inline__)) |  | ||||||
| #endif |  | ||||||
| #endif |  | ||||||
| struct kconf_id * |  | ||||||
| kconf_id_lookup (register const char *str, register unsigned int len) |  | ||||||
| { |  | ||||||
|   enum |  | ||||||
|     { |  | ||||||
|       TOTAL_KEYWORDS = 35, |  | ||||||
|       MIN_WORD_LENGTH = 2, |  | ||||||
|       MAX_WORD_LENGTH = 14, |  | ||||||
|       MIN_HASH_VALUE = 2, |  | ||||||
|       MAX_HASH_VALUE = 48 |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|   static struct kconf_id wordlist[] = |  | ||||||
|     { |  | ||||||
|       {-1}, {-1}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2,		T_ON,		TF_PARAM}, |  | ||||||
|       {-1}, {-1}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5,		T_ENDIF,	TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6,		T_OPTION,	TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7,	T_ENDMENU,	TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8,	T_OPTIONAL,	TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9,	T_ENDCHOICE,	TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10,		T_RANGE,	TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11,		T_CHOICE,	TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12,	T_DEFAULT,	TF_COMMAND, S_UNKNOWN}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13,	T_DEFAULT,	TF_COMMAND, S_BOOLEAN}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14,		T_HELP,		TF_COMMAND}, |  | ||||||
|       {-1}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16,		T_CONFIG,	TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17,	T_DEFAULT,	TF_COMMAND, S_TRISTATE}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18,		T_OPT_ENV,	TF_OPTION}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str19,	T_OPT_DEFCONFIG_LIST,TF_OPTION}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str20,		T_RESET,	TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21,		T_TYPE,		TF_COMMAND, S_STRING}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22,		T_IF,		TF_COMMAND|TF_PARAM}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23,		T_TYPE,		TF_COMMAND, S_INT}, |  | ||||||
|       {-1}, {-1}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26,		T_SELECT,	TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27,	T_OPT_MODULES,	TF_OPTION}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28,	T_TYPE,		TF_COMMAND, S_TRISTATE}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29,		T_MENU,		TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str30,	T_HELP,		TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31,		T_SOURCE,	TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32,	T_COMMENT,	TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33,		T_TYPE,		TF_COMMAND, S_HEX}, |  | ||||||
|       {-1}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35,	T_MENUCONFIG,	TF_COMMAND}, |  | ||||||
|       {-1}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37,	T_VISIBLE,	TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str38,	T_OPT_ALLNOCONFIG_Y,TF_OPTION}, |  | ||||||
|       {-1}, {-1}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41,		T_PROMPT,	TF_COMMAND}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42,	T_DEPENDS,	TF_COMMAND}, |  | ||||||
|       {-1}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str44,		T_TYPE,		TF_COMMAND, S_BOOLEAN}, |  | ||||||
|       {-1}, {-1}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47,	T_TYPE,		TF_COMMAND, S_BOOLEAN}, |  | ||||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str48,	T_MAINMENU,	TF_COMMAND} |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) |  | ||||||
|     { |  | ||||||
|       register int key = kconf_id_hash (str, len); |  | ||||||
|  |  | ||||||
|       if (key <= MAX_HASH_VALUE && key >= 0) |  | ||||||
|         { |  | ||||||
|           register int o = wordlist[key].name; |  | ||||||
|           if (o >= 0) |  | ||||||
|             { |  | ||||||
|               register const char *s = o + kconf_id_strings; |  | ||||||
|  |  | ||||||
|               if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') |  | ||||||
|                 return &wordlist[key]; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user