util/kconfig: Uprev to Linux 5.13's kconfig
This was originally several commits that had to be squashed into one because the intermediate states weren't able to build coreboot: - one to remove everything that wasn't our own code, leaving only regex.[ch], toada.c, description.md and Makefile.inc. - one to copy in Linux 5.13's scripts/kconfig and adapt Makefile.inc to make the original Makefile work again. - adapt abuild to use olddefconfig, simplifying matters. - apply patches in util/kconfig/patches. - Some more adaptations to the libpayload build system. The patches are now in util/kconfig/patches/, reverse applying them should lead to a util/kconfig/ tree that contains exactly the Linux version + our own 5 files. Change-Id: Ia0e8fe4e9022b278f34ab113a433ef4d45e5c355 Signed-off-by: Patrick Georgi <pgeorgi@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/37152 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Raul Rangel <rrangel@chromium.org>
This commit is contained in:
		| @@ -55,10 +55,6 @@ command line. | ||||
| - savedefconfig - Creates a ‘defconfig’ file, stripping out all of the symbols | ||||
|   that were left as default values.  This is very useful for debugging, and is | ||||
|   how config files should be saved. | ||||
| - silentoldconfig - This evaluates the .config file the same way that the | ||||
|   oldconfig target does, but does not print out each question as it is | ||||
|   evaluated.  It still stops to query the user if an option with no answer in | ||||
|   the .config file is found. | ||||
|  | ||||
|  | ||||
| ### Targets not typically used in coreboot | ||||
|   | ||||
							
								
								
									
										5
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								Makefile
									
									
									
									
									
								
							| @@ -37,7 +37,7 @@ KCONFIG_AUTOADS := $(obj)/cb-config.ads | ||||
| KCONFIG_AUTOHEADER := $(obj)/config.h | ||||
| KCONFIG_AUTOCONFIG := $(obj)/auto.conf | ||||
| KCONFIG_DEPENDENCIES := $(obj)/auto.conf.cmd | ||||
| KCONFIG_SPLITCONFIG := $(obj)/config | ||||
| KCONFIG_SPLITCONFIG := $(obj)/config/ | ||||
| KCONFIG_TRISTATE := $(obj)/tristate.conf | ||||
| KCONFIG_NEGATIVES := 1 | ||||
| KCONFIG_STRICT := 1 | ||||
| @@ -196,7 +196,8 @@ real-all: real-target | ||||
| .DELETE_ON_ERROR: | ||||
|  | ||||
| $(KCONFIG_AUTOHEADER): $(KCONFIG_CONFIG) $(objutil)/kconfig/conf | ||||
| 	+$(MAKE) oldconfig | ||||
| 	$(MAKE) olddefconfig | ||||
| 	$(MAKE) syncconfig | ||||
|  | ||||
| $(KCONFIG_AUTOCONFIG): $(KCONFIG_AUTOHEADER) | ||||
| 	true | ||||
|   | ||||
| @@ -34,7 +34,7 @@ export KCONFIG_SPLITCONFIG	:= $(obj)/config | ||||
| export KCONFIG_TRISTATE		:= $(obj)/tristate.conf | ||||
| export KCONFIG_CONFIG		:= $(CURDIR)/.config | ||||
| export KCONFIG_NEGATIVES	:= 1 | ||||
| export Kconfig			:= Kconfig | ||||
| export KBUILD_KCONFIG		:= Kconfig | ||||
|  | ||||
| CONFIG_SHELL := sh | ||||
| KBUILD_DEFCONFIG := configs/defconfig | ||||
| @@ -70,7 +70,7 @@ $(obj)/config.h: | ||||
|  | ||||
| $(shell mkdir -p $(objk)/lxdialog $(KCONFIG_SPLITCONFIG)) | ||||
|  | ||||
| include $(srck)/Makefile | ||||
| include $(srck)/Makefile.inc | ||||
|  | ||||
| .PHONY: $(PHONY) prepare all real-all defaultbuild | ||||
|  | ||||
|   | ||||
| @@ -43,10 +43,10 @@ export objk := $(objutil)/lp_kconfig | ||||
| export KCONFIG_AUTOHEADER := $(obj)/config.h | ||||
| export KCONFIG_AUTOCONFIG := $(obj)/auto.conf | ||||
| export KCONFIG_DEPENDENCIES := $(obj)/auto.conf.cmd | ||||
| export KCONFIG_SPLITCONFIG := $(obj)/config | ||||
| export KCONFIG_SPLITCONFIG := $(obj)/config/ | ||||
| export KCONFIG_TRISTATE := $(obj)/tristate.conf | ||||
| export KCONFIG_NEGATIVES := 1 | ||||
| export Kconfig := Kconfig | ||||
| export KBUILD_KCONFIG := Kconfig | ||||
| export CONFIG_ := CONFIG_LP_ | ||||
|  | ||||
| # directory containing the toplevel Makefile.inc | ||||
| @@ -88,7 +88,7 @@ endif | ||||
|  | ||||
| # This include must come _before_ the pattern rules below! | ||||
| # Order _does_ matter for pattern rules. | ||||
| include $(srck)/Makefile | ||||
| include $(srck)/Makefile.inc | ||||
|  | ||||
| include $(HAVE_DOTCONFIG) | ||||
|  | ||||
| @@ -202,7 +202,8 @@ endif | ||||
| .SECONDEXPANSION: | ||||
|  | ||||
| $(KCONFIG_AUTOHEADER): $(KCONFIG_CONFIG) | ||||
| 	$(MAKE) oldconfig | ||||
| 	$(MAKE) CONFIG_=CONFIG_LP_ olddefconfig | ||||
| 	$(MAKE) CONFIG_=CONFIG_LP_ syncconfig | ||||
|  | ||||
| # Add a new class of source/object files to the build system | ||||
| add-class= \ | ||||
|   | ||||
| @@ -119,6 +119,7 @@ $(obj)/%.S.o: %.S $(LIBPAYLOAD_CONFIG_H) $(DEFAULT_DEPS) | ||||
|  | ||||
| LIBPAYLOAD_OPTS := obj="$(LIBPAYLOAD_OBJ)" | ||||
| LIBPAYLOAD_OPTS += DOTCONFIG="$(LIBPAYLOAD_DOTCONFIG)" | ||||
| LIBPAYLOAD_OPTS += CONFIG_=CONFIG_LP_ | ||||
| LIBPAYLOAD_OPTS += $(if $(CCACHE),CONFIG_LP_CCACHE=y) | ||||
|  | ||||
| defconfig: lp-defconfig | ||||
|   | ||||
| @@ -169,8 +169,8 @@ $(TEST_KCONFIG_AUTOHEADER): TEST_KCONFIG_FLAGS:= DOTCONFIG=$(TEST_DOTCONFIG) \ | ||||
|  | ||||
| $(TEST_KCONFIG_AUTOHEADER): $(TEST_DOTCONFIG) $(objutil)/kconfig/conf | ||||
| 	mkdir -p $(dir $@) | ||||
| 	+$(MAKE) $(TEST_KCONFIG_FLAGS) olddefconfig | ||||
| 	+$(MAKE) $(TEST_KCONFIG_FLAGS) silentoldconfig | ||||
| 	$(MAKE) $(TEST_KCONFIG_FLAGS) olddefconfig | ||||
| 	$(MAKE) $(TEST_KCONFIG_FLAGS) syncconfig | ||||
|  | ||||
| $(TEST_KCONFIG_AUTOCONFIG): $(TEST_KCONFIG_AUTOHEADER) | ||||
| 	true | ||||
|   | ||||
| @@ -281,7 +281,7 @@ function update_config | ||||
| 	# shellcheck disable=SC2059 | ||||
| 	printf "$configoptions" >> "${config_file}" | ||||
|  | ||||
| 	yes "" 2>/dev/null | $MAKE oldconfig "$verboseopt" "DOTCONFIG=${config_file}" "obj=${build_dir}" "objutil=$TARGET/sharedutils" &> "${build_dir}/config.log" ; \ | ||||
| 	$MAKE olddefconfig "$verboseopt" "DOTCONFIG=${config_file}" "obj=${build_dir}" "objutil=$TARGET/sharedutils" &> "${build_dir}/config.log" ; \ | ||||
| 		CONFIG_OK=$? | ||||
| 	if [ $CONFIG_OK -eq 0 ]; then | ||||
| 		$MAKE savedefconfig "$verboseopt" DEFCONFIG="${defconfig_file}" DOTCONFIG="${config_file}" obj="${build_dir}" objutil="$TARGET/sharedutils" &>> "${build_dir}/config.log" | ||||
| @@ -316,7 +316,7 @@ function create_buildenv | ||||
| 	echo "OBJUTIL=\$(BUILD)/sharedutils" >> "$MAKEFILE" | ||||
| 	echo "all:" >> "$MAKEFILE" | ||||
| 	echo "	@cp -a config.h config.h.bak" >> "$MAKEFILE" | ||||
| 	echo "	@cd \$(TOP); \$(MAKE) oldconfig DOTCONFIG=\$(OBJ)/config.build objutil=\$(OBJUTIL) obj=\$(OBJ)" >> "$MAKEFILE" | ||||
| 	echo "	@cd \$(TOP); \$(MAKE) olddefconfig DOTCONFIG=\$(OBJ)/config.build objutil=\$(OBJUTIL) obj=\$(OBJ)" >> "$MAKEFILE" | ||||
| 	echo "	@tail -n+6 config.h > config.new; tail -n+6 config.h.bak > config.old" >> "$MAKEFILE" | ||||
| 	echo "	@cmp -s config.new config.old && cp -a config.h.bak config.h || echo \"Config file changed\"" >> "$MAKEFILE" | ||||
| 	echo "	@rm config.h.bak config.new config.old" >> "$MAKEFILE" | ||||
| @@ -788,7 +788,7 @@ fi | ||||
|  | ||||
| # Generate a single xcompile for all boards | ||||
| export xcompile="${TARGET}/xcompile" | ||||
| $MAKE -C"${ROOT}" UPDATED_SUBMODULES=1 "${xcompile}" || exit 1 | ||||
| $MAKE -C"${ROOT}" obj="$TARGET/temp" objutil="$TARGET/sharedutils" UPDATED_SUBMODULES=1 "${xcompile}" || exit 1 | ||||
|  | ||||
| customizing=$(echo "$customizing" | cut -c3-) | ||||
| if [ "$customizing" = "" ]; then | ||||
| @@ -838,9 +838,7 @@ build_targets() | ||||
| 	# seed shared utils | ||||
| 	TMPCFG=$(mktemp) | ||||
| 	printf "%s" "$configoptions" > "$TMPCFG" | ||||
| 	$MAKE -j "$cpus" DOTCONFIG="$TMPCFG" obj="$TARGET/temp" objutil="$TARGET/sharedutils" allnoconfig | ||||
| 	printf "%s" "$configoptions" >> "$TMPCFG" | ||||
| 	yes "" 2>/dev/null | $MAKE -j "$cpus" DOTCONFIG="$TMPCFG" obj="$TARGET/temp" objutil="$TARGET/sharedutils" oldconfig | ||||
| 	$MAKE -j "$cpus" DOTCONFIG="$TMPCFG" obj="$TARGET/temp" objutil="$TARGET/sharedutils" olddefconfig 2>/dev/null | ||||
| 	BUILDPREFIX= | ||||
| 	if [ "$scanbuild" = "true" ]; then | ||||
| 		scanbuild_out=$TARGET/sharedutils-scanbuild | ||||
|   | ||||
							
								
								
									
										5
									
								
								util/kconfig/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								util/kconfig/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| # SPDX-License-Identifier: GPL-2.0-only | ||||
| /conf | ||||
| /[gmnq]conf | ||||
| /[gmnq]conf-cfg | ||||
| /qconf-moc.cc | ||||
| @@ -1,377 +1,213 @@ | ||||
| # SPDX-License-Identifier: GPL-2.0 | ||||
| # =========================================================================== | ||||
| # Kernel configuration targets | ||||
| # These targets are used from top-level makefile | ||||
|  | ||||
| export LC_ALL=C | ||||
| export LANG=C | ||||
| ifdef KBUILD_KCONFIG | ||||
| Kconfig := $(KBUILD_KCONFIG) | ||||
| else | ||||
| Kconfig := Kconfig | ||||
| endif | ||||
|  | ||||
| DEFCONFIG?=defconfig | ||||
| ifndef KBUILD_DEFCONFIG | ||||
| KBUILD_DEFCONFIG := defconfig | ||||
| endif | ||||
|  | ||||
| PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config \ | ||||
| 	localmodconfig localyesconfig | ||||
| ifeq ($(quiet),silent_) | ||||
| silent := -s | ||||
| endif | ||||
|  | ||||
| xconfig: $(objk)/qconf | ||||
| 	$< $(Kconfig) | ||||
| export KCONFIG_DEFCONFIG_LIST := | ||||
| ifndef cross_compiling | ||||
| kernel-release := $(shell uname -r) | ||||
| KCONFIG_DEFCONFIG_LIST += \ | ||||
| 	/lib/modules/$(kernel-release)/.config \ | ||||
| 	/etc/kernel-config \ | ||||
| 	/boot/config-$(kernel-release) | ||||
| endif | ||||
| KCONFIG_DEFCONFIG_LIST += arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) | ||||
|  | ||||
| gconfig: $(objk)/gconf | ||||
| 	cp -f $(srck)/gconf.glade $(objk)/gconf.glade | ||||
| 	$< $(Kconfig) | ||||
| # We need this, in case the user has it in its environment | ||||
| unexport CONFIG_ | ||||
|  | ||||
| menuconfig: $(objk)/mconf | ||||
| 	$< $(Kconfig) | ||||
| config-prog	:= conf | ||||
| menuconfig-prog	:= mconf | ||||
| nconfig-prog	:= nconf | ||||
| gconfig-prog	:= gconf | ||||
| xconfig-prog	:= qconf | ||||
|  | ||||
| config: $(objk)/conf | ||||
| 	$< --oldaskconfig $(Kconfig) | ||||
| define config_rule | ||||
| PHONY += $(1) | ||||
| $(1): $(obj)/$($(1)-prog) | ||||
| 	$(Q)$$< $(silent) $(Kconfig) | ||||
|  | ||||
| nconfig: $(objk)/nconf | ||||
| 	$< $(Kconfig) | ||||
| PHONY += build_$(1) | ||||
| build_$(1): $(obj)/$($(1)-prog) | ||||
| endef | ||||
|  | ||||
| # Disable strict mode because oldconfig is typically used to clean up | ||||
| # templates and the like. The second invocation should already have sane data. | ||||
| oldconfig: $(objk)/conf | ||||
| 	KCONFIG_STRICT= $< --$@ $(Kconfig) | ||||
| 	$< --silentoldconfig $(Kconfig) | ||||
| $(foreach c, config menuconfig nconfig gconfig xconfig, $(eval $(call config_rule,$(c)))) | ||||
|  | ||||
| silentoldconfig: $(objk)/conf | ||||
| 	$< --$@ $(Kconfig) | ||||
|  | ||||
| # --- UNUSED, ignore ---------------------------------------------------------- | ||||
| localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf | ||||
| 	$(Q)mkdir -p include/generated | ||||
| 	$(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config | ||||
| 	$(Q)if [ -f .config ]; then 					\ | ||||
| 			cmp -s .tmp.config .config ||			\ | ||||
| 			(mv -f .config .config.old.1;			\ | ||||
| 			 mv -f .tmp.config .config;			\ | ||||
| 			 $(obj)/conf --silentoldconfig $(Kconfig);	\ | ||||
| 			 mv -f .config.old.1 .config.old)		\ | ||||
| 	else								\ | ||||
| 			mv -f .tmp.config .config;			\ | ||||
| 			$(obj)/conf --silentoldconfig $(Kconfig);	\ | ||||
| PHONY += localmodconfig localyesconfig | ||||
| localyesconfig localmodconfig: $(obj)/conf | ||||
| 	$(Q)$(PERL) $(srctree)/$(src)/streamline_config.pl --$@ $(srctree) $(Kconfig) > .tmp.config | ||||
| 	$(Q)if [ -f .config ]; then 				\ | ||||
| 		cmp -s .tmp.config .config ||			\ | ||||
| 		(mv -f .config .config.old.1;			\ | ||||
| 		 mv -f .tmp.config .config;			\ | ||||
| 		 $< $(silent) --oldconfig $(Kconfig);		\ | ||||
| 		 mv -f .config.old.1 .config.old)		\ | ||||
| 	else							\ | ||||
| 		mv -f .tmp.config .config;			\ | ||||
| 		$< $(silent) --oldconfig $(Kconfig);		\ | ||||
| 	fi | ||||
| 	$(Q)rm -f .tmp.config | ||||
|  | ||||
| # Create new linux.pot file | ||||
| # Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files | ||||
| update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h | ||||
| 	$(Q)echo "  GEN     config.pot" | ||||
| 	$(Q)xgettext --default-domain=linux                         \ | ||||
| 	    --add-comments --keyword=_ --keyword=N_                 \ | ||||
| 	    --from-code=UTF-8                                       \ | ||||
| 	    --files-from=$(srctree)/scripts/kconfig/POTFILES.in     \ | ||||
| 	    --directory=$(srctree) --directory=$(objtree)           \ | ||||
| 	    --output $(obj)/config.pot | ||||
| 	$(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot | ||||
| 	$(Q)(for i in `ls $(srctree)/arch/*/Kconfig      \ | ||||
| 	    $(srctree)/arch/*/um/Kconfig`;               \ | ||||
| 	    do                                           \ | ||||
| 		echo "  GEN     $$i";                    \ | ||||
| 		$(obj)/kxgettext $$i                     \ | ||||
| 		     >> $(obj)/config.pot;               \ | ||||
| 	    done ) | ||||
| 	$(Q)echo "  GEN     linux.pot" | ||||
| 	$(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \ | ||||
| 	    --output $(obj)/linux.pot | ||||
| 	$(Q)rm -f $(obj)/config.pot | ||||
| # --- UNUSED, ignore ---------------------------------------------------------- | ||||
| # These targets map 1:1 to the commandline options of 'conf' | ||||
| # | ||||
| # Note: | ||||
| #  syncconfig has become an internal implementation detail and is now | ||||
| #  deprecated for external use | ||||
| simple-targets := oldconfig allnoconfig allyesconfig allmodconfig \ | ||||
| 	alldefconfig randconfig listnewconfig olddefconfig syncconfig \ | ||||
| 	helpnewconfig yes2modconfig mod2yesconfig | ||||
|  | ||||
| PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig savedefconfig | ||||
| PHONY += $(simple-targets) | ||||
|  | ||||
| allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(objk)/conf | ||||
| 	$< --$@ $(Kconfig) | ||||
| $(simple-targets): $(obj)/conf | ||||
| 	$(Q)$< $(silent) --$@ $(Kconfig) | ||||
|  | ||||
| savedefconfig: $(objk)/conf | ||||
| 	$< --$@=$(DEFCONFIG) $(Kconfig) | ||||
| PHONY += savedefconfig defconfig | ||||
|  | ||||
| defconfig: $(objk)/conf | ||||
| ifeq ($(KBUILD_DEFCONFIG),) | ||||
| 	$< --defconfig $(Kconfig) | ||||
| savedefconfig: $(obj)/conf | ||||
| 	$(Q)$< $(silent) --$@=defconfig $(Kconfig) | ||||
|  | ||||
| defconfig: $(obj)/conf | ||||
| ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)),) | ||||
| 	@$(kecho) "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'" | ||||
| 	$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig) | ||||
| else | ||||
| 	@echo "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'" | ||||
| 	$< --defconfig=$(KBUILD_DEFCONFIG) $(Kconfig) | ||||
| 	@$(kecho) "*** Default configuration is based on target '$(KBUILD_DEFCONFIG)'" | ||||
| 	$(Q)$(MAKE) -f $(srctree)/Makefile $(KBUILD_DEFCONFIG) | ||||
| endif | ||||
|  | ||||
| olddefconfig: $(objk)/conf | ||||
| 	$< --olddefconfig $(Kconfig) | ||||
| %_defconfig: $(obj)/conf | ||||
| 	$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig) | ||||
|  | ||||
| %_defconfig: $(objk)/conf | ||||
| 	$< --defconfig=configs/$@ $(Kconfig) | ||||
| configfiles=$(wildcard $(srctree)/kernel/configs/$@ $(srctree)/arch/$(SRCARCH)/configs/$@) | ||||
|  | ||||
| %.config: $(obj)/conf | ||||
| 	$(if $(call configfiles),, $(error No configuration exists for this target on this architecture)) | ||||
| 	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(configfiles) | ||||
| 	$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig | ||||
|  | ||||
| PHONY += tinyconfig | ||||
| tinyconfig: | ||||
| 	$(Q)KCONFIG_ALLCONFIG=kernel/configs/tiny-base.config $(MAKE) -f $(srctree)/Makefile allnoconfig | ||||
| 	$(Q)$(MAKE) -f $(srctree)/Makefile tiny.config | ||||
|  | ||||
| # CHECK: -o cache_dir=<path> working? | ||||
| PHONY += testconfig | ||||
| testconfig: $(obj)/conf | ||||
| 	$(Q)$(PYTHON3) -B -m pytest $(srctree)/$(src)/tests \ | ||||
| 	-o cache_dir=$(abspath $(obj)/tests/.cache) \ | ||||
| 	$(if $(findstring 1,$(KBUILD_VERBOSE)),--capture=no) | ||||
| clean-files += tests/.cache | ||||
|  | ||||
| # Help text used by make help | ||||
| help_kconfig help:: | ||||
| 	@echo  '*** Kconfig Targets ***' | ||||
| help: | ||||
| 	@echo  '  config	  - Update current config utilising a line-oriented program' | ||||
| 	@echo  '  nconfig         - Update current config utilising a ncurses menu based program' | ||||
| 	@echo  '  menuconfig	  - Update current config utilising a menu based program' | ||||
| 	@echo  '  xconfig	  - Update current config utilising a QT based front-end' | ||||
| 	@echo  '  gconfig	  - Update current config utilising a GTK based front-end' | ||||
| 	@echo  '  xconfig	  - Update current config utilising a Qt based front-end' | ||||
| 	@echo  '  gconfig	  - Update current config utilising a GTK+ based front-end' | ||||
| 	@echo  '  oldconfig	  - Update current config utilising a provided .config as base' | ||||
| 	@echo  '  olddefconfig    - Same as oldconfig, but with default answer to all new options' | ||||
| 	#@echo  '  localmodconfig  - Update current config disabling modules not loaded' | ||||
| 	#@echo  '  localyesconfig  - Update current config converting local mods to core' | ||||
| 	@echo  '  silentoldconfig - Same as oldconfig, but quietly, additionally update deps' | ||||
| 	@echo  '  defconfig	  - New config with default answer to all options' | ||||
| 	@echo  '  localmodconfig  - Update current config disabling modules not loaded' | ||||
| 	@echo  '                    except those preserved by LMC_KEEP environment variable' | ||||
| 	@echo  '  localyesconfig  - Update current config converting local mods to core' | ||||
| 	@echo  '                    except those preserved by LMC_KEEP environment variable' | ||||
| 	@echo  '  defconfig	  - New config with default from ARCH supplied defconfig' | ||||
| 	@echo  '  savedefconfig   - Save current config as ./defconfig (minimal config)' | ||||
| 	#@echo  '  allnoconfig	  - New config where all options are answered with no' | ||||
| 	#@echo  '  allyesconfig	  - New config where all options are accepted with yes' | ||||
| 	#@echo  '  allmodconfig	  - New config selecting modules when possible' | ||||
| 	#@echo  '  randconfig	  - New config with random answer to all options' | ||||
| 	@echo | ||||
|  | ||||
| # lxdialog stuff | ||||
| check-lxdialog  := $(srck)/lxdialog/check-lxdialog.sh | ||||
|  | ||||
| # Use recursively expanded variables so we do not call gcc unless | ||||
| # we really need to do so. (Do not call gcc as part of make mrproper) | ||||
| HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \ | ||||
|                     -DLOCALE | ||||
| HOST_LOADLIBES   = $(shell $(CONFIG_SHELL) $(check-lxdialog) \ | ||||
|                     -ldflags $(HOSTCC)) -ltinfo | ||||
|  | ||||
| 	@echo  '  allnoconfig	  - New config where all options are answered with no' | ||||
| 	@echo  '  allyesconfig	  - New config where all options are accepted with yes' | ||||
| 	@echo  '  allmodconfig	  - New config selecting modules when possible' | ||||
| 	@echo  '  alldefconfig    - New config with all symbols set to default' | ||||
| 	@echo  '  randconfig	  - New config with random answer to all options' | ||||
| 	@echo  '  yes2modconfig	  - Change answers from yes to mod if possible' | ||||
| 	@echo  '  mod2yesconfig	  - Change answers from mod to yes if possible' | ||||
| 	@echo  '  listnewconfig   - List new options' | ||||
| 	@echo  '  helpnewconfig   - List new options and help text' | ||||
| 	@echo  '  olddefconfig	  - Same as oldconfig but sets new symbols to their' | ||||
| 	@echo  '                    default value without prompting' | ||||
| 	@echo  '  tinyconfig	  - Configure the tiniest possible kernel' | ||||
| 	@echo  '  testconfig	  - Run Kconfig unit tests (requires python3 and pytest)' | ||||
|  | ||||
| # =========================================================================== | ||||
| # Shared Makefile for the various kconfig executables: | ||||
| # conf:	  Used for defconfig, oldconfig and related targets | ||||
| # nconf:  Used for the nconfig target. | ||||
| #         Utilizes ncurses | ||||
| # mconf:  Used for the menuconfig target | ||||
| #         Utilizes the lxdialog package | ||||
| # qconf:  Used for the xconfig target | ||||
| #         Based on QT which needs to be installed to compile it | ||||
| # gconf:  Used for the gconfig target | ||||
| #         Based on GTK which needs to be installed to compile it | ||||
| # object files used by all kconfig flavours | ||||
| common-objs	:= confdata.o expr.o lexer.lex.o menu.o parser.tab.o \ | ||||
| 		   preprocess.o symbol.o util.o | ||||
|  | ||||
| lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o | ||||
| lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o | ||||
| $(obj)/lexer.lex.o: $(obj)/parser.tab.h | ||||
| HOSTCFLAGS_lexer.lex.o	:= -I $(srctree)/$(src) | ||||
| HOSTCFLAGS_parser.tab.o	:= -I $(srctree)/$(src) | ||||
|  | ||||
| conf-objs	:= conf.o  zconf.tab.o $(regex-objs) | ||||
| mconf-objs     := mconf.o zconf.tab.o $(lxdialog) $(regex-objs) | ||||
| nconf-objs     := nconf.o zconf.tab.o nconf.gui.o | ||||
| kxgettext-objs	:= kxgettext.o zconf.tab.o | ||||
| qconf-cxxobjs	:= qconf.o | ||||
| qconf-objs	:= zconf.tab.o | ||||
| gconf-objs	:= gconf.o zconf.tab.o | ||||
| # conf: Used for defconfig, oldconfig and related targets | ||||
| hostprogs	+= conf | ||||
| conf-objs	:= conf.o $(common-objs) | ||||
|  | ||||
| hostprogs-y := conf | ||||
| # nconf: Used for the nconfig target based on ncurses | ||||
| hostprogs	+= nconf | ||||
| nconf-objs	:= nconf.o nconf.gui.o $(common-objs) | ||||
|  | ||||
| ifeq ($(MAKECMDGOALS),nconfig) | ||||
| 	hostprogs-y += nconf | ||||
| endif | ||||
| HOSTLDLIBS_nconf	= $(shell . $(obj)/nconf-cfg && echo $$libs) | ||||
| HOSTCFLAGS_nconf.o	= $(shell . $(obj)/nconf-cfg && echo $$cflags) | ||||
| HOSTCFLAGS_nconf.gui.o	= $(shell . $(obj)/nconf-cfg && echo $$cflags) | ||||
|  | ||||
| ifeq ($(MAKECMDGOALS),menuconfig) | ||||
| 	hostprogs-y += mconf | ||||
| endif | ||||
| $(obj)/nconf.o $(obj)/nconf.gui.o: $(obj)/nconf-cfg | ||||
|  | ||||
| ifeq ($(MAKECMDGOALS),update-po-config) | ||||
| 	hostprogs-y += kxgettext | ||||
| endif | ||||
| # mconf: Used for the menuconfig target based on lxdialog | ||||
| hostprogs	+= mconf | ||||
| lxdialog	:= $(addprefix lxdialog/, \ | ||||
| 		     checklist.o inputbox.o menubox.o textbox.o util.o yesno.o) | ||||
| mconf-objs	:= mconf.o $(lxdialog) $(common-objs) | ||||
|  | ||||
| ifeq ($(MAKECMDGOALS),xconfig) | ||||
| 	qconf-target := 1 | ||||
| endif | ||||
| ifeq ($(MAKECMDGOALS),gconfig) | ||||
| 	gconf-target := 1 | ||||
| endif | ||||
| HOSTLDLIBS_mconf = $(shell . $(obj)/mconf-cfg && echo $$libs) | ||||
| $(foreach f, mconf.o $(lxdialog), \ | ||||
|   $(eval HOSTCFLAGS_$f = $$(shell . $(obj)/mconf-cfg && echo $$$$cflags))) | ||||
|  | ||||
| $(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/mconf-cfg | ||||
|  | ||||
| ifeq ($(qconf-target),1) | ||||
| 	hostprogs-y += qconf | ||||
| endif | ||||
| # qconf: Used for the xconfig target based on Qt | ||||
| hostprogs	+= qconf | ||||
| qconf-cxxobjs	:= qconf.o qconf-moc.o | ||||
| qconf-objs	:= images.o $(common-objs) | ||||
|  | ||||
| ifeq ($(gconf-target),1) | ||||
| 	hostprogs-y += gconf | ||||
| endif | ||||
| HOSTLDLIBS_qconf	= $(shell . $(obj)/qconf-cfg && echo $$libs) | ||||
| HOSTCXXFLAGS_qconf.o	= $(shell . $(obj)/qconf-cfg && echo $$cflags) | ||||
| HOSTCXXFLAGS_qconf-moc.o = $(shell . $(obj)/qconf-cfg && echo $$cflags) | ||||
|  | ||||
| clean-files	:= qconf.moc .tmp_qtcheck .tmp_gtkcheck | ||||
| clean-files	+= zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h | ||||
| clean-files     += mconf qconf gconf nconf | ||||
| clean-files     += config.pot linux.pot | ||||
| $(obj)/qconf.o: $(obj)/qconf-cfg | ||||
|  | ||||
| # Check that we have the required ncurses stuff installed for lxdialog (menuconfig) | ||||
| PHONY += $(objk)/dochecklxdialog | ||||
| $(addprefix $(obj)/,$(lxdialog)): $(objk)/dochecklxdialog | ||||
| $(objk)/dochecklxdialog: | ||||
| 	$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOST_LOADLIBES) | ||||
| quiet_cmd_moc = MOC     $@ | ||||
|       cmd_moc = $(shell . $(obj)/qconf-cfg && echo $$moc) $< -o $@ | ||||
|  | ||||
| always := dochecklxdialog | ||||
| $(obj)/qconf-moc.cc: $(src)/qconf.h $(obj)/qconf-cfg FORCE | ||||
| 	$(call if_changed,moc) | ||||
|  | ||||
| # Add environment specific flags | ||||
| HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srck)/check.sh $(HOSTCC) $(HOSTCFLAGS)) | ||||
| targets += qconf-moc.cc | ||||
|  | ||||
| # generated files seem to need this to find local include files | ||||
| HOSTCFLAGS_zconf.lex.o	:= -I$(src) | ||||
| HOSTCFLAGS_zconf.tab.o	:= -I$(src) | ||||
| # gconf: Used for the gconfig target based on GTK+ | ||||
| hostprogs	+= gconf | ||||
| gconf-objs	:= gconf.o images.o $(common-objs) | ||||
|  | ||||
| LEX_PREFIX_zconf	:= zconf | ||||
| YACC_PREFIX_zconf	:= zconf | ||||
| HOSTLDLIBS_gconf    = $(shell . $(obj)/gconf-cfg && echo $$libs) | ||||
| HOSTCFLAGS_gconf.o  = $(shell . $(obj)/gconf-cfg && echo $$cflags) | ||||
|  | ||||
| HOSTLOADLIBES_qconf	= $(KC_QT_LIBS) -ldl | ||||
| HOSTCXXFLAGS_qconf.o	= $(KC_QT_CFLAGS) | ||||
| $(obj)/gconf.o: $(obj)/gconf-cfg | ||||
|  | ||||
| HOSTLOADLIBES_gconf	= `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` | ||||
| HOSTCFLAGS_gconf.o	= `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \ | ||||
|                           -Wno-missing-prototypes | ||||
| # check if necessary packages are available, and configure build flags | ||||
| filechk_conf_cfg = $(CONFIG_SHELL) $< | ||||
|  | ||||
| HOSTLOADLIBES_mconf   = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) | ||||
| $(obj)/%conf-cfg: $(src)/%conf-cfg.sh FORCE | ||||
| 	$(call filechk,conf_cfg) | ||||
|  | ||||
| HOSTLOADLIBES_nconf	= $(shell \ | ||||
| 				pkg-config --libs menu panel ncurses 2>/dev/null \ | ||||
| 				|| echo "-lmenu -lpanel -lncurses"  ) | ||||
|  | ||||
| $(objk)/qconf.o: $(objk)/.tmp_qtcheck | ||||
|  | ||||
| ifeq ($(qconf-target),1) | ||||
| $(objk)/.tmp_qtcheck: $(srck)/Makefile | ||||
| -include $(objk)/.tmp_qtcheck | ||||
|  | ||||
| # QT needs some extra effort... | ||||
| $(objk)/.tmp_qtcheck: | ||||
| 	@set -e; echo "  CHECK   qt"; dir=""; pkg=""; \ | ||||
| 	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 | ||||
|  | ||||
| $(objk)/gconf.o: $(objk)/.tmp_gtkcheck | ||||
|  | ||||
| ifeq ($(gconf-target),1) | ||||
| -include $(objk)/.tmp_gtkcheck | ||||
|  | ||||
| # GTK needs some extra effort, too... | ||||
| $(objk)/.tmp_gtkcheck: | ||||
| 	@if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then		\ | ||||
| 		if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then			\ | ||||
| 			touch $@;								\ | ||||
| 		else									\ | ||||
| 			echo >&2 "*"; 							\ | ||||
| 			echo >&2 "* GTK+ is present but version >= 2.0.0 is required.";	\ | ||||
| 			echo >&2 "*";							\ | ||||
| 			false;								\ | ||||
| 		fi									\ | ||||
| 	else										\ | ||||
| 		echo >&2 "*"; 								\ | ||||
| 		echo >&2 "* Unable to find the GTK+ installation. Please make sure that"; 	\ | ||||
| 		echo >&2 "* the GTK+ 2.0 development package is correctly installed..."; 	\ | ||||
| 		echo >&2 "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; 		\ | ||||
| 		echo >&2 "*"; 								\ | ||||
| 		false;									\ | ||||
| 	fi | ||||
| endif | ||||
|  | ||||
| # --- UNUSED, ignore ---------------------------------------------------------- | ||||
| ifdef UNUSED | ||||
| $(obj)/zconf.tab.o: $(obj)/zconf.lex.c $(obj)/zconf.hash.c | ||||
|  | ||||
| $(obj)/qconf.o: $(obj)/qconf.moc $(obj)/lkc_defs.h | ||||
|  | ||||
| $(obj)/gconf.o: $(obj)/lkc_defs.h | ||||
|  | ||||
| $(obj)/%.moc: $(srck)/%.h | ||||
| 	$(KC_QT_MOC) -i $< -o $@ | ||||
|  | ||||
| $(obj)/lkc_defs.h: $(src)/lkc_proto.h | ||||
| 	sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/' | ||||
|  | ||||
| # Extract gconf menu items for I18N support | ||||
| $(obj)/gconf.glade.h: $(obj)/gconf.glade | ||||
| 	intltool-extract --type=gettext/glade $(obj)/gconf.glade | ||||
| endif | ||||
| # --- UNUSED, ignore ---------------------------------------------------------- | ||||
|  | ||||
| ### | ||||
| # The following requires flex/bison/gperf | ||||
| # By default we use the _shipped versions, uncomment the following line if | ||||
| # you are modifying the flex/bison src. | ||||
| # LKC_GENPARSER := 1 | ||||
|  | ||||
| ifdef LKC_GENPARSER | ||||
|  | ||||
| # --- UNUSED, ignore ---------------------------------------------------------- | ||||
| $(obj)/zconf.tab.c: $(src)/zconf.y | ||||
| $(obj)/zconf.lex.c: $(src)/zconf.l | ||||
| $(obj)/zconf.hash.c: $(src)/zconf.gperf | ||||
|  | ||||
| %.tab.c: %.y | ||||
| 	bison -t -l -b $* -p $(notdir $*) $< | ||||
|  | ||||
| %.tab.c_shipped: %.tab.c | ||||
| 	cp $< $@ | ||||
|  | ||||
| %.lex.c: %.l | ||||
| 	flex -L -P$(notdir $*) -o$@ $< | ||||
|  | ||||
| %.lex.c_shipped: %.lex.c | ||||
| 	cp $< $@ | ||||
|  | ||||
| %.hash.c: %.gperf | ||||
| 	gperf < $< > $@ | ||||
| 	cp $@ $@_shipped | ||||
| # --- UNUSED, ignore ---------------------------------------------------------- | ||||
|  | ||||
| endif | ||||
|  | ||||
| $(objk)/qconf: $(patsubst %,$(objk)/%,$(qconf-cxxobjs)) \ | ||||
| 	       $(patsubst %,$(objk)/%,$(qconf-objs)) | ||||
| 	$(HOSTCXX) $(HOSTCXXFLAGS) -o $@ $^ $(HOSTLOADLIBES_qconf) | ||||
| $(objk)/gconf: $(patsubst %,$(objk)/%,$(gconf-objs)) | ||||
| 	$(HOSTCC) $(HOSTCFLAGS) -o $@ $^ $(HOSTLOADLIBES_gconf) | ||||
| $(objk)/mconf: $(patsubst %,$(objk)/%,$(mconf-objs)) | ||||
| 	$(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) $^ -o $@ $(HOST_LOADLIBES) | ||||
| $(objk)/nconf: $(patsubst %,$(objk)/%,$(nconf-objs)) | ||||
| 	$(HOSTCC) $(HOSTCFLAGS) -o $@ $^ $(HOSTLOADLIBES_nconf) | ||||
| $(objk)/conf: $(patsubst %,$(objk)/%,$(conf-objs)) | ||||
| 	$(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) -o $@ $^ | ||||
|  | ||||
| $(objk)/mconf.o: $(srck)/mconf.c | ||||
| 	$(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) -c -o $@ $< | ||||
| $(objk)/nconf.o: $(srck)/nconf.c | ||||
| 	$(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) -c -o $@ $< | ||||
| $(objk)/nconf.gui.o: $(srck)/nconf.gui.c | ||||
| 	$(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) -c -o $@ $< | ||||
| $(objk)/conf.o: $(srck)/conf.c | ||||
| 	$(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) -c -o $@ $< | ||||
|  | ||||
| $(objk)/zconf.tab.o: $(objk)/zconf.tab.c $(objk)/zconf.lex.c \ | ||||
| 		     $(objk)/zconf.hash.c | ||||
| 	$(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) -c -o $@ $(objk)/zconf.tab.c | ||||
| $(objk)/qconf.o: $(srck)/qconf.cc $(objk)/qconf.moc $(objk)/lkc_defs.h | ||||
| 	$(HOSTCXX) $(HOSTCXXFLAGS) $(HOSTCXXFLAGS_qconf.o) -c -o $@ $< | ||||
| $(objk)/gconf.o: $(srck)/gconf.c $(objk)/lkc_defs.h | ||||
| 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTCFLAGS_gconf.o) -c -o $@ $< | ||||
| $(objk)/%.moc: $(srck)/%.h | ||||
| 	$(KC_QT_MOC) -i $< -o $@ | ||||
| $(objk)/lkc_defs.h: $(srck)/lkc_proto.h | ||||
| 	sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/' | ||||
|  | ||||
| $(objk)/zconf.lex.c: $(srck)/zconf.lex.c_shipped | ||||
| 	cp $< $@ | ||||
| $(objk)/zconf.hash.c: $(srck)/zconf.hash.c_shipped | ||||
| 	cp $< $@ | ||||
| $(objk)/zconf.tab.c: $(srck)/zconf.tab.c_shipped | ||||
| 	cp $< $@ | ||||
|  | ||||
| $(objk)/lxdialog/lxdialog: $(objk)/dochecklxdialog \ | ||||
| 			   $(patsubst %,$(objk)/lxdialog/%,$(lxdialog)) | ||||
| 	$(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) \ | ||||
| 		$(patsubst %,$(objk)/lxdialog/%,$(lxdialog)) $(HOST_LOADLIBES) -o $@ | ||||
| $(objk)/lxdialog/%.o: $(srck)/lxdialog/%.c | ||||
| 	$(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) $^ -c -o $@ | ||||
|  | ||||
| $(objk)/%.o: HOSTCFLAGS+=-I$(srck) -I$(objk) | ||||
| $(objk)/%.o: HOSTCXXFLAGS+=-I$(srck) -I$(objk) | ||||
| clean-files += *conf-cfg | ||||
|   | ||||
| @@ -1,12 +1,69 @@ | ||||
| # SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| # Early configuration of coreboot specific changes | ||||
| Kconfig ?= src/Kconfig | ||||
| # Early coreboot specific configuration | ||||
| KBUILD_KCONFIG ?= src/Kconfig | ||||
|  | ||||
| # Include verbatim Makefile | ||||
| include $(dir $(lastword $(MAKEFILE_LIST)))Makefile | ||||
| export LC_ALL=C | ||||
| export LANG=C | ||||
|  | ||||
| # Extend Linux kconfig build rules | ||||
| # Include original Makefile, with just enough edits to work for us | ||||
| $(objk)/Makefile.real: $(dir $(lastword $(MAKEFILE_LIST)))Makefile | ||||
| 	mkdir -p $(objk) | ||||
| 	sed \ | ||||
| 		-e "s,\$$(obj),\$$(objk),g" \ | ||||
| 		-e "s,\$$(src),\$$(srck),g" \ | ||||
| 		-e "s,^help:,help_kconfig help::," \ | ||||
| 		-e "s,^%.config:,__disable__&," \ | ||||
| 		-e "s,^savedefconfig:,__disable__&," \ | ||||
| 		-e "s,\$$(srctree)/arch/\$$(SRCARCH)/configs/\$$(KBUILD_DEFCONFIG),\$$(KBUILD_DEFCONFIG)," \ | ||||
| 		-e "s,--defconfig=arch/\$$(SRCARCH)/configs/\$$(KBUILD_DEFCONFIG),--defconfig=\$$(KBUILD_DEFCONFIG)," \ | ||||
| 		-e "/^unexport CONFIG_$$/d" \ | ||||
| 		$< > $@.tmp | ||||
| 	mv $@.tmp $@ | ||||
|  | ||||
| kecho := echo | ||||
|  | ||||
| -include $(objk)/Makefile.real | ||||
|  | ||||
| # Fill in Linux kconfig build rules to work | ||||
|  | ||||
| oldconfig: KCONFIG_STRICT= | ||||
|  | ||||
| savedefconfig: $(objk)/conf | ||||
| 	cp $(DOTCONFIG) $(DEFCONFIG) | ||||
| 	$< --savedefconfig=$(DEFCONFIG) $(KBUILD_KCONFIG) | ||||
|  | ||||
| FORCE: | ||||
|  | ||||
| filechk=$< > $@ | ||||
|  | ||||
| $(objk)/%.o: $(srck)/%.c | ||||
| 	$(HOSTCC) -I $(srck) -I $(objk) -c $(HOSTCFLAGS_$(notdir $@)) -o $@ $< | ||||
|  | ||||
| $(objk)/%.o: $(srck)/%.cc | ||||
| 	$(HOSTCXX) -I $(srck) -I $(objk) -c $(HOSTCXXFLAGS_$(notdir $@)) -o $@ $< | ||||
|  | ||||
| $(objk)/%.o: $(objk)/%.c | ||||
| 	$(HOSTCC) -I $(srck) -I $(objk) -c -o $@ $< | ||||
|  | ||||
| $(objk)/%.moc: $(srck)/%.h | $(objk)/qconf-cfg | ||||
| 	$(call cmd_moc) | ||||
|  | ||||
| define hostprogs_template | ||||
| # $1 entry in hostprogs | ||||
| $(objk)/$(1): $$(foreach _o,$$($(1)-objs) $$($(1)-cxxobjs),$(objk)/$$(_o)) | $(wildcard $(objk)/$(1)-cfg) | ||||
| 	$$(HOSTCXX) -o $$@ $$^ $$(HOSTLDLIBS_$(1)) | ||||
| endef | ||||
|  | ||||
| $(foreach prog,$(hostprogs),$(eval $(call hostprogs_template,$(prog)))) | ||||
|  | ||||
| $(objk)/parser.tab.h: | $(objk)/parser.tab.c | ||||
| $(objk)/%.tab.h: | $(objk)/%.tab.c | ||||
| $(objk)/%.tab.c: $(srck)/%.y | ||||
| 	bison -t -l --defines=$(objk)/$*.tab.h -b $(objk)/$* $< | ||||
|  | ||||
| $(objk)/%.lex.c: $(srck)/%.l | ||||
| 	flex -L -o$@ $< | ||||
|  | ||||
| # Support mingw by shipping our own regex implementation | ||||
| _OS=$(shell uname -s |cut -c-7) | ||||
|   | ||||
| @@ -1,12 +0,0 @@ | ||||
| scripts/kconfig/lxdialog/checklist.c | ||||
| scripts/kconfig/lxdialog/inputbox.c | ||||
| scripts/kconfig/lxdialog/menubox.c | ||||
| scripts/kconfig/lxdialog/textbox.c | ||||
| scripts/kconfig/lxdialog/util.c | ||||
| scripts/kconfig/lxdialog/yesno.c | ||||
| scripts/kconfig/mconf.c | ||||
| scripts/kconfig/conf.c | ||||
| scripts/kconfig/confdata.c | ||||
| scripts/kconfig/gconf.c | ||||
| scripts/kconfig/gconf.glade.h | ||||
| scripts/kconfig/qconf.cc | ||||
| @@ -1,13 +0,0 @@ | ||||
| #!/usr/bin/env sh | ||||
| # Needed for systems without gettext | ||||
| $* -x c -o /dev/null - > /dev/null 2>&1 << EOF | ||||
| #include <libintl.h> | ||||
| int main() | ||||
| { | ||||
| 	gettext(""); | ||||
| 	return 0; | ||||
| } | ||||
| EOF | ||||
| if [ ! "$?" -eq "0"  ]; then | ||||
| 	echo -DKBUILD_NO_NLS; | ||||
| fi | ||||
| @@ -1,17 +1,16 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * 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 <limits.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <time.h> | ||||
| #include <unistd.h> | ||||
| #include <getopt.h> | ||||
| #include <sys/stat.h> | ||||
| #include <sys/time.h> | ||||
| #include <errno.h> | ||||
|  | ||||
| @@ -21,11 +20,10 @@ int kconfig_warnings = 0; | ||||
|  | ||||
| static void conf(struct menu *menu); | ||||
| static void check_conf(struct menu *menu); | ||||
| static void xfgets(char *str, int size, FILE *in); | ||||
|  | ||||
| enum input_mode { | ||||
| 	oldaskconfig, | ||||
| 	silentoldconfig, | ||||
| 	syncconfig, | ||||
| 	oldconfig, | ||||
| 	allnoconfig, | ||||
| 	allyesconfig, | ||||
| @@ -35,15 +33,18 @@ enum input_mode { | ||||
| 	defconfig, | ||||
| 	savedefconfig, | ||||
| 	listnewconfig, | ||||
| 	helpnewconfig, | ||||
| 	olddefconfig, | ||||
| } input_mode = oldaskconfig; | ||||
|  | ||||
| 	yes2modconfig, | ||||
| 	mod2yesconfig, | ||||
| }; | ||||
| static enum input_mode input_mode = oldaskconfig; | ||||
| static int input_mode_opt; | ||||
| static int indent = 1; | ||||
| static int tty_stdio; | ||||
| static int valid_stdin = 1; | ||||
| static int sync_kconfig; | ||||
| static int conf_cnt; | ||||
| static char line[128]; | ||||
| static char line[PATH_MAX]; | ||||
| static struct menu *rootEntry; | ||||
|  | ||||
| static void print_help(struct menu *menu) | ||||
| @@ -73,27 +74,260 @@ static void strip(char *str) | ||||
| 		*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) { | ||||
| 		printf(_("aborted!\n\n")); | ||||
| 		printf(_("Console input/output is redirected. ")); | ||||
| 		printf(_("Run 'make oldconfig' to update configuration.\n\n")); | ||||
| 		exit(1); | ||||
| 	if (!fgets(str, size, in)) | ||||
| 		fprintf(stderr, "\nError in reading or end of file.\n"); | ||||
|  | ||||
| 	if (!tty_stdio) | ||||
| 		printf("%s", str); | ||||
| } | ||||
|  | ||||
| static void set_randconfig_seed(void) | ||||
| { | ||||
| 	unsigned int seed; | ||||
| 	char *env; | ||||
| 	bool seed_set = false; | ||||
|  | ||||
| 	env = getenv("KCONFIG_SEED"); | ||||
| 	if (env && *env) { | ||||
| 		char *endp; | ||||
|  | ||||
| 		seed = strtol(env, &endp, 0); | ||||
| 		if (*endp == '\0') | ||||
| 			seed_set = true; | ||||
| 	} | ||||
|  | ||||
| 	if (!seed_set) { | ||||
| 		struct timeval now; | ||||
|  | ||||
| 		/* | ||||
| 		 * Use microseconds derived seed, compensate for systems where it may | ||||
| 		 * be zero. | ||||
| 		 */ | ||||
| 		gettimeofday(&now, NULL); | ||||
| 		seed = (now.tv_sec + 1) * (now.tv_usec + 1); | ||||
| 	} | ||||
|  | ||||
| 	printf("KCONFIG_SEED=0x%X\n", seed); | ||||
| 	srand(seed); | ||||
| } | ||||
|  | ||||
| static bool randomize_choice_values(struct symbol *csym) | ||||
| { | ||||
| 	struct property *prop; | ||||
| 	struct symbol *sym; | ||||
| 	struct expr *e; | ||||
| 	int cnt, def; | ||||
|  | ||||
| 	/* | ||||
| 	 * If choice is mod then we may have more items selected | ||||
| 	 * and if no then no-one. | ||||
| 	 * In both cases stop. | ||||
| 	 */ | ||||
| 	if (csym->curr.tri != yes) | ||||
| 		return false; | ||||
|  | ||||
| 	prop = sym_get_choice_prop(csym); | ||||
|  | ||||
| 	/* count entries in choice block */ | ||||
| 	cnt = 0; | ||||
| 	expr_list_for_each_sym(prop->expr, e, sym) | ||||
| 		cnt++; | ||||
|  | ||||
| 	/* | ||||
| 	 * find a random value and set it to yes, | ||||
| 	 * set the rest to no so we have only one set | ||||
| 	 */ | ||||
| 	def = rand() % cnt; | ||||
|  | ||||
| 	cnt = 0; | ||||
| 	expr_list_for_each_sym(prop->expr, e, sym) { | ||||
| 		if (def == cnt++) { | ||||
| 			sym->def[S_DEF_USER].tri = yes; | ||||
| 			csym->def[S_DEF_USER].val = sym; | ||||
| 		} else { | ||||
| 			sym->def[S_DEF_USER].tri = no; | ||||
| 		} | ||||
| 		sym->flags |= SYMBOL_DEF_USER; | ||||
| 		/* clear VALID to get value calculated */ | ||||
| 		sym->flags &= ~SYMBOL_VALID; | ||||
| 	} | ||||
| 	csym->flags |= SYMBOL_DEF_USER; | ||||
| 	/* clear VALID to get value calculated */ | ||||
| 	csym->flags &= ~SYMBOL_VALID; | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| enum conf_def_mode { | ||||
| 	def_default, | ||||
| 	def_yes, | ||||
| 	def_mod, | ||||
| 	def_y2m, | ||||
| 	def_m2y, | ||||
| 	def_no, | ||||
| 	def_random | ||||
| }; | ||||
|  | ||||
| static bool conf_set_all_new_symbols(enum conf_def_mode mode) | ||||
| { | ||||
| 	struct symbol *sym, *csym; | ||||
| 	int i, cnt; | ||||
| 	/* | ||||
| 	 * can't go as the default in switch-case below, otherwise gcc whines | ||||
| 	 * about -Wmaybe-uninitialized | ||||
| 	 */ | ||||
| 	int pby = 50; /* probability of bool     = y */ | ||||
| 	int pty = 33; /* probability of tristate = y */ | ||||
| 	int ptm = 33; /* probability of tristate = m */ | ||||
| 	bool has_changed = false; | ||||
|  | ||||
| 	if (mode == def_random) { | ||||
| 		int n, p[3]; | ||||
| 		char *env = getenv("KCONFIG_PROBABILITY"); | ||||
|  | ||||
| 		n = 0; | ||||
| 		while (env && *env) { | ||||
| 			char *endp; | ||||
| 			int tmp = strtol(env, &endp, 10); | ||||
|  | ||||
| 			if (tmp >= 0 && tmp <= 100) { | ||||
| 				p[n++] = tmp; | ||||
| 			} else { | ||||
| 				errno = ERANGE; | ||||
| 				perror("KCONFIG_PROBABILITY"); | ||||
| 				exit(1); | ||||
| 			} | ||||
| 			env = (*endp == ':') ? endp + 1 : endp; | ||||
| 			if (n >= 3) | ||||
| 				break; | ||||
| 		} | ||||
| 		switch (n) { | ||||
| 		case 1: | ||||
| 			pby = p[0]; | ||||
| 			ptm = pby / 2; | ||||
| 			pty = pby - ptm; | ||||
| 			break; | ||||
| 		case 2: | ||||
| 			pty = p[0]; | ||||
| 			ptm = p[1]; | ||||
| 			pby = pty + ptm; | ||||
| 			break; | ||||
| 		case 3: | ||||
| 			pby = p[0]; | ||||
| 			pty = p[1]; | ||||
| 			ptm = p[2]; | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		if (pty + ptm > 100) { | ||||
| 			errno = ERANGE; | ||||
| 			perror("KCONFIG_PROBABILITY"); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for_all_symbols(i, sym) { | ||||
| 		if (sym_has_value(sym) || sym->flags & SYMBOL_VALID) | ||||
| 			continue; | ||||
| 		switch (sym_get_type(sym)) { | ||||
| 		case S_BOOLEAN: | ||||
| 		case S_TRISTATE: | ||||
| 			has_changed = true; | ||||
| 			switch (mode) { | ||||
| 			case def_yes: | ||||
| 				sym->def[S_DEF_USER].tri = yes; | ||||
| 				break; | ||||
| 			case def_mod: | ||||
| 				sym->def[S_DEF_USER].tri = mod; | ||||
| 				break; | ||||
| 			case def_no: | ||||
| 				sym->def[S_DEF_USER].tri = no; | ||||
| 				break; | ||||
| 			case def_random: | ||||
| 				sym->def[S_DEF_USER].tri = no; | ||||
| 				cnt = rand() % 100; | ||||
| 				if (sym->type == S_TRISTATE) { | ||||
| 					if (cnt < pty) | ||||
| 						sym->def[S_DEF_USER].tri = yes; | ||||
| 					else if (cnt < pty + ptm) | ||||
| 						sym->def[S_DEF_USER].tri = mod; | ||||
| 				} else if (cnt < pby) | ||||
| 					sym->def[S_DEF_USER].tri = yes; | ||||
| 				break; | ||||
| 			default: | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (!(sym_is_choice(sym) && mode == def_random)) | ||||
| 				sym->flags |= SYMBOL_DEF_USER; | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	sym_clear_all_valid(); | ||||
|  | ||||
| 	/* | ||||
| 	 * We have different type of choice blocks. | ||||
| 	 * If curr.tri equals to mod then we can select several | ||||
| 	 * choice symbols in one block. | ||||
| 	 * In this case we do nothing. | ||||
| 	 * If curr.tri equals yes then only one symbol can be | ||||
| 	 * selected in a choice block and we set it to yes, | ||||
| 	 * and the rest to no. | ||||
| 	 */ | ||||
| 	if (mode != def_random) { | ||||
| 		for_all_symbols(i, csym) { | ||||
| 			if ((sym_is_choice(csym) && !sym_has_value(csym)) || | ||||
| 			    sym_is_choice_value(csym)) | ||||
| 				csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for_all_symbols(i, csym) { | ||||
| 		if (sym_has_value(csym) || !sym_is_choice(csym)) | ||||
| 			continue; | ||||
|  | ||||
| 		sym_calc_value(csym); | ||||
| 		if (mode == def_random) | ||||
| 			has_changed |= randomize_choice_values(csym); | ||||
| 		else { | ||||
| 			set_all_choice_values(csym); | ||||
| 			has_changed = true; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return has_changed; | ||||
| } | ||||
|  | ||||
| static 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_clear_all_valid(); | ||||
| } | ||||
|  | ||||
| static int conf_askvalue(struct symbol *sym, const char *def) | ||||
| { | ||||
| 	enum symbol_type type = sym_get_type(sym); | ||||
|  | ||||
| 	if (!sym_has_value(sym)) | ||||
| 		printf(_("(NEW) ")); | ||||
| 		printf("(NEW) "); | ||||
|  | ||||
| 	line[0] = '\n'; | ||||
| 	line[1] = 0; | ||||
|  | ||||
| 	if (!sym_is_changable(sym)) { | ||||
| 	if (!sym_is_changeable(sym)) { | ||||
| 		printf("%s\n", def); | ||||
| 		line[0] = '\n'; | ||||
| 		line[1] = 0; | ||||
| @@ -102,33 +336,18 @@ static int conf_askvalue(struct symbol *sym, const char *def) | ||||
|  | ||||
| 	switch (input_mode) { | ||||
| 	case oldconfig: | ||||
| 	case silentoldconfig: | ||||
| 	case syncconfig: | ||||
| 		if (sym_has_value(sym)) { | ||||
| 			printf("%s\n", def); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		check_stdin(); | ||||
| 		/* fall through */ | ||||
| 	case oldaskconfig: | ||||
| 		fflush(stdout); | ||||
| 		xfgets(line, 128, stdin); | ||||
| 		if (!tty_stdio) | ||||
| 			printf("\n"); | ||||
| 		return 1; | ||||
| 	default: | ||||
| 		fflush(stdout); | ||||
| 		xfgets(line, sizeof(line), stdin); | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	switch (type) { | ||||
| 	case S_INT: | ||||
| 	case S_HEX: | ||||
| 	case S_STRING: | ||||
| 		printf("%s\n", def); | ||||
| 		return 1; | ||||
| 	default: | ||||
| 		; | ||||
| 	} | ||||
| 	printf("%s", line); | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| @@ -138,10 +357,10 @@ static int conf_string(struct menu *menu) | ||||
| 	const char *def; | ||||
|  | ||||
| 	while (1) { | ||||
| 		printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); | ||||
| 		printf("%*s%s ", indent - 1, "", menu->prompt->text); | ||||
| 		printf("(%s) ", sym->name); | ||||
| 		def = sym_get_string_value(sym); | ||||
| 		if (sym_get_string_value(sym)) | ||||
| 		if (def) | ||||
| 			printf("[%s] ", def); | ||||
| 		if (!conf_askvalue(sym, def)) | ||||
| 			return 0; | ||||
| @@ -171,7 +390,7 @@ static int conf_sym(struct menu *menu) | ||||
| 	tristate oldval, newval; | ||||
|  | ||||
| 	while (1) { | ||||
| 		printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); | ||||
| 		printf("%*s%s ", indent - 1, "", menu->prompt->text); | ||||
| 		if (sym->name) | ||||
| 			printf("(%s) ", sym->name); | ||||
| 		putchar('['); | ||||
| @@ -193,9 +412,7 @@ static int conf_sym(struct menu *menu) | ||||
| 			printf("/m"); | ||||
| 		if (oldval != yes && sym_tristate_within_range(sym, yes)) | ||||
| 			printf("/y"); | ||||
| 		if (menu_has_help(menu)) | ||||
| 			printf("/?"); | ||||
| 		printf("] "); | ||||
| 		printf("/?] "); | ||||
| 		if (!conf_askvalue(sym, sym_get_string_value(sym))) | ||||
| 			return 0; | ||||
| 		strip(line); | ||||
| @@ -242,7 +459,7 @@ static int conf_choice(struct menu *menu) | ||||
|  | ||||
| 	sym = menu->sym; | ||||
| 	is_new = !sym_has_value(sym); | ||||
| 	if (sym_is_changable(sym)) { | ||||
| 	if (sym_is_changeable(sym)) { | ||||
| 		conf_sym(menu); | ||||
| 		sym_calc_value(sym); | ||||
| 		switch (sym_get_tristate_value(sym)) { | ||||
| @@ -258,7 +475,7 @@ static int conf_choice(struct menu *menu) | ||||
| 		case no: | ||||
| 			return 1; | ||||
| 		case mod: | ||||
| 			printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); | ||||
| 			printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); | ||||
| 			return 0; | ||||
| 		case yes: | ||||
| 			break; | ||||
| @@ -268,7 +485,7 @@ static int conf_choice(struct menu *menu) | ||||
| 	while (1) { | ||||
| 		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); | ||||
| 		cnt = def = 0; | ||||
| 		line[0] = 0; | ||||
| @@ -276,7 +493,7 @@ static int conf_choice(struct menu *menu) | ||||
| 			if (!menu_is_visible(child)) | ||||
| 				continue; | ||||
| 			if (!child->sym) { | ||||
| 				printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); | ||||
| 				printf("%*c %s\n", indent, '*', menu_get_prompt(child)); | ||||
| 				continue; | ||||
| 			} | ||||
| 			cnt++; | ||||
| @@ -285,35 +502,31 @@ static int conf_choice(struct menu *menu) | ||||
| 				printf("%*c", indent, '>'); | ||||
| 			} else | ||||
| 				printf("%*c", indent, ' '); | ||||
| 			printf(" %d. %s", cnt, _(menu_get_prompt(child))); | ||||
| 			printf(" %d. %s", cnt, menu_get_prompt(child)); | ||||
| 			if (child->sym->name) | ||||
| 				printf(" (%s)", child->sym->name); | ||||
| 			if (!sym_has_value(child->sym)) | ||||
| 				printf(_(" (NEW)")); | ||||
| 				printf(" (NEW)"); | ||||
| 			printf("\n"); | ||||
| 		} | ||||
| 		printf(_("%*schoice"), indent - 1, ""); | ||||
| 		printf("%*schoice", indent - 1, ""); | ||||
| 		if (cnt == 1) { | ||||
| 			printf("[1]: 1\n"); | ||||
| 			goto conf_childs; | ||||
| 		} | ||||
| 		printf("[1-%d", cnt); | ||||
| 		if (menu_has_help(menu)) | ||||
| 			printf("?"); | ||||
| 		printf("]: "); | ||||
| 		printf("[1-%d?]: ", cnt); | ||||
| 		switch (input_mode) { | ||||
| 		case oldconfig: | ||||
| 		case silentoldconfig: | ||||
| 		case syncconfig: | ||||
| 			if (!is_new) { | ||||
| 				cnt = def; | ||||
| 				printf("%d\n", cnt); | ||||
| 				break; | ||||
| 			} | ||||
| 			check_stdin(); | ||||
| 			/* fall through */ | ||||
| 		case oldaskconfig: | ||||
| 			fflush(stdout); | ||||
| 			xfgets(line, 128, stdin); | ||||
| 			xfgets(line, sizeof(line), stdin); | ||||
| 			strip(line); | ||||
| 			if (line[0] == '?') { | ||||
| 				print_help(menu); | ||||
| @@ -369,10 +582,11 @@ static void conf(struct menu *menu) | ||||
|  | ||||
| 		switch (prop->type) { | ||||
| 		case P_MENU: | ||||
| 			if ((input_mode == silentoldconfig || | ||||
| 			     input_mode == listnewconfig || | ||||
| 			     input_mode == olddefconfig) && | ||||
| 			    rootEntry != menu) { | ||||
| 			/* | ||||
| 			 * Except in oldaskconfig mode, we show only menus that | ||||
| 			 * contain new symbols. | ||||
| 			 */ | ||||
| 			if (input_mode != oldaskconfig && rootEntry != menu) { | ||||
| 				check_conf(menu); | ||||
| 				return; | ||||
| 			} | ||||
| @@ -382,7 +596,7 @@ static void conf(struct menu *menu) | ||||
| 			if (prompt) | ||||
| 				printf("%*c\n%*c %s\n%*c\n", | ||||
| 					indent, '*', | ||||
| 					indent, '*', _(prompt), | ||||
| 					indent, '*', prompt, | ||||
| 					indent, '*'); | ||||
| 		default: | ||||
| 			; | ||||
| @@ -428,19 +642,37 @@ static void check_conf(struct menu *menu) | ||||
| 		return; | ||||
|  | ||||
| 	sym = menu->sym; | ||||
| 	if (sym && !sym_has_value(sym)) { | ||||
| 		if (sym_is_changable(sym) || | ||||
| 		    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { | ||||
| 			if (input_mode == listnewconfig) { | ||||
| 				if (sym->name && !sym_is_choice_value(sym)) { | ||||
| 					printf("%s%s\n", CONFIG_, sym->name); | ||||
| 	if (sym && !sym_has_value(sym) && | ||||
| 	    (sym_is_changeable(sym) || | ||||
| 	     (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes))) { | ||||
|  | ||||
| 		switch (input_mode) { | ||||
| 		case listnewconfig: | ||||
| 			if (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) { | ||||
| 				if (!conf_cnt++) | ||||
| 					printf(_("*\n* Restart config...\n*\n")); | ||||
| 				rootEntry = menu_get_parent_menu(menu); | ||||
| 				conf(rootEntry); | ||||
| 			} | ||||
| 			break; | ||||
| 		case helpnewconfig: | ||||
| 			printf("-----\n"); | ||||
| 			print_help(menu); | ||||
| 			printf("-----\n"); | ||||
| 			break; | ||||
| 		default: | ||||
| 			if (!conf_cnt++) | ||||
| 				printf("*\n* Restart config...\n*\n"); | ||||
| 			rootEntry = menu_get_parent_menu(menu); | ||||
| 			conf(rootEntry); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -449,38 +681,42 @@ static void check_conf(struct menu *menu) | ||||
| } | ||||
|  | ||||
| static struct option long_opts[] = { | ||||
| 	{"oldaskconfig",    no_argument,       NULL, oldaskconfig}, | ||||
| 	{"oldconfig",       no_argument,       NULL, oldconfig}, | ||||
| 	{"silentoldconfig", no_argument,       NULL, silentoldconfig}, | ||||
| 	{"defconfig",       optional_argument, NULL, defconfig}, | ||||
| 	{"savedefconfig",   required_argument, NULL, savedefconfig}, | ||||
| 	{"allnoconfig",     no_argument,       NULL, allnoconfig}, | ||||
| 	{"allyesconfig",    no_argument,       NULL, allyesconfig}, | ||||
| 	{"allmodconfig",    no_argument,       NULL, allmodconfig}, | ||||
| 	{"alldefconfig",    no_argument,       NULL, alldefconfig}, | ||||
| 	{"randconfig",      no_argument,       NULL, randconfig}, | ||||
| 	{"listnewconfig",   no_argument,       NULL, listnewconfig}, | ||||
| 	{"olddefconfig",    no_argument,       NULL, olddefconfig}, | ||||
| 	/* | ||||
| 	 * oldnoconfig is an alias of olddefconfig, because people already | ||||
| 	 * 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}, | ||||
| 	{"help",          no_argument,       NULL,            'h'}, | ||||
| 	{"silent",        no_argument,       NULL,            's'}, | ||||
| 	{"oldaskconfig",  no_argument,       &input_mode_opt, oldaskconfig}, | ||||
| 	{"oldconfig",     no_argument,       &input_mode_opt, oldconfig}, | ||||
| 	{"syncconfig",    no_argument,       &input_mode_opt, syncconfig}, | ||||
| 	{"defconfig",     required_argument, &input_mode_opt, defconfig}, | ||||
| 	{"savedefconfig", required_argument, &input_mode_opt, savedefconfig}, | ||||
| 	{"allnoconfig",   no_argument,       &input_mode_opt, allnoconfig}, | ||||
| 	{"allyesconfig",  no_argument,       &input_mode_opt, allyesconfig}, | ||||
| 	{"allmodconfig",  no_argument,       &input_mode_opt, allmodconfig}, | ||||
| 	{"alldefconfig",  no_argument,       &input_mode_opt, alldefconfig}, | ||||
| 	{"randconfig",    no_argument,       &input_mode_opt, randconfig}, | ||||
| 	{"listnewconfig", no_argument,       &input_mode_opt, listnewconfig}, | ||||
| 	{"helpnewconfig", no_argument,       &input_mode_opt, helpnewconfig}, | ||||
| 	{"olddefconfig",  no_argument,       &input_mode_opt, olddefconfig}, | ||||
| 	{"yes2modconfig", no_argument,       &input_mode_opt, yes2modconfig}, | ||||
| 	{"mod2yesconfig", no_argument,       &input_mode_opt, mod2yesconfig}, | ||||
| 	{NULL, 0, NULL, 0} | ||||
| }; | ||||
|  | ||||
| static void conf_usage(const char *progname) | ||||
| { | ||||
|  | ||||
| 	printf("Usage: %s [option] <kconfig-file>\n", progname); | ||||
| 	printf("[option] is _one_ of the following:\n"); | ||||
| 	printf("Usage: %s [options] <kconfig-file>\n", progname); | ||||
| 	printf("\n"); | ||||
| 	printf("Generic options:\n"); | ||||
| 	printf("  -h, --help              Print this message and exit.\n"); | ||||
| 	printf("  -s, --silent            Do not print log.\n"); | ||||
| 	printf("\n"); | ||||
| 	printf("Mode 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("  --oldconfig             Update a configuration using a provided .config as base\n"); | ||||
| 	printf("  --silentoldconfig       Same as oldconfig, but quietly, additionally update deps\n"); | ||||
| 	printf("  --olddefconfig          Same as silentoldconfig but sets new symbols to their default value\n"); | ||||
| 	printf("  --oldnoconfig           An alias of olddefconfig\n"); | ||||
| 	printf("  --syncconfig            Similar to oldconfig but generates configuration in\n" | ||||
| 	       "                          include/{generated/,config/}\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("  --savedefconfig <file>  Save the minimal current configuration to <file>\n"); | ||||
| 	printf("  --allnoconfig           New config where all options are answered with no\n"); | ||||
| @@ -488,6 +724,9 @@ static void conf_usage(const char *progname) | ||||
| 	printf("  --allmodconfig          New config where all options are answered with mod\n"); | ||||
| 	printf("  --alldefconfig          New config with all symbols set to default\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"); | ||||
| 	printf("  (If none of the above is given, --oldaskconfig is the default)\n"); | ||||
| } | ||||
|  | ||||
| int main(int ac, char **av) | ||||
| @@ -496,102 +735,73 @@ int main(int ac, char **av) | ||||
| 	int opt; | ||||
| 	const char *name, *defconfig_file = NULL /* gcc uninit */; | ||||
| 	char *env; | ||||
| 	struct stat tmpstat; | ||||
| 	int no_conf_write = 0; | ||||
|  | ||||
| 	setlocale(LC_ALL, ""); | ||||
| 	bindtextdomain(PACKAGE, LOCALEDIR); | ||||
| 	textdomain(PACKAGE); | ||||
| 	tty_stdio = isatty(0) && isatty(1); | ||||
|  | ||||
| 	tty_stdio = isatty(0) && isatty(1) && isatty(2); | ||||
|  | ||||
| 	while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) { | ||||
| 		input_mode = (enum input_mode)opt; | ||||
| 	while ((opt = getopt_long(ac, av, "hs", long_opts, NULL)) != -1) { | ||||
| 		switch (opt) { | ||||
| 		case silentoldconfig: | ||||
| 			sync_kconfig = 1; | ||||
| 			break; | ||||
| 		case defconfig: | ||||
| 		case savedefconfig: | ||||
| 			defconfig_file = optarg; | ||||
| 			break; | ||||
| 		case randconfig: | ||||
| 		{ | ||||
| 			struct timeval now; | ||||
| 			unsigned int seed; | ||||
| 			char *seed_env; | ||||
|  | ||||
| 			/* | ||||
| 			 * Use microseconds derived seed, | ||||
| 			 * compensate for systems where it may be zero | ||||
| 			 */ | ||||
| 			gettimeofday(&now, NULL); | ||||
| 			seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1)); | ||||
|  | ||||
| 			seed_env = getenv("KCONFIG_SEED"); | ||||
| 			if( seed_env && *seed_env ) { | ||||
| 				char *endp; | ||||
| 				int tmp = (int)strtol(seed_env, &endp, 0); | ||||
| 				if (*endp == '\0') { | ||||
| 					seed = tmp; | ||||
| 				} | ||||
| 			} | ||||
| 			fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed ); | ||||
| 			srand(seed); | ||||
| 			break; | ||||
| 		} | ||||
| 		case oldaskconfig: | ||||
| 		case oldconfig: | ||||
| 		case allnoconfig: | ||||
| 		case allyesconfig: | ||||
| 		case allmodconfig: | ||||
| 		case alldefconfig: | ||||
| 		case listnewconfig: | ||||
| 		case olddefconfig: | ||||
| 			break; | ||||
| 		case '?': | ||||
| 		case 'h': | ||||
| 			conf_usage(progname); | ||||
| 			exit(1); | ||||
| 			break; | ||||
| 		case 's': | ||||
| 			conf_set_message_callback(NULL); | ||||
| 			break; | ||||
| 		case 0: | ||||
| 			input_mode = input_mode_opt; | ||||
| 			switch (input_mode) { | ||||
| 			case syncconfig: | ||||
| 				/* | ||||
| 				 * syncconfig is invoked during the build stage. | ||||
| 				 * Suppress distracting | ||||
| 				 *   "configuration written to ..." | ||||
| 				 */ | ||||
| 				conf_set_message_callback(NULL); | ||||
| 				sync_kconfig = 1; | ||||
| 				break; | ||||
| 			case defconfig: | ||||
| 			case savedefconfig: | ||||
| 				defconfig_file = optarg; | ||||
| 				break; | ||||
| 			case randconfig: | ||||
| 				set_randconfig_seed(); | ||||
| 				break; | ||||
| 			default: | ||||
| 				break; | ||||
| 			} | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	if (ac == optind) { | ||||
| 		printf(_("%s: Kconfig file missing\n"), av[0]); | ||||
| 		fprintf(stderr, "%s: Kconfig file missing\n", av[0]); | ||||
| 		conf_usage(progname); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	name = av[optind]; | ||||
| 	conf_parse(name); | ||||
| 	conf_parse(av[optind]); | ||||
| 	//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) { | ||||
| 	case defconfig: | ||||
| 		if (!defconfig_file) | ||||
| 			defconfig_file = conf_get_default_confname(); | ||||
| 		if (conf_read(defconfig_file)) { | ||||
| 			printf(_("***\n" | ||||
| 				"*** Can't find default configuration \"%s\"!\n" | ||||
| 				"***\n"), defconfig_file); | ||||
| 			fprintf(stderr, | ||||
| 				"***\n" | ||||
| 				  "*** Can't find default configuration \"%s\"!\n" | ||||
| 				  "***\n", | ||||
| 				defconfig_file); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 		break; | ||||
| 	case savedefconfig: | ||||
| 	case silentoldconfig: | ||||
| 	case syncconfig: | ||||
| 	case oldaskconfig: | ||||
| 	case oldconfig: | ||||
| 	case listnewconfig: | ||||
| 	case helpnewconfig: | ||||
| 	case olddefconfig: | ||||
| 	case yes2modconfig: | ||||
| 	case mod2yesconfig: | ||||
| 		conf_read(NULL); | ||||
| 		break; | ||||
| 	case allnoconfig: | ||||
| @@ -605,7 +815,7 @@ int main(int ac, char **av) | ||||
| 		if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) { | ||||
| 			if (conf_read_simple(name, S_DEF_USER)) { | ||||
| 				fprintf(stderr, | ||||
| 					_("*** Can't read seed configuration \"%s\"!\n"), | ||||
| 					"*** Can't read seed configuration \"%s\"!\n", | ||||
| 					name); | ||||
| 				exit(1); | ||||
| 			} | ||||
| @@ -622,7 +832,7 @@ int main(int ac, char **av) | ||||
| 		if (conf_read_simple(name, S_DEF_USER) && | ||||
| 		    conf_read_simple("all.config", S_DEF_USER)) { | ||||
| 			fprintf(stderr, | ||||
| 				_("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"), | ||||
| 				"*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n", | ||||
| 				name); | ||||
| 			exit(1); | ||||
| 		} | ||||
| @@ -631,16 +841,23 @@ int main(int ac, char **av) | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	env = getenv("KCONFIG_STRICT"); | ||||
| 	if (env && *env && kconfig_warnings) { | ||||
| 		fprintf(stderr, "\n*** ERROR: %d warnings encountered, and " | ||||
| 			"warnings are errors.\n\n", kconfig_warnings); | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| 	if (sync_kconfig) { | ||||
| 		if (conf_get_changed()) { | ||||
| 			name = getenv("KCONFIG_NOSILENTUPDATE"); | ||||
| 			if (name && *name) { | ||||
| 		name = getenv("KCONFIG_NOSILENTUPDATE"); | ||||
| 		if (name && *name) { | ||||
| 			if (conf_get_changed()) { | ||||
| 				fprintf(stderr, | ||||
| 					_("\n*** The configuration requires explicit update.\n\n")); | ||||
| 					"\n*** The configuration requires explicit update.\n\n"); | ||||
| 				return 1; | ||||
| 			} | ||||
| 			no_conf_write = 1; | ||||
| 		} | ||||
| 		valid_stdin = tty_stdio; | ||||
| 	} | ||||
|  | ||||
| 	switch (input_mode) { | ||||
| @@ -665,64 +882,58 @@ int main(int ac, char **av) | ||||
| 		break; | ||||
| 	case savedefconfig: | ||||
| 		break; | ||||
| 	case yes2modconfig: | ||||
| 		conf_rewrite_mod_or_yes(def_y2m); | ||||
| 		break; | ||||
| 	case mod2yesconfig: | ||||
| 		conf_rewrite_mod_or_yes(def_m2y); | ||||
| 		break; | ||||
| 	case oldaskconfig: | ||||
| 		rootEntry = &rootmenu; | ||||
| 		conf(&rootmenu); | ||||
| 		input_mode = silentoldconfig; | ||||
| 		input_mode = oldconfig; | ||||
| 		/* fall through */ | ||||
| 	case oldconfig: | ||||
| 	case listnewconfig: | ||||
| 	case olddefconfig: | ||||
| 	case silentoldconfig: | ||||
| 	case helpnewconfig: | ||||
| 	case syncconfig: | ||||
| 		/* Update until a loop caused no more changes */ | ||||
| 		do { | ||||
| 			conf_cnt = 0; | ||||
| 			check_conf(&rootmenu); | ||||
| 		} while (conf_cnt && | ||||
| 			 (input_mode != listnewconfig && | ||||
| 			  input_mode != olddefconfig)); | ||||
| 		} while (conf_cnt); | ||||
| 		break; | ||||
| 	case olddefconfig: | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	env = getenv("KCONFIG_STRICT"); | ||||
| 	if (env && *env && kconfig_warnings) { | ||||
| 		fprintf(stderr, _("\n*** ERROR: %d warnings encountered, and " | ||||
| 			"warnings are errors.\n\n"), kconfig_warnings); | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| 	if (sync_kconfig) { | ||||
| 		/* silentoldconfig is used during the build so we shall update autoconf. | ||||
| 		 * All other commands are only used to generate a config. | ||||
| 		 */ | ||||
| 		if (conf_get_changed() && conf_write(NULL)) { | ||||
| 			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 (input_mode == savedefconfig) { | ||||
| 		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); | ||||
| 			return 1; | ||||
| 		} | ||||
| 	} else if (input_mode != listnewconfig) { | ||||
| 		if (conf_write(NULL)) { | ||||
| 			fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); | ||||
| 	} else if (input_mode != listnewconfig && input_mode != helpnewconfig) { | ||||
| 		if (!no_conf_write && conf_write(NULL)) { | ||||
| 			fprintf(stderr, "\n*** Error during writing of the configuration.\n\n"); | ||||
| 			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; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * 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"); | ||||
| } | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,8 +1,10 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * 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 <stdlib.h> | ||||
| #include <string.h> | ||||
| @@ -11,6 +13,8 @@ | ||||
|  | ||||
| #define DEBUG_EXPR	0 | ||||
|  | ||||
| static struct expr *expr_eliminate_yn(struct expr *e); | ||||
|  | ||||
| struct expr *expr_alloc_symbol(struct symbol *sym) | ||||
| { | ||||
| 	struct expr *e = xcalloc(1, sizeof(*e)); | ||||
| @@ -76,6 +80,10 @@ struct expr *expr_copy(const struct expr *org) | ||||
| 		e->left.expr = expr_copy(org->left.expr); | ||||
| 		break; | ||||
| 	case E_EQUAL: | ||||
| 	case E_GEQ: | ||||
| 	case E_GTH: | ||||
| 	case E_LEQ: | ||||
| 	case E_LTH: | ||||
| 	case E_UNEQUAL: | ||||
| 		e->left.sym = org->left.sym; | ||||
| 		e->right.sym = org->right.sym; | ||||
| @@ -87,7 +95,7 @@ struct expr *expr_copy(const struct expr *org) | ||||
| 		e->right.expr = expr_copy(org->right.expr); | ||||
| 		break; | ||||
| 	default: | ||||
| 		printf("can't copy type %d\n", e->type); | ||||
| 		fprintf(stderr, "can't copy type %d\n", e->type); | ||||
| 		free(e); | ||||
| 		e = NULL; | ||||
| 		break; | ||||
| @@ -106,8 +114,12 @@ void expr_free(struct expr *e) | ||||
| 		break; | ||||
| 	case E_NOT: | ||||
| 		expr_free(e->left.expr); | ||||
| 		return; | ||||
| 		break; | ||||
| 	case E_EQUAL: | ||||
| 	case E_GEQ: | ||||
| 	case E_GTH: | ||||
| 	case E_LEQ: | ||||
| 	case E_LTH: | ||||
| 	case E_UNEQUAL: | ||||
| 		break; | ||||
| 	case E_OR: | ||||
| @@ -116,7 +128,7 @@ void expr_free(struct expr *e) | ||||
| 		expr_free(e->right.expr); | ||||
| 		break; | ||||
| 	default: | ||||
| 		printf("how to free type %d?\n", e->type); | ||||
| 		fprintf(stderr, "how to free type %d?\n", e->type); | ||||
| 		break; | ||||
| 	} | ||||
| 	free(e); | ||||
| @@ -127,8 +139,18 @@ static int trans_count; | ||||
| #define e1 (*ep1) | ||||
| #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) | ||||
| { | ||||
| 	/* Recurse down to leaves */ | ||||
|  | ||||
| 	if (e1->type == type) { | ||||
| 		__expr_eliminate_eq(type, &e1->left.expr, &e2); | ||||
| 		__expr_eliminate_eq(type, &e1->right.expr, &e2); | ||||
| @@ -139,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); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	/* e1 and e2 are leaves. Compare them. */ | ||||
|  | ||||
| 	if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && | ||||
| 	    e1->left.sym == e2->left.sym && | ||||
| 	    (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) | ||||
| 		return; | ||||
| 	if (!expr_eq(e1, e2)) | ||||
| 		return; | ||||
|  | ||||
| 	/* e1 and e2 are equal leaves. Prepare them for elimination. */ | ||||
|  | ||||
| 	trans_count++; | ||||
| 	expr_free(e1); expr_free(e2); | ||||
| 	switch (type) { | ||||
| @@ -161,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) | ||||
| { | ||||
| 	if (!e1 || !e2) | ||||
| @@ -186,14 +243,31 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) | ||||
| #undef e1 | ||||
| #undef 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; | ||||
|  | ||||
| 	/* | ||||
| 	 * 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) | ||||
| 		return 0; | ||||
| 	switch (e1->type) { | ||||
| 	case E_EQUAL: | ||||
| 	case E_GEQ: | ||||
| 	case E_GTH: | ||||
| 	case E_LEQ: | ||||
| 	case E_LTH: | ||||
| 	case E_UNEQUAL: | ||||
| 		return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; | ||||
| 	case E_SYMBOL: | ||||
| @@ -228,7 +302,18 @@ int expr_eq(struct expr *e1, struct expr *e2) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| struct expr *expr_eliminate_yn(struct expr *e) | ||||
| /* | ||||
|  * 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) | ||||
| { | ||||
| 	struct expr *tmp; | ||||
|  | ||||
| @@ -501,12 +586,21 @@ static struct expr *expr_join_and(struct expr *e1, struct expr *e2) | ||||
| 	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) | ||||
| { | ||||
| #define e1 (*ep1) | ||||
| #define e2 (*ep2) | ||||
| 	struct expr *tmp; | ||||
|  | ||||
| 	/* Recurse down to leaves */ | ||||
|  | ||||
| 	if (e1->type == type) { | ||||
| 		expr_eliminate_dups1(type, &e1->left.expr, &e2); | ||||
| 		expr_eliminate_dups1(type, &e1->right.expr, &e2); | ||||
| @@ -517,6 +611,9 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct | ||||
| 		expr_eliminate_dups1(type, &e1, &e2->right.expr); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	/* e1 and e2 are leaves. Compare and process them. */ | ||||
|  | ||||
| 	if (e1 == e2) | ||||
| 		return; | ||||
|  | ||||
| @@ -553,62 +650,17 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct | ||||
| #undef e2 | ||||
| } | ||||
|  | ||||
| static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2) | ||||
| { | ||||
| #define e1 (*ep1) | ||||
| #define e2 (*ep2) | ||||
| 	struct expr *tmp, *tmp1, *tmp2; | ||||
|  | ||||
| 	if (e1->type == type) { | ||||
| 		expr_eliminate_dups2(type, &e1->left.expr, &e2); | ||||
| 		expr_eliminate_dups2(type, &e1->right.expr, &e2); | ||||
| 		return; | ||||
| 	} | ||||
| 	if (e2->type == type) { | ||||
| 		expr_eliminate_dups2(type, &e1, &e2->left.expr); | ||||
| 		expr_eliminate_dups2(type, &e1, &e2->right.expr); | ||||
| 	} | ||||
| 	if (e1 == e2) | ||||
| 		return; | ||||
|  | ||||
| 	switch (e1->type) { | ||||
| 	case E_OR: | ||||
| 		expr_eliminate_dups2(e1->type, &e1, &e1); | ||||
| 		// (FOO || BAR) && (!FOO && !BAR) -> n | ||||
| 		tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); | ||||
| 		tmp2 = expr_copy(e2); | ||||
| 		tmp = expr_extract_eq_and(&tmp1, &tmp2); | ||||
| 		if (expr_is_yes(tmp1)) { | ||||
| 			expr_free(e1); | ||||
| 			e1 = expr_alloc_symbol(&symbol_no); | ||||
| 			trans_count++; | ||||
| 		} | ||||
| 		expr_free(tmp2); | ||||
| 		expr_free(tmp1); | ||||
| 		expr_free(tmp); | ||||
| 		break; | ||||
| 	case E_AND: | ||||
| 		expr_eliminate_dups2(e1->type, &e1, &e1); | ||||
| 		// (FOO && BAR) || (!FOO || !BAR) -> y | ||||
| 		tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); | ||||
| 		tmp2 = expr_copy(e2); | ||||
| 		tmp = expr_extract_eq_or(&tmp1, &tmp2); | ||||
| 		if (expr_is_no(tmp1)) { | ||||
| 			expr_free(e1); | ||||
| 			e1 = expr_alloc_symbol(&symbol_yes); | ||||
| 			trans_count++; | ||||
| 		} | ||||
| 		expr_free(tmp2); | ||||
| 		expr_free(tmp1); | ||||
| 		expr_free(tmp); | ||||
| 		break; | ||||
| 	default: | ||||
| 		; | ||||
| 	} | ||||
| #undef e1 | ||||
| #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) | ||||
| { | ||||
| 	int oldcount; | ||||
| @@ -621,11 +673,11 @@ struct expr *expr_eliminate_dups(struct expr *e) | ||||
| 		switch (e->type) { | ||||
| 		case E_OR: case E_AND: | ||||
| 			expr_eliminate_dups1(e->type, &e, &e); | ||||
| 			expr_eliminate_dups2(e->type, &e, &e); | ||||
| 		default: | ||||
| 			; | ||||
| 		} | ||||
| 		if (!trans_count) | ||||
| 			/* No simplifications done in this pass. We're done */ | ||||
| 			break; | ||||
| 		e = expr_eliminate_yn(e); | ||||
| 	} | ||||
| @@ -633,6 +685,12 @@ struct expr *expr_eliminate_dups(struct expr *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 *tmp; | ||||
| @@ -641,6 +699,10 @@ struct expr *expr_transform(struct expr *e) | ||||
| 		return NULL; | ||||
| 	switch (e->type) { | ||||
| 	case E_EQUAL: | ||||
| 	case E_GEQ: | ||||
| 	case E_GTH: | ||||
| 	case E_LEQ: | ||||
| 	case E_LTH: | ||||
| 	case E_UNEQUAL: | ||||
| 	case E_SYMBOL: | ||||
| 	case E_LIST: | ||||
| @@ -713,6 +775,22 @@ struct expr *expr_transform(struct expr *e) | ||||
| 			e = tmp; | ||||
| 			e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL; | ||||
| 			break; | ||||
| 		case E_LEQ: | ||||
| 		case E_GEQ: | ||||
| 			// !a<='x' -> a>'x' | ||||
| 			tmp = e->left.expr; | ||||
| 			free(e); | ||||
| 			e = tmp; | ||||
| 			e->type = e->type == E_LEQ ? E_GTH : E_LTH; | ||||
| 			break; | ||||
| 		case E_LTH: | ||||
| 		case E_GTH: | ||||
| 			// !a<'x' -> a>='x' | ||||
| 			tmp = e->left.expr; | ||||
| 			free(e); | ||||
| 			e = tmp; | ||||
| 			e->type = e->type == E_LTH ? E_GEQ : E_LEQ; | ||||
| 			break; | ||||
| 		case E_OR: | ||||
| 			// !(a || b) -> !a && !b | ||||
| 			tmp = e->left.expr; | ||||
| @@ -783,6 +861,10 @@ int expr_contains_symbol(struct expr *dep, struct symbol *sym) | ||||
| 	case E_SYMBOL: | ||||
| 		return dep->left.sym == sym; | ||||
| 	case E_EQUAL: | ||||
| 	case E_GEQ: | ||||
| 	case E_GTH: | ||||
| 	case E_LEQ: | ||||
| 	case E_LTH: | ||||
| 	case E_UNEQUAL: | ||||
| 		return dep->left.sym == sym || | ||||
| 		       dep->right.sym == sym; | ||||
| @@ -823,57 +905,20 @@ bool expr_depends_symbol(struct expr *dep, struct symbol *sym) | ||||
|  	return false; | ||||
| } | ||||
|  | ||||
| struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2) | ||||
| { | ||||
| 	struct expr *tmp = NULL; | ||||
| 	expr_extract_eq(E_AND, &tmp, ep1, ep2); | ||||
| 	if (tmp) { | ||||
| 		*ep1 = expr_eliminate_yn(*ep1); | ||||
| 		*ep2 = expr_eliminate_yn(*ep2); | ||||
| 	} | ||||
| 	return tmp; | ||||
| } | ||||
|  | ||||
| struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2) | ||||
| { | ||||
| 	struct expr *tmp = NULL; | ||||
| 	expr_extract_eq(E_OR, &tmp, ep1, ep2); | ||||
| 	if (tmp) { | ||||
| 		*ep1 = expr_eliminate_yn(*ep1); | ||||
| 		*ep2 = expr_eliminate_yn(*ep2); | ||||
| 	} | ||||
| 	return tmp; | ||||
| } | ||||
|  | ||||
| void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2) | ||||
| { | ||||
| #define e1 (*ep1) | ||||
| #define e2 (*ep2) | ||||
| 	if (e1->type == type) { | ||||
| 		expr_extract_eq(type, ep, &e1->left.expr, &e2); | ||||
| 		expr_extract_eq(type, ep, &e1->right.expr, &e2); | ||||
| 		return; | ||||
| 	} | ||||
| 	if (e2->type == type) { | ||||
| 		expr_extract_eq(type, ep, ep1, &e2->left.expr); | ||||
| 		expr_extract_eq(type, ep, ep1, &e2->right.expr); | ||||
| 		return; | ||||
| 	} | ||||
| 	if (expr_eq(e1, e2)) { | ||||
| 		*ep = *ep ? expr_alloc_two(type, *ep, e1) : e1; | ||||
| 		expr_free(e2); | ||||
| 		if (type == E_AND) { | ||||
| 			e1 = expr_alloc_symbol(&symbol_yes); | ||||
| 			e2 = expr_alloc_symbol(&symbol_yes); | ||||
| 		} else if (type == E_OR) { | ||||
| 			e1 = expr_alloc_symbol(&symbol_no); | ||||
| 			e2 = expr_alloc_symbol(&symbol_no); | ||||
| 		} | ||||
| 	} | ||||
| #undef e1 | ||||
| #undef e2 | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * 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 *e1, *e2; | ||||
| @@ -908,6 +953,10 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb | ||||
| 	case E_NOT: | ||||
| 		return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym); | ||||
| 	case E_UNEQUAL: | ||||
| 	case E_LTH: | ||||
| 	case E_LEQ: | ||||
| 	case E_GTH: | ||||
| 	case E_GEQ: | ||||
| 	case E_EQUAL: | ||||
| 		if (type == E_EQUAL) { | ||||
| 			if (sym == &symbol_yes) | ||||
| @@ -935,10 +984,56 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| enum string_value_kind { | ||||
| 	k_string, | ||||
| 	k_signed, | ||||
| 	k_unsigned, | ||||
| }; | ||||
|  | ||||
| union string_value { | ||||
| 	unsigned long long u; | ||||
| 	signed long long s; | ||||
| }; | ||||
|  | ||||
| static enum string_value_kind expr_parse_string(const char *str, | ||||
| 						enum symbol_type type, | ||||
| 						union string_value *val) | ||||
| { | ||||
| 	char *tail; | ||||
| 	enum string_value_kind kind; | ||||
|  | ||||
| 	errno = 0; | ||||
| 	switch (type) { | ||||
| 	case S_BOOLEAN: | ||||
| 	case S_TRISTATE: | ||||
| 		val->s = !strcmp(str, "n") ? 0 : | ||||
| 			 !strcmp(str, "m") ? 1 : | ||||
| 			 !strcmp(str, "y") ? 2 : -1; | ||||
| 		return k_signed; | ||||
| 	case S_INT: | ||||
| 		val->s = strtoll(str, &tail, 10); | ||||
| 		kind = k_signed; | ||||
| 		break; | ||||
| 	case S_HEX: | ||||
| 		val->u = strtoull(str, &tail, 16); | ||||
| 		kind = k_unsigned; | ||||
| 		break; | ||||
| 	default: | ||||
| 		val->s = strtoll(str, &tail, 0); | ||||
| 		kind = k_signed; | ||||
| 		break; | ||||
| 	} | ||||
| 	return !errno && !*tail && tail > str && isxdigit(tail[-1]) | ||||
| 	       ? kind : k_string; | ||||
| } | ||||
|  | ||||
| tristate expr_calc_value(struct expr *e) | ||||
| { | ||||
| 	tristate val1, val2; | ||||
| 	const char *str1, *str2; | ||||
| 	enum string_value_kind k1 = k_string, k2 = k_string; | ||||
| 	union string_value lval = {}, rval = {}; | ||||
| 	int res; | ||||
|  | ||||
| 	if (!e) | ||||
| 		return yes; | ||||
| @@ -959,31 +1054,64 @@ tristate expr_calc_value(struct expr *e) | ||||
| 		val1 = expr_calc_value(e->left.expr); | ||||
| 		return EXPR_NOT(val1); | ||||
| 	case E_EQUAL: | ||||
| 		sym_calc_value(e->left.sym); | ||||
| 		sym_calc_value(e->right.sym); | ||||
| 		str1 = sym_get_string_value(e->left.sym); | ||||
| 		str2 = sym_get_string_value(e->right.sym); | ||||
| 		return !strcmp(str1, str2) ? yes : no; | ||||
| 	case E_GEQ: | ||||
| 	case E_GTH: | ||||
| 	case E_LEQ: | ||||
| 	case E_LTH: | ||||
| 	case E_UNEQUAL: | ||||
| 		sym_calc_value(e->left.sym); | ||||
| 		sym_calc_value(e->right.sym); | ||||
| 		str1 = sym_get_string_value(e->left.sym); | ||||
| 		str2 = sym_get_string_value(e->right.sym); | ||||
| 		return !strcmp(str1, str2) ? no : yes; | ||||
| 		break; | ||||
| 	default: | ||||
| 		printf("expr_calc_value: %d?\n", e->type); | ||||
| 		return no; | ||||
| 	} | ||||
|  | ||||
| 	sym_calc_value(e->left.sym); | ||||
| 	sym_calc_value(e->right.sym); | ||||
| 	str1 = sym_get_string_value(e->left.sym); | ||||
| 	str2 = sym_get_string_value(e->right.sym); | ||||
|  | ||||
| 	if (e->left.sym->type != S_STRING || e->right.sym->type != S_STRING) { | ||||
| 		k1 = expr_parse_string(str1, e->left.sym->type, &lval); | ||||
| 		k2 = expr_parse_string(str2, e->right.sym->type, &rval); | ||||
| 	} | ||||
|  | ||||
| 	if (k1 == k_string || k2 == k_string) | ||||
| 		res = strcmp(str1, str2); | ||||
| 	else if (k1 == k_unsigned || k2 == k_unsigned) | ||||
| 		res = (lval.u > rval.u) - (lval.u < rval.u); | ||||
| 	else /* if (k1 == k_signed && k2 == k_signed) */ | ||||
| 		res = (lval.s > rval.s) - (lval.s < rval.s); | ||||
|  | ||||
| 	switch(e->type) { | ||||
| 	case E_EQUAL: | ||||
| 		return res ? no : yes; | ||||
| 	case E_GEQ: | ||||
| 		return res >= 0 ? yes : no; | ||||
| 	case E_GTH: | ||||
| 		return res > 0 ? yes : no; | ||||
| 	case E_LEQ: | ||||
| 		return res <= 0 ? yes : no; | ||||
| 	case E_LTH: | ||||
| 		return res < 0 ? yes : no; | ||||
| 	case E_UNEQUAL: | ||||
| 		return res ? yes : no; | ||||
| 	default: | ||||
| 		printf("expr_calc_value: relation %d?\n", e->type); | ||||
| 		return no; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int expr_compare_type(enum expr_type t1, enum expr_type t2) | ||||
| static int expr_compare_type(enum expr_type t1, enum expr_type t2) | ||||
| { | ||||
| #if 0 | ||||
| 	return 1; | ||||
| #else | ||||
| 	if (t1 == t2) | ||||
| 		return 0; | ||||
| 	switch (t1) { | ||||
| 	case E_LEQ: | ||||
| 	case E_LTH: | ||||
| 	case E_GEQ: | ||||
| 	case E_GTH: | ||||
| 		if (t2 == E_EQUAL || t2 == E_UNEQUAL) | ||||
| 			return 1; | ||||
| 	case E_EQUAL: | ||||
| 	case E_UNEQUAL: | ||||
| 		if (t2 == E_NOT) | ||||
| @@ -1005,52 +1133,11 @@ int expr_compare_type(enum expr_type t1, enum expr_type t2) | ||||
| 	} | ||||
| 	printf("[%dgt%d?]", t1, t2); | ||||
| 	return 0; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static inline struct expr * | ||||
| expr_get_leftmost_symbol(const struct expr *e) | ||||
| { | ||||
|  | ||||
| 	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) | ||||
| void expr_print(struct expr *e, | ||||
| 		void (*fn)(void *, struct symbol *, const char *), | ||||
| 		void *data, int prevtoken) | ||||
| { | ||||
| 	if (!e) { | ||||
| 		fn(data, NULL, "y"); | ||||
| @@ -1078,6 +1165,24 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char * | ||||
| 		fn(data, NULL, "="); | ||||
| 		fn(data, e->right.sym, e->right.sym->name); | ||||
| 		break; | ||||
| 	case E_LEQ: | ||||
| 	case E_LTH: | ||||
| 		if (e->left.sym->name) | ||||
| 			fn(data, e->left.sym, e->left.sym->name); | ||||
| 		else | ||||
| 			fn(data, NULL, "<choice>"); | ||||
| 		fn(data, NULL, e->type == E_LEQ ? "<=" : "<"); | ||||
| 		fn(data, e->right.sym, e->right.sym->name); | ||||
| 		break; | ||||
| 	case E_GEQ: | ||||
| 	case E_GTH: | ||||
| 		if (e->left.sym->name) | ||||
| 			fn(data, e->left.sym, e->left.sym->name); | ||||
| 		else | ||||
| 			fn(data, NULL, "<choice>"); | ||||
| 		fn(data, NULL, e->type == E_GEQ ? ">=" : ">"); | ||||
| 		fn(data, e->right.sym, e->right.sym->name); | ||||
| 		break; | ||||
| 	case E_UNEQUAL: | ||||
| 		if (e->left.sym->name) | ||||
| 			fn(data, e->left.sym, e->left.sym->name); | ||||
| @@ -1166,3 +1271,33 @@ void expr_gstr_print(struct expr *e, struct gstr *gs) | ||||
| { | ||||
| 	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> | ||||
|  * Released under the terms of the GNU GPL v2.0. | ||||
|  */ | ||||
|  | ||||
| #ifndef EXPR_H | ||||
| @@ -29,7 +29,9 @@ typedef enum tristate { | ||||
| } tristate; | ||||
|  | ||||
| enum expr_type { | ||||
| 	E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE | ||||
| 	E_NONE, E_OR, E_AND, E_NOT, | ||||
| 	E_EQUAL, E_UNEQUAL, E_LTH, E_LEQ, E_GTH, E_GEQ, | ||||
| 	E_LIST, E_SYMBOL, E_RANGE | ||||
| }; | ||||
|  | ||||
| union expr_data { | ||||
| @@ -60,7 +62,7 @@ struct symbol_value { | ||||
| }; | ||||
|  | ||||
| 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[] */ | ||||
| @@ -72,20 +74,64 @@ enum { | ||||
| 	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 { | ||||
| 	/* The next symbol in the same bucket in the symbol hash table */ | ||||
| 	struct symbol *next; | ||||
|  | ||||
| 	/* The name of the symbol, e.g. "FOO" for 'config FOO' */ | ||||
| 	char *name; | ||||
|  | ||||
| 	/* S_BOOLEAN, S_TRISTATE, ... */ | ||||
| 	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; | ||||
|  | ||||
| 	/* | ||||
| 	 * Values for the symbol provided from outside. def[S_DEF_USER] holds | ||||
| 	 * the .config value. | ||||
| 	 */ | ||||
| 	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; | ||||
|  | ||||
| 	/* SYMBOL_* flags */ | ||||
| 	int flags; | ||||
|  | ||||
| 	/* List of properties. See prop_type. */ | ||||
| 	struct property *prop; | ||||
|  | ||||
| 	/* Dependencies from enclosing menus, choices, and ifs */ | ||||
| 	struct expr_value dir_dep; | ||||
|  | ||||
| 	/* Reverse dependencies through being selected by other symbols */ | ||||
| 	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_CHECK      0x0008  /* used during dependency checking */ | ||||
| @@ -95,7 +141,8 @@ struct symbol { | ||||
| #define SYMBOL_OPTIONAL   0x0100  /* choice is optional - values can be 'n' */ | ||||
| #define SYMBOL_WRITE      0x0200  /* write symbol to file (KCONFIG_CONFIG) */ | ||||
| #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_WARNED     0x8000  /* warning has been issued */ | ||||
|  | ||||
| @@ -109,9 +156,6 @@ struct symbol { | ||||
| /* choice values need to be set before calculating this symbol value */ | ||||
| #define SYMBOL_NEED_SET_CHOICE_VALUES  0x100000 | ||||
|  | ||||
| /* Set symbol to y if allnoconfig; used for symbols that hide others */ | ||||
| #define SYMBOL_ALLNOCONFIG_Y 0x200000 | ||||
|  | ||||
| #define SYMBOL_MAXLENGTH	256 | ||||
| #define SYMBOL_HASHSIZE		9973 | ||||
|  | ||||
| @@ -125,23 +169,25 @@ struct symbol { | ||||
|  * config BAZ | ||||
|  *         int "BAZ Value" | ||||
|  *         range 1..255 | ||||
|  * | ||||
|  * Please, also check parser.y:print_symbol() when modifying the | ||||
|  * list of property types! | ||||
|  */ | ||||
| enum prop_type { | ||||
| 	P_UNKNOWN, | ||||
| 	P_PROMPT,   /* prompt "foo prompt" or "BAZ Value" */ | ||||
| 	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_CHOICE,   /* choice value */ | ||||
| 	P_SELECT,   /* select BAR */ | ||||
| 	P_IMPLY,    /* imply BAR */ | ||||
| 	P_RANGE,    /* range 7..100 (for a symbol) */ | ||||
| 	P_ENV,      /* value from environment variable */ | ||||
| 	P_SYMBOL,   /* where a symbol is defined */ | ||||
| }; | ||||
|  | ||||
| struct property { | ||||
| 	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 */ | ||||
| 	const char *text;          /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */ | ||||
| 	struct expr_value visible; | ||||
| @@ -162,22 +208,67 @@ struct property { | ||||
| 	for (st = sym->prop; st; st = st->next) \ | ||||
| 		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 { | ||||
| 	/* The next menu node at the same level */ | ||||
| 	struct menu *next; | ||||
|  | ||||
| 	/* The parent menu node, corresponding to e.g. a menu or choice */ | ||||
| 	struct menu *parent; | ||||
|  | ||||
| 	/* The first child menu node, for e.g. menus and choices */ | ||||
| 	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; | ||||
|  | ||||
| 	/* | ||||
| 	 * 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; | ||||
|  | ||||
| 	/* | ||||
| 	 * 'visible if' dependencies. If more than one is given, they will be | ||||
| 	 * ANDed together. | ||||
| 	 */ | ||||
| 	struct expr *visibility; | ||||
|  | ||||
| 	/* | ||||
| 	 * Ordinary dependencies from e.g. 'depends on' and 'if', ANDed | ||||
| 	 * together | ||||
| 	 */ | ||||
| 	struct expr *dep; | ||||
|  | ||||
| 	/* MENU_* flags */ | ||||
| 	unsigned int flags; | ||||
|  | ||||
| 	/* Any help text associated with the node */ | ||||
| 	char *help; | ||||
|  | ||||
| 	/* The location where the menu node appears in the Kconfig files */ | ||||
| 	struct file *file; | ||||
| 	int lineno; | ||||
|  | ||||
| 	/* For use by front ends that need to store auxiliary 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_ROOT		0x0002 | ||||
|  | ||||
| struct jump_key { | ||||
| @@ -187,15 +278,12 @@ struct jump_key { | ||||
| 	int index; | ||||
| }; | ||||
|  | ||||
| #define JUMP_NB			9 | ||||
|  | ||||
| extern struct file *file_list; | ||||
| extern struct file *current_file; | ||||
| struct file *lookup_file(const char *name); | ||||
|  | ||||
| extern struct symbol symbol_yes, symbol_no, symbol_mod; | ||||
| extern struct symbol *modules_sym; | ||||
| extern struct symbol *sym_defconfig_list; | ||||
| extern int cdebug; | ||||
| struct expr *expr_alloc_symbol(struct symbol *sym); | ||||
| struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); | ||||
| @@ -205,24 +293,21 @@ struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); | ||||
| struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); | ||||
| struct expr *expr_copy(const struct expr *org); | ||||
| void expr_free(struct expr *e); | ||||
| int expr_eq(struct expr *e1, struct expr *e2); | ||||
| 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); | ||||
| struct expr *expr_eliminate_yn(struct expr *e); | ||||
| struct expr *expr_trans_bool(struct expr *e); | ||||
| struct expr *expr_eliminate_dups(struct expr *e); | ||||
| struct expr *expr_transform(struct expr *e); | ||||
| int expr_contains_symbol(struct expr *dep, struct symbol *sym); | ||||
| bool expr_depends_symbol(struct expr *dep, struct symbol *sym); | ||||
| struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2); | ||||
| struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2); | ||||
| void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); | ||||
| 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); | ||||
| struct gstr; /* forward */ | ||||
| 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) | ||||
| { | ||||
|   | ||||
							
								
								
									
										30
									
								
								util/kconfig/gconf-cfg.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										30
									
								
								util/kconfig/gconf-cfg.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| #!/bin/sh | ||||
| # SPDX-License-Identifier: GPL-2.0 | ||||
|  | ||||
| PKG="gtk+-2.0 gmodule-2.0 libglade-2.0" | ||||
|  | ||||
| if [ -z "$(command -v pkg-config)" ]; then | ||||
| 	echo >&2 "*" | ||||
| 	echo >&2 "* 'make gconfig' requires 'pkg-config'. Please install it." | ||||
| 	echo >&2 "*" | ||||
| 	exit 1 | ||||
| fi | ||||
|  | ||||
| if ! pkg-config --exists $PKG; then | ||||
| 	echo >&2 "*" | ||||
| 	echo >&2 "* Unable to find the GTK+ installation. Please make sure that" | ||||
| 	echo >&2 "* the GTK+ 2.0 development package is correctly installed." | ||||
| 	echo >&2 "* You need $PKG" | ||||
| 	echo >&2 "*" | ||||
| 	exit 1 | ||||
| fi | ||||
|  | ||||
| if ! pkg-config --atleast-version=2.0.0 gtk+-2.0; then | ||||
| 	echo >&2 "*" | ||||
| 	echo >&2 "* GTK+ is present but version >= 2.0.0 is required." | ||||
| 	echo >&2 "*" | ||||
| 	exit 1 | ||||
| fi | ||||
|  | ||||
| echo cflags=\"$(pkg-config --cflags $PKG)\" | ||||
| echo libs=\"$(pkg-config --libs $PKG)\" | ||||
| @@ -1,18 +1,11 @@ | ||||
| /* Hey EMACS -*- linux-c -*- */ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * | ||||
|  * Copyright (C) 2002-2003 Romain Lievin <roms@tilp.info> | ||||
|  * Released under the terms of the GNU GPL v2.0. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifdef HAVE_CONFIG_H | ||||
| #  include <config.h> | ||||
| #endif | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include "lkc.h" | ||||
| #include "images.c" | ||||
| #include "images.h" | ||||
|  | ||||
| #include <glade/glade.h> | ||||
| #include <gtk/gtk.h> | ||||
| @@ -21,13 +14,12 @@ | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <strings.h> | ||||
| #include <unistd.h> | ||||
| #include <time.h> | ||||
|  | ||||
| //#define DEBUG | ||||
|  | ||||
| int kconfig_warnings = 0; | ||||
|  | ||||
| enum { | ||||
| 	SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW | ||||
| }; | ||||
| @@ -80,8 +72,8 @@ static gchar **fill_row(struct menu *menu); | ||||
| static void conf_changed(void); | ||||
|  | ||||
| /* Helping/Debugging Functions */ | ||||
|  | ||||
| const char *dbg_sym_flags(int val) | ||||
| #ifdef DEBUG | ||||
| static const char *dbg_sym_flags(int val) | ||||
| { | ||||
| 	static char buf[256]; | ||||
|  | ||||
| @@ -103,16 +95,17 @@ const char *dbg_sym_flags(int val) | ||||
| 		strcat(buf, "write/"); | ||||
| 	if (val & SYMBOL_CHANGED) | ||||
| 		strcat(buf, "changed/"); | ||||
| 	if (val & SYMBOL_AUTO) | ||||
| 		strcat(buf, "auto/"); | ||||
| 	if (val & SYMBOL_NO_WRITE) | ||||
| 		strcat(buf, "no_write/"); | ||||
|  | ||||
| 	buf[strlen(buf) - 1] = '\0'; | ||||
|  | ||||
| 	return buf; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| void replace_button_icon(GladeXML * xml, GdkDrawable * window, | ||||
| 			 GtkStyle * style, gchar * btn_name, gchar ** xpm) | ||||
| static void replace_button_icon(GladeXML *xml, GdkDrawable *window, | ||||
| 				GtkStyle *style, gchar *btn_name, gchar **xpm) | ||||
| { | ||||
| 	GdkPixmap *pixmap; | ||||
| 	GdkBitmap *mask; | ||||
| @@ -130,7 +123,7 @@ void replace_button_icon(GladeXML * xml, GdkDrawable * window, | ||||
| } | ||||
|  | ||||
| /* Main Window Initialization */ | ||||
| void init_main_window(const gchar * glade_file) | ||||
| static void init_main_window(const gchar *glade_file) | ||||
| { | ||||
| 	GladeXML *xml; | ||||
| 	GtkWidget *widget; | ||||
| @@ -139,7 +132,7 @@ void init_main_window(const gchar * glade_file) | ||||
|  | ||||
| 	xml = glade_xml_new(glade_file, "window1", NULL); | ||||
| 	if (!xml) | ||||
| 		g_error(_("GUI loading failed !\n")); | ||||
| 		g_error("GUI loading failed !\n"); | ||||
| 	glade_xml_signal_autoconnect(xml); | ||||
|  | ||||
| 	main_wnd = glade_xml_get_widget(xml, "window1"); | ||||
| @@ -171,14 +164,6 @@ void init_main_window(const gchar * glade_file) | ||||
| 	style = gtk_widget_get_style(main_wnd); | ||||
| 	widget = glade_xml_get_widget(xml, "toolbar1"); | ||||
|  | ||||
| #if 0	/* Use stock Gtk icons instead */ | ||||
| 	replace_button_icon(xml, main_wnd->window, style, | ||||
| 			    "button1", (gchar **) xpm_back); | ||||
| 	replace_button_icon(xml, main_wnd->window, style, | ||||
| 			    "button2", (gchar **) xpm_load); | ||||
| 	replace_button_icon(xml, main_wnd->window, style, | ||||
| 			    "button3", (gchar **) xpm_save); | ||||
| #endif | ||||
| 	replace_button_icon(xml, main_wnd->window, style, | ||||
| 			    "button4", (gchar **) xpm_single_view); | ||||
| 	replace_button_icon(xml, main_wnd->window, style, | ||||
| @@ -186,22 +171,6 @@ void init_main_window(const gchar * glade_file) | ||||
| 	replace_button_icon(xml, main_wnd->window, style, | ||||
| 			    "button6", (gchar **) xpm_tree_view); | ||||
|  | ||||
| #if 0 | ||||
| 	switch (view_mode) { | ||||
| 	case SINGLE_VIEW: | ||||
| 		widget = glade_xml_get_widget(xml, "button4"); | ||||
| 		g_signal_emit_by_name(widget, "clicked"); | ||||
| 		break; | ||||
| 	case SPLIT_VIEW: | ||||
| 		widget = glade_xml_get_widget(xml, "button5"); | ||||
| 		g_signal_emit_by_name(widget, "clicked"); | ||||
| 		break; | ||||
| 	case FULL_VIEW: | ||||
| 		widget = glade_xml_get_widget(xml, "button6"); | ||||
| 		g_signal_emit_by_name(widget, "clicked"); | ||||
| 		break; | ||||
| 	} | ||||
| #endif | ||||
| 	txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); | ||||
| 	tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1", | ||||
| 					  "foreground", "red", | ||||
| @@ -216,7 +185,7 @@ void init_main_window(const gchar * glade_file) | ||||
| 	gtk_widget_show(main_wnd); | ||||
| } | ||||
|  | ||||
| void init_tree_model(void) | ||||
| static void init_tree_model(void) | ||||
| { | ||||
| 	gint i; | ||||
|  | ||||
| @@ -246,7 +215,7 @@ void init_tree_model(void) | ||||
| 	model1 = GTK_TREE_MODEL(tree1); | ||||
| } | ||||
|  | ||||
| void init_left_tree(void) | ||||
| static void init_left_tree(void) | ||||
| { | ||||
| 	GtkTreeView *view = GTK_TREE_VIEW(tree1_w); | ||||
| 	GtkCellRenderer *renderer; | ||||
| @@ -259,7 +228,7 @@ void init_left_tree(void) | ||||
|  | ||||
| 	column = gtk_tree_view_column_new(); | ||||
| 	gtk_tree_view_append_column(view, column); | ||||
| 	gtk_tree_view_column_set_title(column, _("Options")); | ||||
| 	gtk_tree_view_column_set_title(column, "Options"); | ||||
|  | ||||
| 	renderer = gtk_cell_renderer_toggle_new(); | ||||
| 	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), | ||||
| @@ -288,7 +257,7 @@ static void renderer_edited(GtkCellRendererText * cell, | ||||
| 			    const gchar * path_string, | ||||
| 			    const gchar * new_text, gpointer user_data); | ||||
|  | ||||
| void init_right_tree(void) | ||||
| static void init_right_tree(void) | ||||
| { | ||||
| 	GtkTreeView *view = GTK_TREE_VIEW(tree2_w); | ||||
| 	GtkCellRenderer *renderer; | ||||
| @@ -302,7 +271,7 @@ void init_right_tree(void) | ||||
|  | ||||
| 	column = gtk_tree_view_column_new(); | ||||
| 	gtk_tree_view_append_column(view, column); | ||||
| 	gtk_tree_view_column_set_title(column, _("Options")); | ||||
| 	gtk_tree_view_column_set_title(column, "Options"); | ||||
|  | ||||
| 	renderer = gtk_cell_renderer_pixbuf_new(); | ||||
| 	gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), | ||||
| @@ -331,7 +300,7 @@ void init_right_tree(void) | ||||
|  | ||||
| 	renderer = gtk_cell_renderer_text_new(); | ||||
| 	gtk_tree_view_insert_column_with_attributes(view, -1, | ||||
| 						    _("Name"), renderer, | ||||
| 						    "Name", renderer, | ||||
| 						    "text", COL_NAME, | ||||
| 						    "foreground-gdk", | ||||
| 						    COL_COLOR, NULL); | ||||
| @@ -355,7 +324,7 @@ void init_right_tree(void) | ||||
| 						    COL_COLOR, NULL); | ||||
| 	renderer = gtk_cell_renderer_text_new(); | ||||
| 	gtk_tree_view_insert_column_with_attributes(view, -1, | ||||
| 						    _("Value"), renderer, | ||||
| 						    "Value", renderer, | ||||
| 						    "text", COL_VALUE, | ||||
| 						    "editable", | ||||
| 						    COL_EDIT, | ||||
| @@ -394,7 +363,7 @@ static void text_insert_help(struct menu *menu) | ||||
| { | ||||
| 	GtkTextBuffer *buffer; | ||||
| 	GtkTextIter start, end; | ||||
| 	const char *prompt = _(menu_get_prompt(menu)); | ||||
| 	const char *prompt = menu_get_prompt(menu); | ||||
| 	struct gstr help = str_new(); | ||||
|  | ||||
| 	menu_get_ext_help(menu, &help); | ||||
| @@ -448,7 +417,7 @@ gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event, | ||||
| 	if (!conf_get_changed()) | ||||
| 		return FALSE; | ||||
|  | ||||
| 	dialog = gtk_dialog_new_with_buttons(_("Warning !"), | ||||
| 	dialog = gtk_dialog_new_with_buttons("Warning !", | ||||
| 					     GTK_WINDOW(main_wnd), | ||||
| 					     (GtkDialogFlags) | ||||
| 					     (GTK_DIALOG_MODAL | | ||||
| @@ -462,7 +431,7 @@ gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event, | ||||
| 	gtk_dialog_set_default_response(GTK_DIALOG(dialog), | ||||
| 					GTK_RESPONSE_CANCEL); | ||||
|  | ||||
| 	label = gtk_label_new(_("\nSave configuration ?\n")); | ||||
| 	label = gtk_label_new("\nSave configuration ?\n"); | ||||
| 	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); | ||||
| 	gtk_widget_show(label); | ||||
|  | ||||
| @@ -522,7 +491,7 @@ load_filename(GtkFileSelection * file_selector, gpointer user_data) | ||||
| 					     (user_data)); | ||||
|  | ||||
| 	if (conf_read(fn)) | ||||
| 		text_insert_msg(_("Error"), _("Unable to load configuration !")); | ||||
| 		text_insert_msg("Error", "Unable to load configuration !"); | ||||
| 	else | ||||
| 		display_tree(&rootmenu); | ||||
| } | ||||
| @@ -531,7 +500,7 @@ void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||||
| { | ||||
| 	GtkWidget *fs; | ||||
|  | ||||
| 	fs = gtk_file_selection_new(_("Load file...")); | ||||
| 	fs = gtk_file_selection_new("Load file..."); | ||||
| 	g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), | ||||
| 			 "clicked", | ||||
| 			 G_CALLBACK(load_filename), (gpointer) fs); | ||||
| @@ -550,7 +519,8 @@ void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||||
| void on_save_activate(GtkMenuItem * menuitem, gpointer user_data) | ||||
| { | ||||
| 	if (conf_write(NULL)) | ||||
| 		text_insert_msg(_("Error"), _("Unable to save configuration !")); | ||||
| 		text_insert_msg("Error", "Unable to save configuration !"); | ||||
| 	conf_write_autoconf(0); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -563,7 +533,7 @@ store_filename(GtkFileSelection * file_selector, gpointer user_data) | ||||
| 					     (user_data)); | ||||
|  | ||||
| 	if (conf_write(fn)) | ||||
| 		text_insert_msg(_("Error"), _("Unable to save configuration !")); | ||||
| 		text_insert_msg("Error", "Unable to save configuration !"); | ||||
|  | ||||
| 	gtk_widget_destroy(GTK_WIDGET(user_data)); | ||||
| } | ||||
| @@ -572,7 +542,7 @@ void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||||
| { | ||||
| 	GtkWidget *fs; | ||||
|  | ||||
| 	fs = gtk_file_selection_new(_("Save file as...")); | ||||
| 	fs = gtk_file_selection_new("Save file as..."); | ||||
| 	g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), | ||||
| 			 "clicked", | ||||
| 			 G_CALLBACK(store_filename), (gpointer) fs); | ||||
| @@ -665,7 +635,7 @@ on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data) | ||||
| void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||||
| { | ||||
| 	GtkWidget *dialog; | ||||
| 	const gchar *intro_text = _( | ||||
| 	const gchar *intro_text = | ||||
| 	    "Welcome to gkc, the GTK+ graphical configuration tool\n" | ||||
| 	    "For each option, a blank box indicates the feature is disabled, a\n" | ||||
| 	    "check indicates it is enabled, and a dot indicates that it is to\n" | ||||
| @@ -680,7 +650,7 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||||
| 	    "option.\n" | ||||
| 	    "\n" | ||||
| 	    "Toggling Show Debug Info under the Options menu will show \n" | ||||
| 	    "the dependencies, which you can then match by examining other options."); | ||||
| 	    "the dependencies, which you can then match by examining other options."; | ||||
|  | ||||
| 	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), | ||||
| 					GTK_DIALOG_DESTROY_WITH_PARENT, | ||||
| @@ -697,8 +667,8 @@ void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||||
| { | ||||
| 	GtkWidget *dialog; | ||||
| 	const gchar *about_text = | ||||
| 	    _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n" | ||||
| 	      "Based on the source code from Roman Zippel.\n"); | ||||
| 	    "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n" | ||||
| 	      "Based on the source code from Roman Zippel.\n"; | ||||
|  | ||||
| 	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), | ||||
| 					GTK_DIALOG_DESTROY_WITH_PARENT, | ||||
| @@ -715,9 +685,9 @@ void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) | ||||
| { | ||||
| 	GtkWidget *dialog; | ||||
| 	const gchar *license_text = | ||||
| 	    _("gkc is released under the terms of the GNU GPL v2.\n" | ||||
| 	    "gkc is released under the terms of the GNU GPL v2.\n" | ||||
| 	      "For more information, please see the source code or\n" | ||||
| 	      "visit http://www.fsf.org/licenses/licenses.html\n"); | ||||
| 	      "visit http://www.fsf.org/licenses/licenses.html\n"; | ||||
|  | ||||
| 	dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), | ||||
| 					GTK_DIALOG_DESTROY_WITH_PARENT, | ||||
| @@ -940,7 +910,7 @@ on_treeview2_button_press_event(GtkWidget * widget, | ||||
| 			current = menu; | ||||
| 			display_tree_part(); | ||||
| 			gtk_widget_set_sensitive(back_btn, TRUE); | ||||
| 		} else if ((col == COL_OPTION)) { | ||||
| 		} else if (col == COL_OPTION) { | ||||
| 			toggle_sym_value(menu); | ||||
| 			gtk_tree_view_expand_row(view, path, TRUE); | ||||
| 		} | ||||
| @@ -1074,8 +1044,13 @@ static gchar **fill_row(struct menu *menu) | ||||
| 		g_free(row[i]); | ||||
| 	bzero(row, sizeof(row)); | ||||
|  | ||||
| 	ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; | ||||
|  | ||||
| 	row[COL_OPTION] = | ||||
| 	    g_strdup_printf("%s %s", _(menu_get_prompt(menu)), | ||||
| 	    g_strdup_printf("%s %s %s %s", | ||||
| 			    ptype == P_COMMENT ? "***" : "", | ||||
| 			    menu_get_prompt(menu), | ||||
| 			    ptype == P_COMMENT ? "***" : "", | ||||
| 			    sym && !sym_has_value(sym) ? "(NEW)" : ""); | ||||
|  | ||||
| 	if (opt_mode == OPT_ALL && !menu_is_visible(menu)) | ||||
| @@ -1086,7 +1061,6 @@ static gchar **fill_row(struct menu *menu) | ||||
| 	else | ||||
| 		row[COL_COLOR] = g_strdup("Black"); | ||||
|  | ||||
| 	ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; | ||||
| 	switch (ptype) { | ||||
| 	case P_MENU: | ||||
| 		row[COL_PIXBUF] = (gchar *) xpm_menu; | ||||
| @@ -1128,7 +1102,7 @@ static gchar **fill_row(struct menu *menu) | ||||
|  | ||||
| 		if (def_menu) | ||||
| 			row[COL_VALUE] = | ||||
| 			    g_strdup(_(menu_get_prompt(def_menu))); | ||||
| 			    g_strdup(menu_get_prompt(def_menu)); | ||||
| 	} | ||||
| 	if (sym->flags & SYMBOL_CHOICEVAL) | ||||
| 		row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); | ||||
| @@ -1237,8 +1211,8 @@ static GtkTreeIter found; | ||||
| /* | ||||
|  * Find a menu in the GtkTree starting at parent. | ||||
|  */ | ||||
| GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent, | ||||
| 				    struct menu *tofind) | ||||
| static GtkTreeIter *gtktree_iter_find_node(GtkTreeIter *parent, | ||||
| 					   struct menu *tofind) | ||||
| { | ||||
| 	GtkTreeIter iter; | ||||
| 	GtkTreeIter *child = &iter; | ||||
| @@ -1449,7 +1423,7 @@ static void display_list(void) | ||||
| 	tree = tree2; | ||||
| } | ||||
|  | ||||
| void fixup_rootmenu(struct menu *menu) | ||||
| static void fixup_rootmenu(struct menu *menu) | ||||
| { | ||||
| 	struct menu *child; | ||||
| 	static int menu_cnt = 0; | ||||
| @@ -1473,18 +1447,11 @@ int main(int ac, char *av[]) | ||||
| 	char *env; | ||||
| 	gchar *glade_file; | ||||
|  | ||||
| 	bindtextdomain(PACKAGE, LOCALEDIR); | ||||
| 	bind_textdomain_codeset(PACKAGE, "UTF-8"); | ||||
| 	textdomain(PACKAGE); | ||||
|  | ||||
| 	/* GTK stuffs */ | ||||
| 	gtk_set_locale(); | ||||
| 	gtk_init(&ac, &av); | ||||
| 	glade_init(); | ||||
|  | ||||
| 	//add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); | ||||
| 	//add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps"); | ||||
|  | ||||
| 	/* Determine GUI path */ | ||||
| 	env = getenv(SRCTREE); | ||||
| 	if (env) | ||||
| @@ -1500,9 +1467,12 @@ int main(int ac, char *av[]) | ||||
| 		case 'a': | ||||
| 			//showAll = 1; | ||||
| 			break; | ||||
| 		case 's': | ||||
| 			conf_set_message_callback(NULL); | ||||
| 			break; | ||||
| 		case 'h': | ||||
| 		case '?': | ||||
| 			printf("%s <config>\n", av[0]); | ||||
| 			printf("%s [-s] <config>\n", av[0]); | ||||
| 			exit(0); | ||||
| 		} | ||||
| 		name = av[2]; | ||||
|   | ||||
| @@ -1,9 +1,11 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * 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 * const xpm_load[] = { | ||||
| "22 22 5 1", | ||||
| ". c None", | ||||
| "# c #000000", | ||||
| @@ -33,7 +35,7 @@ static const char *xpm_load[] = { | ||||
| "###############.......", | ||||
| "......................"}; | ||||
|  | ||||
| static const char *xpm_save[] = { | ||||
| const char * const xpm_save[] = { | ||||
| "22 22 5 1", | ||||
| ". c None", | ||||
| "# c #000000", | ||||
| @@ -63,7 +65,7 @@ static const char *xpm_save[] = { | ||||
| "..##################..", | ||||
| "......................"}; | ||||
|  | ||||
| static const char *xpm_back[] = { | ||||
| const char * const xpm_back[] = { | ||||
| "22 22 3 1", | ||||
| ". c None", | ||||
| "# c #000083", | ||||
| @@ -91,7 +93,7 @@ static const char *xpm_back[] = { | ||||
| "......................", | ||||
| "......................"}; | ||||
|  | ||||
| static const char *xpm_tree_view[] = { | ||||
| const char * const xpm_tree_view[] = { | ||||
| "22 22 2 1", | ||||
| ". c None", | ||||
| "# c #000000", | ||||
| @@ -118,7 +120,7 @@ static const char *xpm_tree_view[] = { | ||||
| "......................", | ||||
| "......................"}; | ||||
|  | ||||
| static const char *xpm_single_view[] = { | ||||
| const char * const xpm_single_view[] = { | ||||
| "22 22 2 1", | ||||
| ". c None", | ||||
| "# c #000000", | ||||
| @@ -145,7 +147,7 @@ static const char *xpm_single_view[] = { | ||||
| "......................", | ||||
| "......................"}; | ||||
|  | ||||
| static const char *xpm_split_view[] = { | ||||
| const char * const xpm_split_view[] = { | ||||
| "22 22 2 1", | ||||
| ". c None", | ||||
| "# c #000000", | ||||
| @@ -172,7 +174,7 @@ static const char *xpm_split_view[] = { | ||||
| "......................", | ||||
| "......................"}; | ||||
|  | ||||
| static const char *xpm_symbol_no[] = { | ||||
| const char * const xpm_symbol_no[] = { | ||||
| "12 12 2 1", | ||||
| "  c white", | ||||
| ". c black", | ||||
| @@ -189,7 +191,7 @@ static const char *xpm_symbol_no[] = { | ||||
| " .......... ", | ||||
| "            "}; | ||||
|  | ||||
| static const char *xpm_symbol_mod[] = { | ||||
| const char * const xpm_symbol_mod[] = { | ||||
| "12 12 2 1", | ||||
| "  c white", | ||||
| ". c black", | ||||
| @@ -206,7 +208,7 @@ static const char *xpm_symbol_mod[] = { | ||||
| " .......... ", | ||||
| "            "}; | ||||
|  | ||||
| static const char *xpm_symbol_yes[] = { | ||||
| const char * const xpm_symbol_yes[] = { | ||||
| "12 12 2 1", | ||||
| "  c white", | ||||
| ". c black", | ||||
| @@ -223,7 +225,7 @@ static const char *xpm_symbol_yes[] = { | ||||
| " .......... ", | ||||
| "            "}; | ||||
|  | ||||
| static const char *xpm_choice_no[] = { | ||||
| const char * const xpm_choice_no[] = { | ||||
| "12 12 2 1", | ||||
| "  c white", | ||||
| ". c black", | ||||
| @@ -240,7 +242,7 @@ static const char *xpm_choice_no[] = { | ||||
| "    ....    ", | ||||
| "            "}; | ||||
|  | ||||
| static const char *xpm_choice_yes[] = { | ||||
| const char * const xpm_choice_yes[] = { | ||||
| "12 12 2 1", | ||||
| "  c white", | ||||
| ". c black", | ||||
| @@ -257,7 +259,7 @@ static const char *xpm_choice_yes[] = { | ||||
| "    ....    ", | ||||
| "            "}; | ||||
|  | ||||
| static const char *xpm_menu[] = { | ||||
| const char * const xpm_menu[] = { | ||||
| "12 12 2 1", | ||||
| "  c white", | ||||
| ". c black", | ||||
| @@ -274,7 +276,7 @@ static const char *xpm_menu[] = { | ||||
| " .......... ", | ||||
| "            "}; | ||||
|  | ||||
| static const char *xpm_menu_inv[] = { | ||||
| const char * const xpm_menu_inv[] = { | ||||
| "12 12 2 1", | ||||
| "  c white", | ||||
| ". c black", | ||||
| @@ -291,7 +293,7 @@ static const char *xpm_menu_inv[] = { | ||||
| " .......... ", | ||||
| "            "}; | ||||
|  | ||||
| static const char *xpm_menuback[] = { | ||||
| const char * const xpm_menuback[] = { | ||||
| "12 12 2 1", | ||||
| "  c white", | ||||
| ". c black", | ||||
| @@ -308,7 +310,7 @@ static const char *xpm_menuback[] = { | ||||
| " .......... ", | ||||
| "            "}; | ||||
|  | ||||
| static const char *xpm_void[] = { | ||||
| const char * const xpm_void[] = { | ||||
| "12 12 2 1", | ||||
| "  c white", | ||||
| ". c black", | ||||
|   | ||||
							
								
								
									
										33
									
								
								util/kconfig/images.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								util/kconfig/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 * const xpm_load[]; | ||||
| extern const char * const xpm_save[]; | ||||
| extern const char * const xpm_back[]; | ||||
| extern const char * const xpm_tree_view[]; | ||||
| extern const char * const xpm_single_view[]; | ||||
| extern const char * const xpm_split_view[]; | ||||
| extern const char * const xpm_symbol_no[]; | ||||
| extern const char * const xpm_symbol_mod[]; | ||||
| extern const char * const xpm_symbol_yes[]; | ||||
| extern const char * const xpm_choice_no[]; | ||||
| extern const char * const xpm_choice_yes[]; | ||||
| extern const char * const xpm_menu[]; | ||||
| extern const char * const xpm_menu_inv[]; | ||||
| extern const char * const xpm_menuback[]; | ||||
| extern const char * const xpm_void[]; | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* IMAGES_H */ | ||||
							
								
								
									
										9
									
								
								util/kconfig/internal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								util/kconfig/internal.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||||
| #ifndef INTERNAL_H | ||||
| #define INTERNAL_H | ||||
|  | ||||
| struct menu; | ||||
|  | ||||
| extern struct menu *current_menu, *current_entry; | ||||
|  | ||||
| #endif /* INTERNAL_H */ | ||||
| @@ -1,235 +0,0 @@ | ||||
| /* | ||||
|  * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005 | ||||
|  * | ||||
|  * Released under the terms of the GNU GPL v2.0 | ||||
|  */ | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "lkc.h" | ||||
|  | ||||
| static char *escape(const char* text, char *bf, int len) | ||||
| { | ||||
| 	char *bfp = bf; | ||||
| 	int multiline = strchr(text, '\n') != NULL; | ||||
| 	int eol = 0; | ||||
| 	int textlen = strlen(text); | ||||
|  | ||||
| 	if ((textlen > 0) && (text[textlen-1] == '\n')) | ||||
| 		eol = 1; | ||||
|  | ||||
| 	*bfp++ = '"'; | ||||
| 	--len; | ||||
|  | ||||
| 	if (multiline) { | ||||
| 		*bfp++ = '"'; | ||||
| 		*bfp++ = '\n'; | ||||
| 		*bfp++ = '"'; | ||||
| 		len -= 3; | ||||
| 	} | ||||
|  | ||||
| 	while (*text != '\0' && len > 1) { | ||||
| 		if (*text == '"') | ||||
| 			*bfp++ = '\\'; | ||||
| 		else if (*text == '\n') { | ||||
| 			*bfp++ = '\\'; | ||||
| 			*bfp++ = 'n'; | ||||
| 			*bfp++ = '"'; | ||||
| 			*bfp++ = '\n'; | ||||
| 			*bfp++ = '"'; | ||||
| 			len -= 5; | ||||
| 			++text; | ||||
| 			goto next; | ||||
| 		} | ||||
| 		else if (*text == '\\') { | ||||
| 			*bfp++ = '\\'; | ||||
| 			len--; | ||||
| 		} | ||||
| 		*bfp++ = *text++; | ||||
| next: | ||||
| 		--len; | ||||
| 	} | ||||
|  | ||||
| 	if (multiline && eol) | ||||
| 		bfp -= 3; | ||||
|  | ||||
| 	*bfp++ = '"'; | ||||
| 	*bfp = '\0'; | ||||
|  | ||||
| 	return bf; | ||||
| } | ||||
|  | ||||
| struct file_line { | ||||
| 	struct file_line *next; | ||||
| 	const char *file; | ||||
| 	int lineno; | ||||
| }; | ||||
|  | ||||
| static struct file_line *file_line__new(const char *file, int lineno) | ||||
| { | ||||
| 	struct file_line *self = malloc(sizeof(*self)); | ||||
|  | ||||
| 	if (self == NULL) | ||||
| 		goto out; | ||||
|  | ||||
| 	self->file   = file; | ||||
| 	self->lineno = lineno; | ||||
| 	self->next   = NULL; | ||||
| out: | ||||
| 	return self; | ||||
| } | ||||
|  | ||||
| struct message { | ||||
| 	const char	 *msg; | ||||
| 	const char	 *option; | ||||
| 	struct message	 *next; | ||||
| 	struct file_line *files; | ||||
| }; | ||||
|  | ||||
| static struct message *message__list; | ||||
|  | ||||
| static struct message *message__new(const char *msg, char *option, | ||||
| 				    const char *file, int lineno) | ||||
| { | ||||
| 	struct message *self = malloc(sizeof(*self)); | ||||
|  | ||||
| 	if (self == NULL) | ||||
| 		goto out; | ||||
|  | ||||
| 	self->files = file_line__new(file, lineno); | ||||
| 	if (self->files == NULL) | ||||
| 		goto out_fail; | ||||
|  | ||||
| 	self->msg = strdup(msg); | ||||
| 	if (self->msg == NULL) | ||||
| 		goto out_fail_msg; | ||||
|  | ||||
| 	self->option = option; | ||||
| 	self->next = NULL; | ||||
| out: | ||||
| 	return self; | ||||
| out_fail_msg: | ||||
| 	free(self->files); | ||||
| out_fail: | ||||
| 	free(self); | ||||
| 	self = NULL; | ||||
| 	goto out; | ||||
| } | ||||
|  | ||||
| static struct message *mesage__find(const char *msg) | ||||
| { | ||||
| 	struct message *m = message__list; | ||||
|  | ||||
| 	while (m != NULL) { | ||||
| 		if (strcmp(m->msg, msg) == 0) | ||||
| 			break; | ||||
| 		m = m->next; | ||||
| 	} | ||||
|  | ||||
| 	return m; | ||||
| } | ||||
|  | ||||
| static int message__add_file_line(struct message *self, const char *file, | ||||
| 				  int lineno) | ||||
| { | ||||
| 	int rc = -1; | ||||
| 	struct file_line *fl = file_line__new(file, lineno); | ||||
|  | ||||
| 	if (fl == NULL) | ||||
| 		goto out; | ||||
|  | ||||
| 	fl->next    = self->files; | ||||
| 	self->files = fl; | ||||
| 	rc = 0; | ||||
| out: | ||||
| 	return rc; | ||||
| } | ||||
|  | ||||
| static int message__add(const char *msg, char *option, const char *file, | ||||
| 			int lineno) | ||||
| { | ||||
| 	int rc = 0; | ||||
| 	char bf[16384]; | ||||
| 	char *escaped = escape(msg, bf, sizeof(bf)); | ||||
| 	struct message *m = mesage__find(escaped); | ||||
|  | ||||
| 	if (m != NULL) | ||||
| 		rc = message__add_file_line(m, file, lineno); | ||||
| 	else { | ||||
| 		m = message__new(escaped, option, file, lineno); | ||||
|  | ||||
| 		if (m != NULL) { | ||||
| 			m->next	      = message__list; | ||||
| 			message__list = m; | ||||
| 		} else | ||||
| 			rc = -1; | ||||
| 	} | ||||
| 	return rc; | ||||
| } | ||||
|  | ||||
| static void menu_build_message_list(struct menu *menu) | ||||
| { | ||||
| 	struct menu *child; | ||||
|  | ||||
| 	message__add(menu_get_prompt(menu), NULL, | ||||
| 		     menu->file == NULL ? "Root Menu" : menu->file->name, | ||||
| 		     menu->lineno); | ||||
|  | ||||
| 	if (menu->sym != NULL && menu_has_help(menu)) | ||||
| 		message__add(menu_get_help(menu), menu->sym->name, | ||||
| 			     menu->file == NULL ? "Root Menu" : menu->file->name, | ||||
| 			     menu->lineno); | ||||
|  | ||||
| 	for (child = menu->list; child != NULL; child = child->next) | ||||
| 		if (child->prompt != NULL) | ||||
| 			menu_build_message_list(child); | ||||
| } | ||||
|  | ||||
| static void message__print_file_lineno(struct message *self) | ||||
| { | ||||
| 	struct file_line *fl = self->files; | ||||
|  | ||||
| 	putchar('\n'); | ||||
| 	if (self->option != NULL) | ||||
| 		printf("# %s:00000\n", self->option); | ||||
|  | ||||
| 	printf("#: %s:%d", fl->file, fl->lineno); | ||||
| 	fl = fl->next; | ||||
|  | ||||
| 	while (fl != NULL) { | ||||
| 		printf(", %s:%d", fl->file, fl->lineno); | ||||
| 		fl = fl->next; | ||||
| 	} | ||||
|  | ||||
| 	putchar('\n'); | ||||
| } | ||||
|  | ||||
| static void message__print_gettext_msgid_msgstr(struct message *self) | ||||
| { | ||||
| 	message__print_file_lineno(self); | ||||
|  | ||||
| 	printf("msgid %s\n" | ||||
| 	       "msgstr \"\"\n", self->msg); | ||||
| } | ||||
|  | ||||
| static void menu__xgettext(void) | ||||
| { | ||||
| 	struct message *m = message__list; | ||||
|  | ||||
| 	while (m != NULL) { | ||||
| 		/* skip empty lines ("") */ | ||||
| 		if (strlen(m->msg) > sizeof("\"\"")) | ||||
| 			message__print_gettext_msgid_msgstr(m); | ||||
| 		m = m->next; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int main(int ac, char **av) | ||||
| { | ||||
| 	conf_parse(av[1]); | ||||
|  | ||||
| 	menu_build_message_list(menu_get_root_menu(NULL)); | ||||
| 	menu__xgettext(); | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										494
									
								
								util/kconfig/lexer.l
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										494
									
								
								util/kconfig/lexer.l
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,494 @@ | ||||
| /* SPDX-License-Identifier: GPL-2.0 */ | ||||
| /* | ||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||
|  */ | ||||
| %option nostdinit noyywrap never-interactive full ecs | ||||
| %option 8bit nodefault yylineno | ||||
| %x ASSIGN_VAL HELP STRING | ||||
| %{ | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <glob.h> | ||||
| #include <limits.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "lkc.h" | ||||
| #include "parser.tab.h" | ||||
|  | ||||
| #define YY_DECL		static int yylex1(void) | ||||
|  | ||||
| #define START_STRSIZE	16 | ||||
|  | ||||
| static struct { | ||||
| 	struct file *file; | ||||
| 	int lineno; | ||||
| } current_pos; | ||||
|  | ||||
| static int prev_prev_token = T_EOL; | ||||
| static int prev_token = T_EOL; | ||||
| static char *text; | ||||
| static int text_size, text_asize; | ||||
|  | ||||
| struct buffer { | ||||
| 	struct buffer *parent; | ||||
| 	YY_BUFFER_STATE state; | ||||
| }; | ||||
|  | ||||
| static struct buffer *current_buf; | ||||
|  | ||||
| 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_endfile(void); | ||||
|  | ||||
| static void new_string(void) | ||||
| { | ||||
| 	text = xmalloc(START_STRSIZE); | ||||
| 	text_asize = START_STRSIZE; | ||||
| 	text_size = 0; | ||||
| 	*text = 0; | ||||
| } | ||||
|  | ||||
| static void append_string(const char *str, int size) | ||||
| { | ||||
| 	int new_size = text_size + size + 1; | ||||
| 	if (new_size > text_asize) { | ||||
| 		new_size += START_STRSIZE - 1; | ||||
| 		new_size &= -START_STRSIZE; | ||||
| 		text = xrealloc(text, new_size); | ||||
| 		text_asize = new_size; | ||||
| 	} | ||||
| 	memcpy(text + text_size, str, size); | ||||
| 	text_size += size; | ||||
| 	text[text_size] = 0; | ||||
| } | ||||
|  | ||||
| static void alloc_string(const char *str, int size) | ||||
| { | ||||
| 	text = xmalloc(size + 1); | ||||
| 	memcpy(text, str, size); | ||||
| 	text[size] = 0; | ||||
| } | ||||
|  | ||||
| static void warn_ignored_character(char chr) | ||||
| { | ||||
| 	fprintf(stderr, | ||||
| 	        "%s:%d:warning: ignoring unsupported character '%c'\n", | ||||
| 	        current_file->name, yylineno, chr); | ||||
| } | ||||
| %} | ||||
|  | ||||
| n	[A-Za-z0-9_-] | ||||
|  | ||||
| %% | ||||
| 	int str = 0; | ||||
| 	int ts, i; | ||||
|  | ||||
| #.*			/* ignore comment */ | ||||
| [ \t]*			/* whitespaces */ | ||||
| \\\n			/* escaped new line */ | ||||
| \n			return T_EOL; | ||||
| "bool"			return T_BOOL; | ||||
| "choice"		return T_CHOICE; | ||||
| "comment"		return T_COMMENT; | ||||
| "config"		return T_CONFIG; | ||||
| "def_bool"		return T_DEF_BOOL; | ||||
| "def_tristate"		return T_DEF_TRISTATE; | ||||
| "default"		return T_DEFAULT; | ||||
| "depends"		return T_DEPENDS; | ||||
| "endchoice"		return T_ENDCHOICE; | ||||
| "endif"			return T_ENDIF; | ||||
| "endmenu"		return T_ENDMENU; | ||||
| "help"			return T_HELP; | ||||
| "hex"			return T_HEX; | ||||
| "if"			return T_IF; | ||||
| "imply"			return T_IMPLY; | ||||
| "int"			return T_INT; | ||||
| "mainmenu"		return T_MAINMENU; | ||||
| "menu"			return T_MENU; | ||||
| "menuconfig"		return T_MENUCONFIG; | ||||
| "modules"		return T_MODULES; | ||||
| "on"			return T_ON; | ||||
| "optional"		return T_OPTIONAL; | ||||
| "prompt"		return T_PROMPT; | ||||
| "range"			return T_RANGE; | ||||
| "select"		return T_SELECT; | ||||
| "source"		return T_SOURCE; | ||||
| "string"		return T_STRING; | ||||
| "tristate"		return T_TRISTATE; | ||||
| "visible"		return T_VISIBLE; | ||||
| "||"			return T_OR; | ||||
| "&&"			return T_AND; | ||||
| "="			return T_EQUAL; | ||||
| "!="			return T_UNEQUAL; | ||||
| "<"			return T_LESS; | ||||
| "<="			return T_LESS_EQUAL; | ||||
| ">"			return T_GREATER; | ||||
| ">="			return T_GREATER_EQUAL; | ||||
| "!"			return T_NOT; | ||||
| "("			return T_OPEN_PAREN; | ||||
| ")"			return T_CLOSE_PAREN; | ||||
| ":="			return T_COLON_EQUAL; | ||||
| "+="			return T_PLUS_EQUAL; | ||||
| \"|\'			{ | ||||
| 				str = yytext[0]; | ||||
| 				new_string(); | ||||
| 				BEGIN(STRING); | ||||
| 			} | ||||
| {n}+			{ | ||||
| 				alloc_string(yytext, yyleng); | ||||
| 				yylval.string = text; | ||||
| 				return T_WORD; | ||||
| 			} | ||||
| ({n}|$)+		{ | ||||
| 				/* this token includes at least one '$' */ | ||||
| 				yylval.string = expand_token(yytext, yyleng); | ||||
| 				if (strlen(yylval.string)) | ||||
| 					return T_WORD; | ||||
| 				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>{ | ||||
| 	"$".*	append_expanded_string(yytext); | ||||
| 	[^$'"\\\n]+	{ | ||||
| 		append_string(yytext, yyleng); | ||||
| 	} | ||||
| 	\\.?	{ | ||||
| 		append_string(yytext + 1, yyleng - 1); | ||||
| 	} | ||||
| 	\'|\"	{ | ||||
| 		if (str == yytext[0]) { | ||||
| 			BEGIN(INITIAL); | ||||
| 			yylval.string = text; | ||||
| 			return T_WORD_QUOTE; | ||||
| 		} else | ||||
| 			append_string(yytext, 1); | ||||
| 	} | ||||
| 	\n	{ | ||||
| 		fprintf(stderr, | ||||
| 			"%s:%d:warning: multi-line strings not supported\n", | ||||
| 			zconf_curname(), zconf_lineno()); | ||||
| 		unput('\n'); | ||||
| 		BEGIN(INITIAL); | ||||
| 		yylval.string = text; | ||||
| 		return T_WORD_QUOTE; | ||||
| 	} | ||||
| 	<<EOF>>	{ | ||||
| 		BEGIN(INITIAL); | ||||
| 		yylval.string = text; | ||||
| 		return T_WORD_QUOTE; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| <HELP>{ | ||||
| 	[ \t]+	{ | ||||
| 		ts = 0; | ||||
| 		for (i = 0; i < yyleng; i++) { | ||||
| 			if (yytext[i] == '\t') | ||||
| 				ts = (ts & ~7) + 8; | ||||
| 			else | ||||
| 				ts++; | ||||
| 		} | ||||
| 		last_ts = ts; | ||||
| 		if (first_ts) { | ||||
| 			if (ts < first_ts) { | ||||
| 				zconf_endhelp(); | ||||
| 				return T_HELPTEXT; | ||||
| 			} | ||||
| 			ts -= first_ts; | ||||
| 			while (ts > 8) { | ||||
| 				append_string("        ", 8); | ||||
| 				ts -= 8; | ||||
| 			} | ||||
| 			append_string("        ", ts); | ||||
| 		} | ||||
| 	} | ||||
| 	[ \t]*\n/[^ \t\n] { | ||||
| 		zconf_endhelp(); | ||||
| 		return T_HELPTEXT; | ||||
| 	} | ||||
| 	[ \t]*\n	{ | ||||
| 		append_string("\n", 1); | ||||
| 	} | ||||
| 	[^ \t\n].* { | ||||
| 		while (yyleng) { | ||||
| 			if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) | ||||
| 				break; | ||||
| 			yyleng--; | ||||
| 		} | ||||
| 		append_string(yytext, yyleng); | ||||
| 		if (!first_ts) | ||||
| 			first_ts = last_ts; | ||||
| 	} | ||||
| 	<<EOF>>	{ | ||||
| 		zconf_endhelp(); | ||||
| 		return T_HELPTEXT; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| <<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) { | ||||
| 		zconf_endfile(); | ||||
| 		return T_EOL; | ||||
| 	} | ||||
| 	fclose(yyin); | ||||
| 	yyterminate(); | ||||
| } | ||||
|  | ||||
| %% | ||||
|  | ||||
| /* 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) | ||||
| { | ||||
| 	new_string(); | ||||
| 	last_ts = first_ts = 0; | ||||
| 	BEGIN(HELP); | ||||
| } | ||||
|  | ||||
| static void zconf_endhelp(void) | ||||
| { | ||||
| 	yylval.string = text; | ||||
| 	BEGIN(INITIAL); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Try to open specified file with following names: | ||||
|  * ./name | ||||
|  * $(srctree)/name | ||||
|  * The latter is used when srctree is separate from objtree | ||||
|  * when compiling the kernel. | ||||
|  * Return NULL if file is not found. | ||||
|  */ | ||||
| FILE *zconf_fopen(const char *name) | ||||
| { | ||||
| 	char *env, fullname[PATH_MAX+1]; | ||||
| 	FILE *f; | ||||
|  | ||||
| 	f = fopen(name, "r"); | ||||
| 	if (!f && name != NULL && name[0] != '/') { | ||||
| 		env = getenv(SRCTREE); | ||||
| 		if (env) { | ||||
| 			snprintf(fullname, sizeof(fullname), | ||||
| 				 "%s/%s", env, name); | ||||
| 			f = fopen(fullname, "r"); | ||||
| 		} | ||||
| 	} | ||||
| 	return f; | ||||
| } | ||||
|  | ||||
| void zconf_initscan(const char *name) | ||||
| { | ||||
| 	yyin = zconf_fopen(name); | ||||
| 	if (!yyin) { | ||||
| 		fprintf(stderr, "can't find file %s\n", name); | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| 	current_buf = xmalloc(sizeof(*current_buf)); | ||||
| 	memset(current_buf, 0, sizeof(*current_buf)); | ||||
|  | ||||
| 	current_file = file_lookup(name); | ||||
| 	yylineno = 1; | ||||
| } | ||||
|  | ||||
| void zconf_nextfile(const char *name) | ||||
| { | ||||
| 	struct file *iter; | ||||
| 	struct file *file = file_lookup(name); | ||||
| 	struct buffer *buf = xmalloc(sizeof(*buf)); | ||||
| 	memset(buf, 0, sizeof(*buf)); | ||||
|  | ||||
| 	current_buf->state = YY_CURRENT_BUFFER; | ||||
| 	yyin = zconf_fopen(file->name); | ||||
| 	if (!yyin) { | ||||
| 		fprintf(stderr, "%s:%d: can't open file \"%s\"\n", | ||||
| 			zconf_curname(), zconf_lineno(), file->name); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); | ||||
| 	buf->parent = current_buf; | ||||
| 	current_buf = buf; | ||||
|  | ||||
| 	current_file->lineno = yylineno; | ||||
| 	file->parent = current_file; | ||||
|  | ||||
| 	for (iter = current_file; iter; iter = iter->parent) { | ||||
| 		if (!strcmp(iter->name, file->name)) { | ||||
| 			fprintf(stderr, | ||||
| 				"Recursive inclusion detected.\n" | ||||
| 				"Inclusion path:\n" | ||||
| 				"  current file : %s\n", file->name); | ||||
| 			iter = file; | ||||
| 			do { | ||||
| 				iter = iter->parent; | ||||
| 				fprintf(stderr, "  included from: %s:%d\n", | ||||
| 					iter->name, iter->lineno - 1); | ||||
| 			} while (strcmp(iter->name, file->name)); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	yylineno = 1; | ||||
| 	current_file = file; | ||||
| } | ||||
|  | ||||
| void zconf_nextfiles(const char *wildcard) | ||||
| { | ||||
| 	glob_t g; | ||||
| 	char **w; | ||||
| 	int i; | ||||
|  | ||||
| 	if (glob(wildcard, 0, NULL, &g) != 0) { | ||||
| 		return; | ||||
| 	} | ||||
| 	if (g.gl_pathv == NULL) { | ||||
| 		globfree(&g); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	/* working through files backwards, since | ||||
| 	 * we're first pushing them on a stack | ||||
| 	 * before actually handling them. | ||||
| 	 */ | ||||
| 	for (i = g.gl_pathc; i > 0; i--) { | ||||
| 		w = &g.gl_pathv[i - 1]; | ||||
| 		zconf_nextfile(*w); | ||||
| 	} | ||||
|  | ||||
| 	globfree(&g); | ||||
| } | ||||
|  | ||||
| static void zconf_endfile(void) | ||||
| { | ||||
| 	struct buffer *parent; | ||||
|  | ||||
| 	current_file = current_file->parent; | ||||
| 	if (current_file) | ||||
| 		yylineno = current_file->lineno; | ||||
|  | ||||
| 	parent = current_buf->parent; | ||||
| 	if (parent) { | ||||
| 		fclose(yyin); | ||||
| 		yy_delete_buffer(YY_CURRENT_BUFFER); | ||||
| 		yy_switch_to_buffer(parent->state); | ||||
| 	} | ||||
| 	free(current_buf); | ||||
| 	current_buf = parent; | ||||
| } | ||||
|  | ||||
| int zconf_lineno(void) | ||||
| { | ||||
| 	return current_pos.lineno; | ||||
| } | ||||
|  | ||||
| const char *zconf_curname(void) | ||||
| { | ||||
| 	return current_pos.file ? current_pos.file->name : "<none>"; | ||||
| } | ||||
| @@ -1,3 +1,4 @@ | ||||
| /* SPDX-License-Identifier: GPL-2.0 */ | ||||
| #ifndef LIST_H | ||||
| #define LIST_H | ||||
|  | ||||
|   | ||||
| @@ -1,41 +1,25 @@ | ||||
| /* SPDX-License-Identifier: GPL-2.0 */ | ||||
| /* | ||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||
|  * Released under the terms of the GNU GPL v2.0. | ||||
|  */ | ||||
|  | ||||
| #ifndef LKC_H | ||||
| #define LKC_H | ||||
|  | ||||
| #include "expr.h" | ||||
| #include <assert.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.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 | ||||
| #include "expr.h" | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| #define P(name,type,arg)	extern type name arg | ||||
| #include "lkc_proto.h" | ||||
| #undef P | ||||
|  | ||||
| #define SRCTREE "srctree" | ||||
|  | ||||
| #ifndef PACKAGE | ||||
| #define PACKAGE "linux" | ||||
| #endif | ||||
|  | ||||
| #define LOCALEDIR "/usr/share/locale" | ||||
|  | ||||
| #define _(text) gettext(text) | ||||
| #define N_(text) (text) | ||||
|  | ||||
| #ifndef CONFIG_ | ||||
| #define CONFIG_ "CONFIG_" | ||||
| #endif | ||||
| @@ -46,33 +30,7 @@ static inline const char *CONFIG_prefix(void) | ||||
| #undef CONFIG_ | ||||
| #define CONFIG_ CONFIG_prefix() | ||||
|  | ||||
| #define TF_COMMAND	0x0001 | ||||
| #define TF_PARAM	0x0002 | ||||
| #define TF_OPTION	0x0004 | ||||
|  | ||||
| enum conf_def_mode { | ||||
| 	def_default, | ||||
| 	def_yes, | ||||
| 	def_mod, | ||||
| 	def_no, | ||||
| 	def_random | ||||
| }; | ||||
|  | ||||
| #define T_OPT_MODULES		1 | ||||
| #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; | ||||
| }; | ||||
|  | ||||
| extern int zconfdebug; | ||||
|  | ||||
| int zconfparse(void); | ||||
| extern int yylineno; | ||||
| void zconfdump(FILE *out); | ||||
| void zconf_starthelp(void); | ||||
| FILE *zconf_fopen(const char *name); | ||||
| @@ -87,18 +45,8 @@ extern int kconfig_warnings; | ||||
|  | ||||
| /* confdata.c */ | ||||
| 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_add_change_count(int count); | ||||
| bool conf_set_all_new_symbols(enum conf_def_mode mode); | ||||
| void set_all_choice_values(struct symbol *csym); | ||||
|  | ||||
| struct conf_printer { | ||||
| 	void (*print_symbol)(FILE *, struct symbol *, const char *, void *); | ||||
| 	void (*print_comment)(FILE *, const char *, void *); | ||||
| }; | ||||
|  | ||||
| /* confdata.c and expr.c */ | ||||
| static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) | ||||
| { | ||||
| @@ -108,28 +56,16 @@ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) | ||||
| 		fprintf(stderr, "Error in writing or end of file.\n"); | ||||
| } | ||||
|  | ||||
| /* menu.c */ | ||||
| void _menu_init(void); | ||||
| void menu_warn(struct menu *menu, const char *fmt, ...); | ||||
| struct menu *menu_add_menu(void); | ||||
| void menu_end_menu(void); | ||||
| void menu_add_entry(struct symbol *sym); | ||||
| void menu_end_entry(void); | ||||
| void menu_add_dep(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_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_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); | ||||
| void menu_add_option(int token, char *arg); | ||||
| void menu_finalize(struct menu *parent); | ||||
| void menu_set_type(int type); | ||||
|  | ||||
| /* util.c */ | ||||
| struct file *file_lookup(const char *name); | ||||
| int file_write_dep(const char *name); | ||||
| void *xmalloc(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 { | ||||
| 	size_t len; | ||||
| @@ -141,25 +77,45 @@ struct gstr { | ||||
| 	int max_width; | ||||
| }; | ||||
| struct gstr str_new(void); | ||||
| struct gstr str_assign(const char *s); | ||||
| void str_free(struct gstr *gs); | ||||
| void str_append(struct gstr *gs, const char *s); | ||||
| void str_printf(struct gstr *gs, const char *fmt, ...); | ||||
| const char *str_get(struct gstr *gs); | ||||
|  | ||||
| /* symbol.c */ | ||||
| extern struct expr *sym_env_list; | ||||
| /* menu.c */ | ||||
| void _menu_init(void); | ||||
| void menu_warn(struct menu *menu, const char *fmt, ...); | ||||
| struct menu *menu_add_menu(void); | ||||
| void menu_end_menu(void); | ||||
| void menu_add_entry(struct symbol *sym); | ||||
| void menu_add_dep(struct expr *dep); | ||||
| void menu_add_visibility(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_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); | ||||
| void menu_finalize(struct menu *parent); | ||||
| void menu_set_type(int type); | ||||
|  | ||||
| void sym_init(void); | ||||
| extern struct menu rootmenu; | ||||
|  | ||||
| bool menu_is_empty(struct menu *menu); | ||||
| bool menu_is_visible(struct menu *menu); | ||||
| bool menu_has_prompt(struct menu *menu); | ||||
| const char *menu_get_prompt(struct menu *menu); | ||||
| struct menu *menu_get_root_menu(struct menu *menu); | ||||
| struct menu *menu_get_parent_menu(struct menu *menu); | ||||
| bool menu_has_help(struct menu *menu); | ||||
| const char *menu_get_help(struct menu *menu); | ||||
| struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head); | ||||
| void menu_get_ext_help(struct menu *menu, struct gstr *help); | ||||
|  | ||||
| /* symbol.c */ | ||||
| void sym_clear_all_valid(void); | ||||
| void sym_set_all_changed(void); | ||||
| void sym_set_changed(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); | ||||
| 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 property *sym_get_env_prop(struct symbol *sym); | ||||
|  | ||||
| static inline tristate sym_get_tristate_value(struct symbol *sym) | ||||
| { | ||||
|   | ||||
| @@ -1,57 +1,52 @@ | ||||
| /* SPDX-License-Identifier: GPL-2.0 */ | ||||
| #include <stdarg.h> | ||||
|  | ||||
| /* confdata.c */ | ||||
| P(conf_parse,void,(const char *name)); | ||||
| P(conf_read,int,(const char *name)); | ||||
| P(conf_read_simple,int,(const char *name, int)); | ||||
| P(conf_write_defconfig,int,(const char *name)); | ||||
| P(conf_write,int,(const char *name)); | ||||
| P(conf_write_autoconf,int,(void)); | ||||
| P(conf_get_changed,bool,(void)); | ||||
| P(conf_set_changed_callback, void,(void (*fn)(void))); | ||||
| P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap))); | ||||
|  | ||||
| /* menu.c */ | ||||
| P(rootmenu,struct menu,); | ||||
|  | ||||
| P(menu_is_empty, bool, (struct menu *menu)); | ||||
| P(menu_is_visible, bool, (struct menu *menu)); | ||||
| P(menu_has_prompt, bool, (struct menu *menu)); | ||||
| P(menu_get_prompt,const char *,(struct menu *menu)); | ||||
| P(menu_get_root_menu,struct menu *,(struct menu *menu)); | ||||
| P(menu_get_parent_menu,struct menu *,(struct menu *menu)); | ||||
| P(menu_has_help,bool,(struct menu *menu)); | ||||
| P(menu_get_help,const char *,(struct menu *menu)); | ||||
| P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head | ||||
| 			 *head)); | ||||
| P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head | ||||
| 				   *head)); | ||||
| P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); | ||||
| void conf_parse(const char *name); | ||||
| int conf_read(const char *name); | ||||
| int conf_read_simple(const char *name, int); | ||||
| int conf_write_defconfig(const char *name); | ||||
| int conf_write(const char *name); | ||||
| int conf_write_autoconf(int overwrite); | ||||
| void conf_set_changed(bool val); | ||||
| bool conf_get_changed(void); | ||||
| void conf_set_changed_callback(void (*fn)(void)); | ||||
| void conf_set_message_callback(void (*fn)(const char *s)); | ||||
|  | ||||
| /* symbol.c */ | ||||
| P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); | ||||
| extern struct symbol * symbol_hash[SYMBOL_HASHSIZE]; | ||||
|  | ||||
| P(sym_lookup,struct symbol *,(const char *name, int flags)); | ||||
| P(sym_find,struct symbol *,(const char *name)); | ||||
| P(sym_expand_string_value,const char *,(const char *in)); | ||||
| P(sym_escape_string_value, const char *,(const char *in)); | ||||
| P(sym_re_search,struct symbol **,(const char *pattern)); | ||||
| P(sym_type_name,const char *,(enum symbol_type type)); | ||||
| P(sym_calc_value,void,(struct symbol *sym)); | ||||
| P(sym_get_type,enum symbol_type,(struct symbol *sym)); | ||||
| P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri)); | ||||
| P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri)); | ||||
| P(sym_toggle_tristate_value,tristate,(struct symbol *sym)); | ||||
| P(sym_string_valid,bool,(struct symbol *sym, const char *newval)); | ||||
| P(sym_string_within_range,bool,(struct symbol *sym, const char *str)); | ||||
| P(sym_set_string_value,bool,(struct symbol *sym, const char *newval)); | ||||
| P(sym_is_changable,bool,(struct symbol *sym)); | ||||
| P(sym_get_choice_prop,struct property *,(struct symbol *sym)); | ||||
| P(sym_get_default_prop,struct property *,(struct symbol *sym)); | ||||
| P(sym_get_string_value,const char *,(struct symbol *sym)); | ||||
| struct symbol * sym_lookup(const char *name, int flags); | ||||
| struct symbol * sym_find(const char *name); | ||||
| const char * sym_escape_string_value(const char *in); | ||||
| struct symbol ** sym_re_search(const char *pattern); | ||||
| const char * sym_type_name(enum symbol_type type); | ||||
| void sym_calc_value(struct symbol *sym); | ||||
| enum symbol_type sym_get_type(struct symbol *sym); | ||||
| bool sym_tristate_within_range(struct symbol *sym,tristate tri); | ||||
| bool sym_set_tristate_value(struct symbol *sym,tristate tri); | ||||
| tristate sym_toggle_tristate_value(struct symbol *sym); | ||||
| bool sym_string_valid(struct symbol *sym, const char *newval); | ||||
| bool sym_string_within_range(struct symbol *sym, const char *str); | ||||
| bool sym_set_string_value(struct symbol *sym, const char *newval); | ||||
| bool sym_is_changeable(struct symbol *sym); | ||||
| struct property * sym_get_choice_prop(struct symbol *sym); | ||||
| const char * sym_get_string_value(struct symbol *sym); | ||||
|  | ||||
| P(prop_get_type_name,const char *,(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 */ | ||||
| P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2)); | ||||
| P(expr_print,void,(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); | ||||
|   | ||||
							
								
								
									
										4
									
								
								util/kconfig/lxdialog/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								util/kconfig/lxdialog/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,4 +0,0 @@ | ||||
| # | ||||
| # Generated files | ||||
| # | ||||
| lxdialog | ||||
| @@ -1,91 +0,0 @@ | ||||
| #!/usr/bin/env 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 pdcursesw pdcurses; 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 | ||||
|  * | ||||
| @@ -5,20 +6,6 @@ | ||||
|  *     Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension | ||||
|  *     Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two | ||||
|  *  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" | ||||
| @@ -103,8 +90,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) | ||||
| 	int x = width / 2 - 11; | ||||
| 	int y = height - 2; | ||||
|  | ||||
| 	print_button(dialog, gettext("Select"), y, x, selected == 0); | ||||
| 	print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); | ||||
| 	print_button(dialog, "Select", y, x, selected == 0); | ||||
| 	print_button(dialog, " Help ", y, x + 14, selected == 1); | ||||
|  | ||||
| 	wmove(dialog, y, x + 1 + 14 * selected); | ||||
| 	wrefresh(dialog); | ||||
|   | ||||
| @@ -1,21 +1,8 @@ | ||||
| /* SPDX-License-Identifier: GPL-2.0+ */ | ||||
| /* | ||||
|  *  dialog.h -- common declarations for all dialog modules | ||||
|  * | ||||
|  *  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> | ||||
| @@ -26,16 +13,10 @@ | ||||
| #include <string.h> | ||||
| #include <stdbool.h> | ||||
|  | ||||
| #ifndef KBUILD_NO_NLS | ||||
| # include <libintl.h> | ||||
| #else | ||||
| # define gettext(Msgid) ((const char *) (Msgid)) | ||||
| #endif | ||||
|  | ||||
| #ifdef __sun__ | ||||
| #define CURS_MACROS | ||||
| #endif | ||||
| #include CURSES_LOC | ||||
| #include <ncurses.h> | ||||
|  | ||||
| /* | ||||
|  * 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 | ||||
|  * | ||||
|  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | ||||
|  *  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" | ||||
| @@ -31,8 +18,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) | ||||
| 	int x = width / 2 - 11; | ||||
| 	int y = height - 2; | ||||
|  | ||||
| 	print_button(dialog, gettext("  Ok  "), y, x, selected == 0); | ||||
| 	print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); | ||||
| 	print_button(dialog, "  Ok  ", y, x, selected == 0); | ||||
| 	print_button(dialog, " Help ", y, x + 14, selected == 1); | ||||
|  | ||||
| 	wmove(dialog, y, x + 1 + 14 * selected); | ||||
| 	wrefresh(dialog); | ||||
| @@ -126,7 +113,8 @@ do_resize: | ||||
| 			case KEY_DOWN: | ||||
| 				break; | ||||
| 			case KEY_BACKSPACE: | ||||
| 			case 127: | ||||
| 			case 8:   /* ^H */ | ||||
| 			case 127: /* ^? */ | ||||
| 				if (pos) { | ||||
| 					wattrset(dialog, dlg.inputbox.atr); | ||||
| 					if (input_x == 0) { | ||||
|   | ||||
| @@ -1,22 +1,9 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0+ | ||||
| /* | ||||
|  *  menubox.c -- implements the menu box | ||||
|  * | ||||
|  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | ||||
|  *  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 y = height - 2; | ||||
|  | ||||
| 	print_button(win, gettext("Select"), y, x, selected == 0); | ||||
| 	print_button(win, gettext(" Exit "), y, x + 12, selected == 1); | ||||
| 	print_button(win, gettext(" Help "), y, x + 24, selected == 2); | ||||
| 	print_button(win, gettext(" Save "), y, x + 36, selected == 3); | ||||
| 	print_button(win, gettext(" Load "), y, x + 48, selected == 4); | ||||
| 	print_button(win, "Select", y, x, selected == 0); | ||||
| 	print_button(win, " Exit ", y, x + 12, selected == 1); | ||||
| 	print_button(win, " Help ", y, x + 24, selected == 2); | ||||
| 	print_button(win, " Save ", y, x + 36, selected == 3); | ||||
| 	print_button(win, " Load ", y, x + 48, selected == 4); | ||||
|  | ||||
| 	wmove(win, y, x + 1 + 12 * selected); | ||||
| 	wrefresh(win); | ||||
|   | ||||
| @@ -1,22 +1,9 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0+ | ||||
| /* | ||||
|  *  textbox.c -- implements the text box | ||||
|  * | ||||
|  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | ||||
|  *  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" | ||||
| @@ -129,7 +116,7 @@ do_resize: | ||||
|  | ||||
| 	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); | ||||
| 	getyx(dialog, cur_y, cur_x);	/* Save cursor position */ | ||||
|  | ||||
|   | ||||
| @@ -1,22 +1,9 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0+ | ||||
| /* | ||||
|  *  util.c | ||||
|  * | ||||
|  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | ||||
|  *  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> | ||||
| @@ -376,7 +363,7 @@ void print_title(WINDOW *dialog, const char *title, int width) | ||||
| /* | ||||
|  * Print a string of text in a window, automatically wrap around to the | ||||
|  * next line if the string is too long to fit on one line. Newline | ||||
|  * characters '\n' are propperly processed.  We start on a new line | ||||
|  * characters '\n' are properly processed.  We start on a new line | ||||
|  * if there is no room for at least 4 nonblanks following a double-space. | ||||
|  */ | ||||
| void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) | ||||
| @@ -554,7 +541,7 @@ int first_alpha(const char *string, const char *exempt) | ||||
|  * lxdialog suggest <ESC> <ESC> which is correctly translated to two | ||||
|  * times esc. But then we need to ignore the second esc to avoid stepping | ||||
|  * out one menu too much. Filter away all escaped key sequences since | ||||
|  * keypad(FALSE) turn off ncurses support for escape sequences - and thats | ||||
|  * keypad(FALSE) turn off ncurses support for escape sequences - and that's | ||||
|  * needed to make notimeout() do as expected. | ||||
|  */ | ||||
| int on_key_esc(WINDOW *win) | ||||
|   | ||||
| @@ -1,22 +1,9 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0+ | ||||
| /* | ||||
|  *  yesno.c -- implements the yes/no box | ||||
|  * | ||||
|  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | ||||
|  *  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" | ||||
| @@ -29,8 +16,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) | ||||
| 	int x = width / 2 - 10; | ||||
| 	int y = height - 2; | ||||
|  | ||||
| 	print_button(dialog, gettext(" Yes "), y, x, selected == 0); | ||||
| 	print_button(dialog, gettext("  No  "), y, x + 13, selected == 1); | ||||
| 	print_button(dialog, " Yes ", y, x, selected == 0); | ||||
| 	print_button(dialog, "  No  ", y, x + 13, selected == 1); | ||||
|  | ||||
| 	wmove(dialog, y, x + 1 + 13 * selected); | ||||
| 	wrefresh(dialog); | ||||
|   | ||||
							
								
								
									
										52
									
								
								util/kconfig/mconf-cfg.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										52
									
								
								util/kconfig/mconf-cfg.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| #!/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 | ||||
|  | ||||
| # As a final fallback before giving up, check if $HOSTCC knows of a default | ||||
| # ncurses installation (e.g. from a vendor-specific sysroot). | ||||
| if echo '#include <ncurses.h>' | ${HOSTCC} -E - >/dev/null 2>&1; 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> | ||||
|  * Released under the terms of the GNU GPL v2.0. | ||||
|  * | ||||
|  * Introduced single menu mode (show all sub-menus in one large tree). | ||||
|  * 2002-11-06 Petr Baudis <pasky@ucw.cz> | ||||
| @@ -15,16 +15,18 @@ | ||||
| #include <stdarg.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <strings.h> | ||||
| #include <signal.h> | ||||
| #include <unistd.h> | ||||
| #include <locale.h> | ||||
|  | ||||
| #include "lkc.h" | ||||
| #include "lxdialog/dialog.h" | ||||
|  | ||||
| #define JUMP_NB			9 | ||||
|  | ||||
| int kconfig_warnings = 0; | ||||
|  | ||||
| static const char mconf_readme[] = N_( | ||||
| static const char mconf_readme[] = | ||||
| "Overview\n" | ||||
| "--------\n" | ||||
| "This interface lets you select features and parameters for the build.\n" | ||||
| @@ -173,37 +175,37 @@ static const char mconf_readme[] = N_( | ||||
| " blackbg    => selects a color scheme with black background\n" | ||||
| " classic    => theme with blue background. The classic look\n" | ||||
| " bluetitle  => an LCD friendly version of classic. (default)\n" | ||||
| "\n"), | ||||
| menu_instructions[] = N_( | ||||
| "\n", | ||||
| menu_instructions[] = | ||||
| 	"Arrow keys navigate the menu.  " | ||||
| 	"<Enter> selects submenus ---> (or empty submenus ----).  " | ||||
| 	"Highlighted letters are hotkeys.  " | ||||
| 	"Pressing <Y> includes, <N> excludes, <M> modularizes features.  " | ||||
| 	"Press <Esc><Esc> to exit, <?> for Help, </> for Search.  " | ||||
| 	"Legend: [*] built-in  [ ] excluded  <M> module  < > module capable"), | ||||
| radiolist_instructions[] = N_( | ||||
| 	"Legend: [*] built-in  [ ] excluded  <M> module  < > module capable", | ||||
| radiolist_instructions[] = | ||||
| 	"Use the arrow keys to navigate this window or " | ||||
| 	"press the hotkey of the item you wish to select " | ||||
| 	"followed by the <SPACE BAR>. " | ||||
| 	"Press <?> for additional information about this option."), | ||||
| inputbox_instructions_int[] = N_( | ||||
| 	"Press <?> for additional information about this option.", | ||||
| inputbox_instructions_int[] = | ||||
| 	"Please enter a decimal value. " | ||||
| 	"Fractions will not be accepted.  " | ||||
| 	"Use the <TAB> key to move from the input field to the buttons below it."), | ||||
| inputbox_instructions_hex[] = N_( | ||||
| 	"Use the <TAB> key to move from the input field to the buttons below it.", | ||||
| inputbox_instructions_hex[] = | ||||
| 	"Please enter a hexadecimal value. " | ||||
| 	"Use the <TAB> key to move from the input field to the buttons below it."), | ||||
| inputbox_instructions_string[] = N_( | ||||
| 	"Use the <TAB> key to move from the input field to the buttons below it.", | ||||
| inputbox_instructions_string[] = | ||||
| 	"Please enter a string value. " | ||||
| 	"Use the <TAB> key to move from the input field to the buttons below it."), | ||||
| setmod_text[] = N_( | ||||
| 	"Use the <TAB> key to move from the input field to the buttons below it.", | ||||
| setmod_text[] = | ||||
| 	"This feature depends on another which has been configured as a module.\n" | ||||
| 	"As a result, this feature will be built as a module."), | ||||
| load_config_text[] = N_( | ||||
| 	"As a result, this feature will be built as a module.", | ||||
| load_config_text[] = | ||||
| 	"Enter the name of the configuration file you wish to load.  " | ||||
| 	"Accept the name shown to restore the configuration you " | ||||
| 	"last retrieved.  Leave blank to abort."), | ||||
| load_config_help[] = N_( | ||||
| 	"last retrieved.  Leave blank to abort.", | ||||
| load_config_help[] = | ||||
| 	"\n" | ||||
| 	"For various reasons, one may wish to keep several different\n" | ||||
| 	"configurations available on a single machine.\n" | ||||
| @@ -213,11 +215,11 @@ load_config_help[] = N_( | ||||
| 	"configuration.\n" | ||||
| 	"\n" | ||||
| 	"If you are uncertain, then you have probably never used alternate\n" | ||||
| 	"configuration files. You should therefore leave this blank to abort.\n"), | ||||
| save_config_text[] = N_( | ||||
| 	"configuration files. You should therefore leave this blank to abort.\n", | ||||
| save_config_text[] = | ||||
| 	"Enter a filename to which this configuration should be saved " | ||||
| 	"as an alternate.  Leave blank to abort."), | ||||
| save_config_help[] = N_( | ||||
| 	"as an alternate.  Leave blank to abort.", | ||||
| save_config_help[] = | ||||
| 	"\n" | ||||
| 	"For various reasons, one may wish to keep different configurations\n" | ||||
| 	"available on a single machine.\n" | ||||
| @@ -227,8 +229,8 @@ save_config_help[] = N_( | ||||
| 	"configuration options you have selected at that time.\n" | ||||
| 	"\n" | ||||
| 	"If you are uncertain what all this means then you should probably\n" | ||||
| 	"leave this blank.\n"), | ||||
| search_help[] = N_( | ||||
| 	"leave this blank.\n", | ||||
| search_help[] = | ||||
| 	"\n" | ||||
| 	"Search for symbols and display their relations.\n" | ||||
| 	"Regular expressions are allowed.\n" | ||||
| @@ -248,7 +250,7 @@ search_help[] = N_( | ||||
| 	"  Selected by: BAR [=n]\n" | ||||
| 	"-----------------------------------------------------------------\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" | ||||
| 	"  this symbol\n" | ||||
| 	"o The 'Defined at' line tells at what file / line number the symbol\n" | ||||
| @@ -273,7 +275,7 @@ search_help[] = N_( | ||||
| 	"Examples: USB	=> find all symbols containing USB\n" | ||||
| 	"          ^USB => find all symbols starting with USB\n" | ||||
| 	"          USB$ => find all symbols ending with USB\n" | ||||
| 	"\n"); | ||||
| 	"\n"; | ||||
|  | ||||
| static int indent; | ||||
| static struct menu *current_menu; | ||||
| @@ -281,6 +283,7 @@ static int child_count; | ||||
| static int single_menu_mode; | ||||
| static int show_all_options; | ||||
| static int save_and_exit; | ||||
| static int silent; | ||||
|  | ||||
| static void conf(struct menu *menu, struct menu *active_menu); | ||||
| static void conf_choice(struct menu *menu); | ||||
| @@ -298,17 +301,12 @@ static char filename[PATH_MAX+1]; | ||||
| static void set_config_filename(const char *config_filename) | ||||
| { | ||||
| 	static char menu_backtitle[PATH_MAX+128]; | ||||
| 	int size; | ||||
|  | ||||
| 	size = snprintf(menu_backtitle, sizeof(menu_backtitle), | ||||
| 			"%s - %s", config_filename, rootmenu.prompt->text); | ||||
| 	if (size >= sizeof(menu_backtitle)) | ||||
| 		menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; | ||||
| 	snprintf(menu_backtitle, sizeof(menu_backtitle), "%s - %s", | ||||
| 		 config_filename, rootmenu.prompt->text); | ||||
| 	set_dialog_backtitle(menu_backtitle); | ||||
|  | ||||
| 	size = snprintf(filename, sizeof(filename), "%s", config_filename); | ||||
| 	if (size >= sizeof(filename)) | ||||
| 		filename[sizeof(filename)-1] = '\0'; | ||||
| 	snprintf(filename, sizeof(filename), "%s", config_filename); | ||||
| } | ||||
|  | ||||
| struct subtitle_part { | ||||
| @@ -401,19 +399,19 @@ static void search_conf(void) | ||||
| 	struct subtitle_part stpart; | ||||
|  | ||||
| 	title = str_new(); | ||||
| 	str_printf( &title, _("Enter (sub)string or regexp to search for " | ||||
| 			      "(with or without \"%s\")"), CONFIG_); | ||||
| 	str_printf( &title, "Enter (sub)string or regexp to search for " | ||||
| 			      "(with or without \"%s\")", CONFIG_); | ||||
|  | ||||
| again: | ||||
| 	dialog_clear(); | ||||
| 	dres = dialog_inputbox(_("Search Configuration Parameter"), | ||||
| 	dres = dialog_inputbox("Search Configuration Parameter", | ||||
| 			      str_get(&title), | ||||
| 			      10, 75, ""); | ||||
| 	switch (dres) { | ||||
| 	case 0: | ||||
| 		break; | ||||
| 	case 1: | ||||
| 		show_helptext(_("Search Configuration"), search_help); | ||||
| 		show_helptext("Search Configuration", search_help); | ||||
| 		goto again; | ||||
| 	default: | ||||
| 		str_free(&title); | ||||
| @@ -444,7 +442,7 @@ again: | ||||
|  | ||||
| 		res = get_relations_str(sym_arr, &head); | ||||
| 		set_subtitle(); | ||||
| 		dres = show_textbox_ext(_("Search Results"), (char *) | ||||
| 		dres = show_textbox_ext("Search Results", (char *) | ||||
| 					str_get(&res), 0, 0, keys, &vscroll, | ||||
| 					&hscroll, &update_text, (void *) | ||||
| 					&data); | ||||
| @@ -492,7 +490,6 @@ static void build_conf(struct menu *menu) | ||||
| 			switch (prop->type) { | ||||
| 			case P_MENU: | ||||
| 				child_count++; | ||||
| 				prompt = _(prompt); | ||||
| 				if (single_menu_mode) { | ||||
| 					item_make("%s%*c%s", | ||||
| 						  menu->data ? "-->" : "++>", | ||||
| @@ -509,7 +506,7 @@ static void build_conf(struct menu *menu) | ||||
| 			case P_COMMENT: | ||||
| 				if (prompt) { | ||||
| 					child_count++; | ||||
| 					item_make("   %*c*** %s ***", indent + 1, ' ', _(prompt)); | ||||
| 					item_make("   %*c*** %s ***", indent + 1, ' ', prompt); | ||||
| 					item_set_tag(':'); | ||||
| 					item_set_data(menu); | ||||
| 				} | ||||
| @@ -517,7 +514,7 @@ static void build_conf(struct menu *menu) | ||||
| 			default: | ||||
| 				if (prompt) { | ||||
| 					child_count++; | ||||
| 					item_make("---%*c%s", indent + 1, ' ', _(prompt)); | ||||
| 					item_make("---%*c%s", indent + 1, ' ', prompt); | ||||
| 					item_set_tag(':'); | ||||
| 					item_set_data(menu); | ||||
| 				} | ||||
| @@ -539,7 +536,7 @@ static void build_conf(struct menu *menu) | ||||
| 		} | ||||
|  | ||||
| 		val = sym_get_tristate_value(sym); | ||||
| 		if (sym_is_changable(sym)) { | ||||
| 		if (sym_is_changeable(sym)) { | ||||
| 			switch (type) { | ||||
| 			case S_BOOLEAN: | ||||
| 				item_make("[%c]", val == no ? ' ' : '*'); | ||||
| @@ -561,10 +558,10 @@ static void build_conf(struct menu *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 (def_menu) { | ||||
| 				item_add_str(" (%s)", _(menu_get_prompt(def_menu))); | ||||
| 				item_add_str(" (%s)", menu_get_prompt(def_menu)); | ||||
| 				item_add_str("  --->"); | ||||
| 				if (def_menu->list) { | ||||
| 					indent += 2; | ||||
| @@ -576,7 +573,7 @@ static void build_conf(struct menu *menu) | ||||
| 		} | ||||
| 	} else { | ||||
| 		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_data(menu); | ||||
| 			goto conf_childs; | ||||
| @@ -590,7 +587,7 @@ static void build_conf(struct menu *menu) | ||||
| 		} else { | ||||
| 			switch (type) { | ||||
| 			case S_BOOLEAN: | ||||
| 				if (sym_is_changable(sym)) | ||||
| 				if (sym_is_changeable(sym)) | ||||
| 					item_make("[%c]", val == no ? ' ' : '*'); | ||||
| 				else | ||||
| 					item_make("-%c-", val == no ? ' ' : '*'); | ||||
| @@ -603,7 +600,7 @@ static void build_conf(struct menu *menu) | ||||
| 				case mod: ch = 'M'; break; | ||||
| 				default:  ch = ' '; break; | ||||
| 				} | ||||
| 				if (sym_is_changable(sym)) { | ||||
| 				if (sym_is_changeable(sym)) { | ||||
| 					if (sym->rev_dep.tri == mod) | ||||
| 						item_make("{%c}", ch); | ||||
| 					else | ||||
| @@ -619,17 +616,17 @@ static void build_conf(struct menu *menu) | ||||
| 				tmp = indent - tmp + 4; | ||||
| 				if (tmp < 0) | ||||
| 					tmp = 0; | ||||
| 				item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)), | ||||
| 					     (sym_has_value(sym) || !sym_is_changable(sym)) ? | ||||
| 					     "" : _(" (NEW)")); | ||||
| 				item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu), | ||||
| 					     (sym_has_value(sym) || !sym_is_changeable(sym)) ? | ||||
| 					     "" : " (NEW)"); | ||||
| 				item_set_tag('s'); | ||||
| 				item_set_data(menu); | ||||
| 				goto conf_childs; | ||||
| 			} | ||||
| 		} | ||||
| 		item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)), | ||||
| 			  (sym_has_value(sym) || !sym_is_changable(sym)) ? | ||||
| 			  "" : _(" (NEW)")); | ||||
| 		item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu), | ||||
| 			  (sym_has_value(sym) || !sym_is_changeable(sym)) ? | ||||
| 			  "" : " (NEW)"); | ||||
| 		if (menu->prompt->type == P_MENU) { | ||||
| 			item_add_str("  %s", menu_is_empty(menu) ? "----" : "--->"); | ||||
| 			return; | ||||
| @@ -666,8 +663,8 @@ static void conf(struct menu *menu, struct menu *active_menu) | ||||
| 			break; | ||||
| 		set_subtitle(); | ||||
| 		dialog_clear(); | ||||
| 		res = dialog_menu(prompt ? _(prompt) : _("Main Menu"), | ||||
| 				  _(menu_instructions), | ||||
| 		res = dialog_menu(prompt ? prompt : "Main Menu", | ||||
| 				  menu_instructions, | ||||
| 				  active_menu, &s_scroll); | ||||
| 		if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) | ||||
| 			break; | ||||
| @@ -709,7 +706,7 @@ static void conf(struct menu *menu, struct menu *active_menu) | ||||
| 				show_help(submenu); | ||||
| 			else { | ||||
| 				reset_subtitle(); | ||||
| 				show_helptext(_("README"), _(mconf_readme)); | ||||
| 				show_helptext("README", mconf_readme); | ||||
| 			} | ||||
| 			break; | ||||
| 		case 3: | ||||
| @@ -774,15 +771,14 @@ static void show_helptext(const char *title, const char *text) | ||||
| 	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) | ||||
| 		printf("%s", buf); | ||||
| 	else | ||||
| 		show_textbox(NULL, buf, 6, 60); | ||||
| 	if (save_and_exit) { | ||||
| 		if (!silent) | ||||
| 			printf("%s", s); | ||||
| 	} else { | ||||
| 		show_textbox(NULL, s, 6, 60); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void show_help(struct menu *menu) | ||||
| @@ -792,13 +788,13 @@ static void show_help(struct menu *menu) | ||||
| 	help.max_width = getmaxx(stdscr) - 10; | ||||
| 	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); | ||||
| } | ||||
|  | ||||
| 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 symbol *active; | ||||
|  | ||||
| @@ -813,9 +809,9 @@ static void conf_choice(struct menu *menu) | ||||
| 			if (!menu_is_visible(child)) | ||||
| 				continue; | ||||
| 			if (child->sym) | ||||
| 				item_make("%s", _(menu_get_prompt(child))); | ||||
| 				item_make("%s", menu_get_prompt(child)); | ||||
| 			else { | ||||
| 				item_make("*** %s ***", _(menu_get_prompt(child))); | ||||
| 				item_make("*** %s ***", menu_get_prompt(child)); | ||||
| 				item_set_tag(':'); | ||||
| 			} | ||||
| 			item_set_data(child); | ||||
| @@ -825,8 +821,8 @@ static void conf_choice(struct menu *menu) | ||||
| 				item_set_tag('X'); | ||||
| 		} | ||||
| 		dialog_clear(); | ||||
| 		res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), | ||||
| 					_(radiolist_instructions), | ||||
| 		res = dialog_checklist(prompt ? prompt : "Main Menu", | ||||
| 					radiolist_instructions, | ||||
| 					MENUBOX_HEIGTH_MIN, | ||||
| 					MENUBOX_WIDTH_MIN, | ||||
| 					CHECKLIST_HEIGTH_MIN); | ||||
| @@ -867,26 +863,26 @@ static void conf_string(struct menu *menu) | ||||
|  | ||||
| 		switch (sym_get_type(menu->sym)) { | ||||
| 		case S_INT: | ||||
| 			heading = _(inputbox_instructions_int); | ||||
| 			heading = inputbox_instructions_int; | ||||
| 			break; | ||||
| 		case S_HEX: | ||||
| 			heading = _(inputbox_instructions_hex); | ||||
| 			heading = inputbox_instructions_hex; | ||||
| 			break; | ||||
| 		case S_STRING: | ||||
| 			heading = _(inputbox_instructions_string); | ||||
| 			heading = inputbox_instructions_string; | ||||
| 			break; | ||||
| 		default: | ||||
| 			heading = _("Internal mconf error!"); | ||||
| 			heading = "Internal mconf error!"; | ||||
| 		} | ||||
| 		dialog_clear(); | ||||
| 		res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"), | ||||
| 		res = dialog_inputbox(prompt ? prompt : "Main Menu", | ||||
| 				      heading, 10, 75, | ||||
| 				      sym_get_string_value(menu->sym)); | ||||
| 		switch (res) { | ||||
| 		case 0: | ||||
| 			if (sym_set_string_value(menu->sym, dialog_input_result)) | ||||
| 				return; | ||||
| 			show_textbox(NULL, _("You have made an invalid entry."), 5, 43); | ||||
| 			show_textbox(NULL, "You have made an invalid entry.", 5, 43); | ||||
| 			break; | ||||
| 		case 1: | ||||
| 			show_help(menu); | ||||
| @@ -911,13 +907,13 @@ static void conf_load(void) | ||||
| 				return; | ||||
| 			if (!conf_read(dialog_input_result)) { | ||||
| 				set_config_filename(dialog_input_result); | ||||
| 				sym_set_change_count(1); | ||||
| 				conf_set_changed(true); | ||||
| 				return; | ||||
| 			} | ||||
| 			show_textbox(NULL, _("File does not exist!"), 5, 38); | ||||
| 			show_textbox(NULL, "File does not exist!", 5, 38); | ||||
| 			break; | ||||
| 		case 1: | ||||
| 			show_helptext(_("Load Alternate Configuration"), load_config_help); | ||||
| 			show_helptext("Load Alternate Configuration", load_config_help); | ||||
| 			break; | ||||
| 		case KEY_ESC: | ||||
| 			return; | ||||
| @@ -940,10 +936,10 @@ static void conf_save(void) | ||||
| 				set_config_filename(dialog_input_result); | ||||
| 				return; | ||||
| 			} | ||||
| 			show_textbox(NULL, _("Can't create file!  Probably a nonexistent directory."), 5, 60); | ||||
| 			show_textbox(NULL, "Can't create file!", 5, 60); | ||||
| 			break; | ||||
| 		case 1: | ||||
| 			show_helptext(_("Save Alternate Configuration"), save_config_help); | ||||
| 			show_helptext("Save Alternate Configuration", save_config_help); | ||||
| 			break; | ||||
| 		case KEY_ESC: | ||||
| 			return; | ||||
| @@ -961,8 +957,8 @@ static int handle_exit(void) | ||||
| 	dialog_clear(); | ||||
| 	if (conf_get_changed()) | ||||
| 		res = dialog_yesno(NULL, | ||||
| 				   _("Do you wish to save your new configuration?\n" | ||||
| 				     "(Press <ESC><ESC> to continue configuration.)"), | ||||
| 				   "Do you wish to save your new configuration?\n" | ||||
| 				     "(Press <ESC><ESC> to continue kernel configuration.)", | ||||
| 				   6, 60); | ||||
| 	else | ||||
| 		res = -1; | ||||
| @@ -971,32 +967,35 @@ static int handle_exit(void) | ||||
|  | ||||
| 	env = getenv("KCONFIG_STRICT"); | ||||
| 	if (env && *env && kconfig_warnings) { | ||||
| 		fprintf(stderr, _("\n*** ERROR: %d warnings encountered, and " | ||||
| 			"warnings are errors.\n\n"), kconfig_warnings); | ||||
| 		fprintf(stderr, "\n*** ERROR: %d warnings encountered, and " | ||||
| 			"warnings are errors.\n\n", kconfig_warnings); | ||||
| 		res = 2; | ||||
| 	} | ||||
|  | ||||
| 	switch (res) { | ||||
| 	case 0: | ||||
| 		if (conf_write(filename)) { | ||||
| 			fprintf(stderr, _("\n\n" | ||||
| 			fprintf(stderr, "\n\n" | ||||
| 					  "Error while writing of the configuration.\n" | ||||
| 					  "Your configuration changes were NOT saved." | ||||
| 					  "\n\n")); | ||||
| 					  "\n\n"); | ||||
| 			return 1; | ||||
| 		} | ||||
| 		conf_write_autoconf(0); | ||||
| 		/* fall through */ | ||||
| 	case -1: | ||||
| 		printf(_("\n\n" | ||||
| 			 "*** End of the configuration.\n" | ||||
| 			 "*** Execute 'make' to start the build or try 'make help'." | ||||
| 			 "\n\n")); | ||||
| 		if (!silent) | ||||
| 			printf("\n\n" | ||||
| 				 "*** End of the configuration.\n" | ||||
| 				 "*** Execute 'make' to start the build or try 'make help'." | ||||
| 				 "\n\n"); | ||||
| 		res = 0; | ||||
| 		break; | ||||
| 	default: | ||||
| 		fprintf(stderr, _("\n\n" | ||||
| 				  "Your configuration changes were NOT saved." | ||||
| 				  "\n\n")); | ||||
| 		if (!silent) | ||||
| 			fprintf(stderr, "\n\n" | ||||
| 					  "Your configuration changes were NOT saved." | ||||
| 					  "\n\n"); | ||||
| 		if (res != KEY_ESC) | ||||
| 			res = 0; | ||||
| 	} | ||||
| @@ -1014,12 +1013,14 @@ int main(int ac, char **av) | ||||
| 	char *mode; | ||||
| 	int res; | ||||
|  | ||||
| 	setlocale(LC_ALL, ""); | ||||
| 	bindtextdomain(PACKAGE, LOCALEDIR); | ||||
| 	textdomain(PACKAGE); | ||||
|  | ||||
| 	signal(SIGINT, sig_handler); | ||||
|  | ||||
| 	if (ac > 1 && strcmp(av[1], "-s") == 0) { | ||||
| 		silent = 1; | ||||
| 		/* Silence conf_read() until the real callback is set up */ | ||||
| 		conf_set_message_callback(NULL); | ||||
| 		av++; | ||||
| 	} | ||||
| 	conf_parse(av[1]); | ||||
| 	conf_read(NULL); | ||||
|  | ||||
| @@ -1030,8 +1031,8 @@ int main(int ac, char **av) | ||||
| 	} | ||||
|  | ||||
| 	if (init_dialog(NULL)) { | ||||
| 		fprintf(stderr, N_("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, "Your display is too small to run Menuconfig!\n"); | ||||
| 		fprintf(stderr, "It must be at least 19 lines by 80 columns.\n"); | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||
|  * Released under the terms of the GNU GPL v2.0. | ||||
|  */ | ||||
|  | ||||
| #include <ctype.h> | ||||
| @@ -9,6 +9,7 @@ | ||||
| #include <string.h> | ||||
|  | ||||
| #include "lkc.h" | ||||
| #include "internal.h" | ||||
|  | ||||
| static const char nohelp_text[] = "There is no help available for this option."; | ||||
|  | ||||
| @@ -62,15 +63,11 @@ void menu_add_entry(struct symbol *sym) | ||||
| 		menu_add_symbol(P_SYMBOL, sym, NULL); | ||||
| } | ||||
|  | ||||
| void menu_end_entry(void) | ||||
| { | ||||
| } | ||||
|  | ||||
| struct menu *menu_add_menu(void) | ||||
| { | ||||
| 	menu_end_entry(); | ||||
| 	last_entry_ptr = ¤t_entry->list; | ||||
| 	return current_menu = current_entry; | ||||
| 	current_menu = current_entry; | ||||
| 	return current_menu; | ||||
| } | ||||
|  | ||||
| void menu_end_menu(void) | ||||
| @@ -79,19 +76,23 @@ void menu_end_menu(void) | ||||
| 	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) | ||||
| 		return e; | ||||
|  | ||||
| 	switch (e->type) { | ||||
| 	case E_NOT: | ||||
| 		e->left.expr = menu_check_dep(e->left.expr); | ||||
| 		e->left.expr = rewrite_m(e->left.expr); | ||||
| 		break; | ||||
| 	case E_OR: | ||||
| 	case E_AND: | ||||
| 		e->left.expr = menu_check_dep(e->left.expr); | ||||
| 		e->right.expr = menu_check_dep(e->right.expr); | ||||
| 		e->left.expr = rewrite_m(e->left.expr); | ||||
| 		e->right.expr = rewrite_m(e->right.expr); | ||||
| 		break; | ||||
| 	case E_SYMBOL: | ||||
| 		/* change 'm' into 'm' && MODULES */ | ||||
| @@ -106,7 +107,7 @@ static struct expr *menu_check_dep(struct expr *e) | ||||
|  | ||||
| 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) | ||||
| @@ -125,59 +126,74 @@ void menu_set_type(int 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) | ||||
| static 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->expr = expr; | ||||
| 	prop->visible.expr = menu_check_dep(dep); | ||||
| 	prop->visible.expr = dep; | ||||
|  | ||||
| 	if (prompt) { | ||||
| 		if (isspace(*prompt)) { | ||||
| 			prop_warn(prop, "leading whitespace ignored"); | ||||
| 			while (isspace(*prompt)) | ||||
| 				prompt++; | ||||
| 		} | ||||
| 		if (current_entry->prompt && current_entry != &rootmenu) | ||||
| 			prop_warn(prop, "prompt redefined"); | ||||
| 	/* append property to the prop list of symbol */ | ||||
| 	if (current_entry->sym) { | ||||
| 		struct property **propp; | ||||
|  | ||||
| 		/* Apply all upper menus' visibilities to actual prompts. */ | ||||
| 		if(type == P_PROMPT) { | ||||
| 			struct menu *menu = current_entry; | ||||
|  | ||||
| 			while ((menu = menu->parent) != NULL) { | ||||
| 				struct expr *dup_expr; | ||||
|  | ||||
| 				if (!menu->visibility) | ||||
| 					continue; | ||||
| 				/* | ||||
| 				 * Do not add a reference to the | ||||
| 				 * menu's visibility expression but | ||||
| 				 * use a copy of it.  Otherwise the | ||||
| 				 * expression reduction functions | ||||
| 				 * will modify expressions that have | ||||
| 				 * multiple references which can | ||||
| 				 * cause unwanted side effects. | ||||
| 				 */ | ||||
| 				dup_expr = expr_copy(menu->visibility); | ||||
|  | ||||
| 				prop->visible.expr | ||||
| 					= expr_alloc_and(prop->visible.expr, | ||||
| 							 dup_expr); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		current_entry->prompt = prop; | ||||
| 		for (propp = ¤t_entry->sym->prop; | ||||
| 		     *propp; | ||||
| 		     propp = &(*propp)->next) | ||||
| 			; | ||||
| 		*propp = prop; | ||||
| 	} | ||||
| 	prop->text = prompt; | ||||
|  | ||||
| 	return prop; | ||||
| } | ||||
|  | ||||
| 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) | ||||
| { | ||||
| 	return menu_add_prop(type, prompt, NULL, dep); | ||||
| 	struct property *prop = menu_add_prop(type, NULL, dep); | ||||
|  | ||||
| 	if (isspace(*prompt)) { | ||||
| 		prop_warn(prop, "leading whitespace ignored"); | ||||
| 		while (isspace(*prompt)) | ||||
| 			prompt++; | ||||
| 	} | ||||
| 	if (current_entry->prompt) | ||||
| 		prop_warn(prop, "prompt redefined"); | ||||
|  | ||||
| 	/* Apply all upper menus' visibilities to actual prompts. */ | ||||
| 	if (type == P_PROMPT) { | ||||
| 		struct menu *menu = current_entry; | ||||
|  | ||||
| 		while ((menu = menu->parent) != NULL) { | ||||
| 			struct expr *dup_expr; | ||||
|  | ||||
| 			if (!menu->visibility) | ||||
| 				continue; | ||||
| 			/* | ||||
| 			 * Do not add a reference to the menu's visibility | ||||
| 			 * expression but use a copy of it. Otherwise the | ||||
| 			 * expression reduction functions will modify | ||||
| 			 * expressions that have multiple references which | ||||
| 			 * can cause unwanted side effects. | ||||
| 			 */ | ||||
| 			dup_expr = expr_copy(menu->visibility); | ||||
|  | ||||
| 			prop->visible.expr = expr_alloc_and(prop->visible.expr, | ||||
| 							    dup_expr); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	current_entry->prompt = prop; | ||||
| 	prop->text = prompt; | ||||
|  | ||||
| 	return prop; | ||||
| } | ||||
|  | ||||
| void menu_add_visibility(struct expr *expr) | ||||
| @@ -188,39 +204,12 @@ void menu_add_visibility(struct expr *expr) | ||||
|  | ||||
| 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) | ||||
| { | ||||
| 	menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); | ||||
| } | ||||
|  | ||||
| void menu_add_option(int token, char *arg) | ||||
| { | ||||
| 	switch (token) { | ||||
| 	case T_OPT_MODULES: | ||||
| 		if (modules_sym) | ||||
| 			zconf_error("symbol '%s' redefines option 'modules'" | ||||
| 				    " already defined by symbol '%s'", | ||||
| 				    current_entry->sym->name, | ||||
| 				    modules_sym->name | ||||
| 				    ); | ||||
| 		modules_sym = current_entry->sym; | ||||
| 		break; | ||||
| 	case T_OPT_DEFCONFIG_LIST: | ||||
| 		if (!sym_defconfig_list) | ||||
| 			sym_defconfig_list = current_entry->sym; | ||||
| 		else if (sym_defconfig_list != current_entry->sym) | ||||
| 			zconf_error("trying to redefine defconfig symbol"); | ||||
| 		break; | ||||
| 	case T_OPT_ENV: | ||||
| 		prop_add_env(arg); | ||||
| 		break; | ||||
| 	case T_OPT_ALLNOCONFIG_Y: | ||||
| 		current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y; | ||||
| 		break; | ||||
| 	} | ||||
| 	menu_add_prop(type, expr_alloc_symbol(sym), dep); | ||||
| } | ||||
|  | ||||
| static int menu_validate_number(struct symbol *sym, struct symbol *sym2) | ||||
| @@ -233,6 +222,8 @@ static void sym_check_prop(struct symbol *sym) | ||||
| { | ||||
| 	struct property *prop; | ||||
| 	struct symbol *sym2; | ||||
| 	char *use; | ||||
|  | ||||
| 	for (prop = sym->prop; prop; prop = prop->next) { | ||||
| 		switch (prop->type) { | ||||
| 		case P_DEFAULT: | ||||
| @@ -250,20 +241,32 @@ static void sym_check_prop(struct symbol *sym) | ||||
| 					    "'%s': number is invalid", | ||||
| 					    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; | ||||
| 		case P_SELECT: | ||||
| 		case P_IMPLY: | ||||
| 			use = prop->type == P_SELECT ? "select" : "imply"; | ||||
| 			sym2 = prop_get_symbol(prop); | ||||
| 			if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) | ||||
| 				prop_warn(prop, | ||||
| 				    "config symbol '%s' uses select, but is " | ||||
| 				    "not boolean or tristate", sym->name); | ||||
| 				    "config symbol '%s' uses %s, but is " | ||||
| 				    "not bool or tristate", sym->name, use); | ||||
| 			else if (sym2->type != S_UNKNOWN && | ||||
| 				 sym2->type != S_BOOLEAN && | ||||
| 				 sym2->type != S_TRISTATE) | ||||
| 				prop_warn(prop, | ||||
| 				    "'%s' has wrong type. 'select' only " | ||||
| 				    "accept arguments of boolean and " | ||||
| 				    "tristate type", sym2->name); | ||||
| 				    "'%s' has wrong type. '%s' only " | ||||
| 				    "accept arguments of bool and " | ||||
| 				    "tristate type", sym2->name, use); | ||||
| 			break; | ||||
| 		case P_RANGE: | ||||
| 			if (sym->type != S_INT && sym->type != S_HEX) | ||||
| @@ -288,6 +291,11 @@ void menu_finalize(struct menu *parent) | ||||
|  | ||||
| 	sym = parent->sym; | ||||
| 	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->type == S_UNKNOWN) { | ||||
| 				/* find the first choice value to find out choice type */ | ||||
| @@ -305,65 +313,167 @@ void menu_finalize(struct menu *parent) | ||||
| 				if (menu->sym && menu->sym->type == S_UNKNOWN) | ||||
| 					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) { | ||||
| 			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_eliminate_dups(basedep); | ||||
| 			menu->dep = basedep; | ||||
|  | ||||
| 			if (menu->sym) | ||||
| 				/* | ||||
| 				 * Note: For symbols, all prompts are included | ||||
| 				 * too in the symbol's own property list | ||||
| 				 */ | ||||
| 				prop = menu->sym->prop; | ||||
| 			else | ||||
| 				/* | ||||
| 				 * For non-symbol menu nodes, we just need to | ||||
| 				 * handle the prompt | ||||
| 				 */ | ||||
| 				prop = menu->prompt; | ||||
|  | ||||
| 			/* For each property... */ | ||||
| 			for (; prop; prop = prop->next) { | ||||
| 				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; | ||||
| 				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_eliminate_dups(dep); | ||||
| 				if (menu->sym && menu->sym->type != S_TRISTATE) | ||||
| 					dep = expr_trans_bool(dep); | ||||
| 				prop->visible.expr = dep; | ||||
|  | ||||
| 				/* | ||||
| 				 * Handle selects and implies, which modify the | ||||
| 				 * dependencies of the selected/implied symbol | ||||
| 				 */ | ||||
| 				if (prop->type == P_SELECT) { | ||||
| 					struct symbol *es = prop_get_symbol(prop); | ||||
| 					es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, | ||||
| 							expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); | ||||
| 				} 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) | ||||
| 			menu_finalize(menu); | ||||
| 	} 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 = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); | ||||
| 		basedep = expr_eliminate_dups(expr_transform(basedep)); | ||||
|  | ||||
| 		/* Examine consecutive elements after sym */ | ||||
| 		last_menu = NULL; | ||||
| 		for (menu = parent->next; menu; menu = menu->next) { | ||||
| 			dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; | ||||
| 			if (!expr_contains_symbol(dep, sym)) | ||||
| 				/* No dependency, quit */ | ||||
| 				break; | ||||
| 			if (expr_depends_symbol(dep, sym)) | ||||
| 				/* Absolute dependency, put in submenu */ | ||||
| 				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_eliminate_dups(expr_transform(dep)); | ||||
| 			dep2 = expr_copy(basedep); | ||||
| 			expr_eliminate_eq(&dep, &dep2); | ||||
| 			expr_free(dep); | ||||
| 			if (!expr_is_yes(dep2)) { | ||||
| 				/* Not superset, quit */ | ||||
| 				expr_free(dep2); | ||||
| 				break; | ||||
| 			} | ||||
| 			/* Superset, put in submenu */ | ||||
| 			expr_free(dep2); | ||||
| 		next: | ||||
| 			menu_finalize(menu); | ||||
| 			menu->parent = parent; | ||||
| 			last_menu = menu; | ||||
| 		} | ||||
| 		expr_free(basedep); | ||||
| 		if (last_menu) { | ||||
| 			parent->list = parent->next; | ||||
| 			parent->next = last_menu->next; | ||||
| @@ -412,6 +522,35 @@ void menu_finalize(struct menu *parent) | ||||
| 			*ep = expr_alloc_one(E_LIST, NULL); | ||||
| 			(*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)) { | ||||
| 			for (last_menu = menu->list; ; last_menu = last_menu->next) { | ||||
| 				last_menu->parent = parent; | ||||
| @@ -436,6 +575,15 @@ void menu_finalize(struct menu *parent) | ||||
| 		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) { | ||||
| 		sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, | ||||
| 				expr_alloc_and(parent->prompt->visible.expr, | ||||
| @@ -477,7 +625,7 @@ bool menu_is_visible(struct menu *menu) | ||||
|  | ||||
| 	if (menu->visibility) { | ||||
| 		if (expr_calc_value(menu->visibility) == no) | ||||
| 			return no; | ||||
| 			return false; | ||||
| 	} | ||||
|  | ||||
| 	sym = menu->sym; | ||||
| @@ -543,6 +691,21 @@ const char *menu_get_help(struct menu *menu) | ||||
| 		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, | ||||
| 			   struct list_head *head) | ||||
| { | ||||
| @@ -550,7 +713,20 @@ static void get_prompt_str(struct gstr *r, struct property *prop, | ||||
| 	struct menu *submenu[8], *menu, *location = 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; | ||||
| 	for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) { | ||||
| 		bool accessible = menu_is_visible(menu); | ||||
| @@ -583,16 +759,16 @@ static void get_prompt_str(struct gstr *r, struct property *prop, | ||||
| 	} | ||||
|  | ||||
| 	if (i > 0) { | ||||
| 		str_printf(r, _("  Location:\n")); | ||||
| 		str_printf(r, "  Location:\n"); | ||||
| 		for (j = 4; --i >= 0; j += 2) { | ||||
| 			menu = submenu[i]; | ||||
| 			if (jump && menu == location) | ||||
| 				jump->offset = strlen(r->s); | ||||
| 			str_printf(r, "%*c-> %s", j, ' ', | ||||
| 				   _(menu_get_prompt(menu))); | ||||
| 				   menu_get_prompt(menu)); | ||||
| 			if (menu->sym) { | ||||
| 				str_printf(r, " (%s [=%s])", menu->sym->name ? | ||||
| 					menu->sym->name : _("<choice>"), | ||||
| 					menu->sym->name : "<choice>", | ||||
| 					sym_get_string_value(menu->sym)); | ||||
| 			} | ||||
| 			str_append(r, "\n"); | ||||
| @@ -600,25 +776,30 @@ static void get_prompt_str(struct gstr *r, struct property *prop, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * get property of type P_SYMBOL | ||||
|  */ | ||||
| static struct property *get_symbol_prop(struct symbol *sym) | ||||
| static void get_symbol_props_str(struct gstr *r, struct symbol *sym, | ||||
| 				 enum prop_type tok, const char *prefix) | ||||
| { | ||||
| 	struct property *prop = NULL; | ||||
| 	bool hit = false; | ||||
| 	struct property *prop; | ||||
|  | ||||
| 	for_all_properties(sym, prop, P_SYMBOL) | ||||
| 		break; | ||||
| 	return prop; | ||||
| 	for_all_properties(sym, prop, tok) { | ||||
| 		if (!hit) { | ||||
| 			str_append(r, prefix); | ||||
| 			hit = true; | ||||
| 		} else | ||||
| 			str_printf(r, " && "); | ||||
| 		expr_gstr_print(prop->expr, r); | ||||
| 	} | ||||
| 	if (hit) | ||||
| 		str_append(r, "\n"); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * head is optional and may be NULL | ||||
|  */ | ||||
| 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) | ||||
| { | ||||
| 	bool hit; | ||||
| 	struct property *prop; | ||||
|  | ||||
| 	if (sym && sym->name) { | ||||
| @@ -634,36 +815,36 @@ 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); | ||||
| 	if (prop) { | ||||
| 		str_printf(r, _("  Defined at %s:%d\n"), prop->menu->file->name, | ||||
| 			prop->menu->lineno); | ||||
| 		if (!expr_is_yes(prop->visible.expr)) { | ||||
| 			str_append(r, _("  Depends on: ")); | ||||
| 			expr_gstr_print(prop->visible.expr, r); | ||||
| 			str_append(r, "\n"); | ||||
| 	/* Print the definitions with prompts before the ones without */ | ||||
| 	for_all_properties(sym, prop, P_SYMBOL) { | ||||
| 		if (prop->menu->prompt) { | ||||
| 			get_def_str(r, prop->menu); | ||||
| 			get_prompt_str(r, prop->menu->prompt, head); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	hit = false; | ||||
| 	for_all_properties(sym, prop, P_SELECT) { | ||||
| 		if (!hit) { | ||||
| 			str_append(r, "  Selects: "); | ||||
| 			hit = true; | ||||
| 		} else | ||||
| 			str_printf(r, " && "); | ||||
| 		expr_gstr_print(prop->expr, r); | ||||
| 	for_all_properties(sym, prop, P_SYMBOL) { | ||||
| 		if (!prop->menu->prompt) { | ||||
| 			get_def_str(r, prop->menu); | ||||
| 			get_dep_str(r, prop->menu->dep, "  Depends on: "); | ||||
| 		} | ||||
| 	} | ||||
| 	if (hit) | ||||
| 		str_append(r, "\n"); | ||||
|  | ||||
| 	get_symbol_props_str(r, sym, P_SELECT, "Selects: "); | ||||
| 	if (sym->rev_dep.expr) { | ||||
| 		str_append(r, _("  Selected by: ")); | ||||
| 		expr_gstr_print(sym->rev_dep.expr, r); | ||||
| 		str_append(r, "\n"); | ||||
| 		expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, "Selected by [y]:\n"); | ||||
| 		expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, "Selected by [m]:\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"); | ||||
| } | ||||
|  | ||||
| @@ -676,7 +857,7 @@ struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head) | ||||
| 	for (i = 0; sym_arr && (sym = sym_arr[i]); i++) | ||||
| 		get_symbol_str(&res, sym, head); | ||||
| 	if (!i) | ||||
| 		str_append(&res, _("No matches found.\n")); | ||||
| 		str_append(&res, "No matches found.\n"); | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| @@ -691,7 +872,7 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help) | ||||
| 			str_printf(help, "%s%s:\n\n", CONFIG_, sym->name); | ||||
| 		help_text = menu_get_help(menu); | ||||
| 	} | ||||
| 	str_printf(help, "%s\n", _(help_text)); | ||||
| 	str_printf(help, "%s\n", help_text); | ||||
| 	if (sym) | ||||
| 		get_symbol_str(help, sym, NULL); | ||||
| } | ||||
|   | ||||
							
								
								
									
										189
									
								
								util/kconfig/merge_config.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										189
									
								
								util/kconfig/merge_config.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,189 @@ | ||||
| #!/bin/sh | ||||
| # SPDX-License-Identifier: GPL-2.0 | ||||
| # | ||||
| #  merge_config.sh - Takes a list of config fragment values, and merges | ||||
| #  them one by one. Provides warnings on overridden values, and specified | ||||
| #  values that did not make it to the resulting .config file (due to missed | ||||
| #  dependencies or config symbol removal). | ||||
| # | ||||
| #  Portions reused from kconf_check and generate_cfg: | ||||
| #  http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/kconf_check | ||||
| #  http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/generate_cfg | ||||
| # | ||||
| #  Copyright (c) 2009-2010 Wind River Systems, Inc. | ||||
| #  Copyright 2011 Linaro | ||||
|  | ||||
| set -e | ||||
|  | ||||
| clean_up() { | ||||
| 	rm -f $TMP_FILE | ||||
| 	rm -f $MERGE_FILE | ||||
| } | ||||
|  | ||||
| usage() { | ||||
| 	echo "Usage: $0 [OPTIONS] [CONFIG [...]]" | ||||
| 	echo "  -h    display this help text" | ||||
| 	echo "  -m    only merge the fragments, do not execute the make command" | ||||
| 	echo "  -n    use allnoconfig instead of alldefconfig" | ||||
| 	echo "  -r    list redundant entries when merging fragments" | ||||
| 	echo "  -y    make builtin have precedence over modules" | ||||
| 	echo "  -O    dir to put generated output files.  Consider setting \$KCONFIG_CONFIG instead." | ||||
| 	echo | ||||
| 	echo "Used prefix: '$CONFIG_PREFIX'. You can redefine it with \$CONFIG_ environment variable." | ||||
| } | ||||
|  | ||||
| RUNMAKE=true | ||||
| ALLTARGET=alldefconfig | ||||
| WARNREDUN=false | ||||
| BUILTIN=false | ||||
| OUTPUT=. | ||||
| CONFIG_PREFIX=${CONFIG_-CONFIG_} | ||||
|  | ||||
| while true; do | ||||
| 	case $1 in | ||||
| 	"-n") | ||||
| 		ALLTARGET=allnoconfig | ||||
| 		shift | ||||
| 		continue | ||||
| 		;; | ||||
| 	"-m") | ||||
| 		RUNMAKE=false | ||||
| 		shift | ||||
| 		continue | ||||
| 		;; | ||||
| 	"-h") | ||||
| 		usage | ||||
| 		exit | ||||
| 		;; | ||||
| 	"-r") | ||||
| 		WARNREDUN=true | ||||
| 		shift | ||||
| 		continue | ||||
| 		;; | ||||
| 	"-y") | ||||
| 		BUILTIN=true | ||||
| 		shift | ||||
| 		continue | ||||
| 		;; | ||||
| 	"-O") | ||||
| 		if [ -d $2 ];then | ||||
| 			OUTPUT=$(echo $2 | sed 's/\/*$//') | ||||
| 		else | ||||
| 			echo "output directory $2 does not exist" 1>&2 | ||||
| 			exit 1 | ||||
| 		fi | ||||
| 		shift 2 | ||||
| 		continue | ||||
| 		;; | ||||
| 	*) | ||||
| 		break | ||||
| 		;; | ||||
| 	esac | ||||
| done | ||||
|  | ||||
| if [ "$#" -lt 1 ] ; then | ||||
| 	usage | ||||
| 	exit | ||||
| fi | ||||
|  | ||||
| if [ -z "$KCONFIG_CONFIG" ]; then | ||||
| 	if [ "$OUTPUT" != . ]; then | ||||
| 		KCONFIG_CONFIG=$(readlink -m -- "$OUTPUT/.config") | ||||
| 	else | ||||
| 		KCONFIG_CONFIG=.config | ||||
| 	fi | ||||
| fi | ||||
|  | ||||
| INITFILE=$1 | ||||
| shift; | ||||
|  | ||||
| if [ ! -r "$INITFILE" ]; then | ||||
| 	echo "The base file '$INITFILE' does not exist.  Exit." >&2 | ||||
| 	exit 1 | ||||
| fi | ||||
|  | ||||
| MERGE_LIST=$* | ||||
| SED_CONFIG_EXP1="s/^\(${CONFIG_PREFIX}[a-zA-Z0-9_]*\)=.*/\1/p" | ||||
| SED_CONFIG_EXP2="s/^# \(${CONFIG_PREFIX}[a-zA-Z0-9_]*\) is not set$/\1/p" | ||||
|  | ||||
| TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX) | ||||
| MERGE_FILE=$(mktemp ./.merge_tmp.config.XXXXXXXXXX) | ||||
|  | ||||
| echo "Using $INITFILE as base" | ||||
|  | ||||
| trap clean_up EXIT | ||||
|  | ||||
| cat $INITFILE > $TMP_FILE | ||||
|  | ||||
| # Merge files, printing warnings on overridden values | ||||
| for ORIG_MERGE_FILE in $MERGE_LIST ; do | ||||
| 	echo "Merging $ORIG_MERGE_FILE" | ||||
| 	if [ ! -r "$ORIG_MERGE_FILE" ]; then | ||||
| 		echo "The merge file '$ORIG_MERGE_FILE' does not exist.  Exit." >&2 | ||||
| 		exit 1 | ||||
| 	fi | ||||
| 	cat $ORIG_MERGE_FILE > $MERGE_FILE | ||||
| 	CFG_LIST=$(sed -n -e "$SED_CONFIG_EXP1" -e "$SED_CONFIG_EXP2" $MERGE_FILE) | ||||
|  | ||||
| 	for CFG in $CFG_LIST ; do | ||||
| 		grep -q -w $CFG $TMP_FILE || continue | ||||
| 		PREV_VAL=$(grep -w $CFG $TMP_FILE) | ||||
| 		NEW_VAL=$(grep -w $CFG $MERGE_FILE) | ||||
| 		BUILTIN_FLAG=false | ||||
| 		if [ "$BUILTIN" = "true" ] && [ "${NEW_VAL#CONFIG_*=}" = "m" ] && [ "${PREV_VAL#CONFIG_*=}" = "y" ]; then | ||||
| 			echo Previous  value: $PREV_VAL | ||||
| 			echo New value:       $NEW_VAL | ||||
| 			echo -y passed, will not demote y to m | ||||
| 			echo | ||||
| 			BUILTIN_FLAG=true | ||||
| 		elif [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then | ||||
| 			echo Value of $CFG is redefined by fragment $ORIG_MERGE_FILE: | ||||
| 			echo Previous  value: $PREV_VAL | ||||
| 			echo New value:       $NEW_VAL | ||||
| 			echo | ||||
| 		elif [ "$WARNREDUN" = "true" ]; then | ||||
| 			echo Value of $CFG is redundant by fragment $ORIG_MERGE_FILE: | ||||
| 		fi | ||||
| 		if [ "$BUILTIN_FLAG" = "false" ]; then | ||||
| 			sed -i "/$CFG[ =]/d" $TMP_FILE | ||||
| 		else | ||||
| 			sed -i "/$CFG[ =]/d" $MERGE_FILE | ||||
| 		fi | ||||
| 	done | ||||
| 	cat $MERGE_FILE >> $TMP_FILE | ||||
| done | ||||
|  | ||||
| if [ "$RUNMAKE" = "false" ]; then | ||||
| 	cp -T -- "$TMP_FILE" "$KCONFIG_CONFIG" | ||||
| 	echo "#" | ||||
| 	echo "# merged configuration written to $KCONFIG_CONFIG (needs make)" | ||||
| 	echo "#" | ||||
| 	exit | ||||
| fi | ||||
|  | ||||
| # If we have an output dir, setup the O= argument, otherwise leave | ||||
| # it blank, since O=. will create an unnecessary ./source softlink | ||||
| OUTPUT_ARG="" | ||||
| if [ "$OUTPUT" != "." ] ; then | ||||
| 	OUTPUT_ARG="O=$OUTPUT" | ||||
| fi | ||||
|  | ||||
|  | ||||
| # Use the merged file as the starting point for: | ||||
| # alldefconfig: Fills in any missing symbols with Kconfig default | ||||
| # allnoconfig: Fills in any missing symbols with # CONFIG_* is not set | ||||
| make KCONFIG_ALLCONFIG=$TMP_FILE $OUTPUT_ARG $ALLTARGET | ||||
|  | ||||
|  | ||||
| # Check all specified config values took (might have missed-dependency issues) | ||||
| for CFG in $(sed -n -e "$SED_CONFIG_EXP1" -e "$SED_CONFIG_EXP2" $TMP_FILE); do | ||||
|  | ||||
| 	REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE) | ||||
| 	ACTUAL_VAL=$(grep -w -e "$CFG" "$KCONFIG_CONFIG" || true) | ||||
| 	if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then | ||||
| 		echo "Value requested for $CFG not in final .config" | ||||
| 		echo "Requested value:  $REQUESTED_VAL" | ||||
| 		echo "Actual value:     $ACTUAL_VAL" | ||||
| 		echo "" | ||||
| 	fi | ||||
| done | ||||
							
								
								
									
										50
									
								
								util/kconfig/nconf-cfg.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										50
									
								
								util/kconfig/nconf-cfg.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| #!/bin/sh | ||||
| # SPDX-License-Identifier: GPL-2.0 | ||||
|  | ||||
| PKG="ncursesw menuw panelw" | ||||
| PKG2="ncurses menu panel" | ||||
|  | ||||
| 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 -lmenuw -lpanelw\" | ||||
| 	exit 0 | ||||
| fi | ||||
|  | ||||
| if [ -f /usr/include/ncurses/ncurses.h ]; then | ||||
| 	echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\" | ||||
| 	echo libs=\"-lncurses -lmenu -lpanel\" | ||||
| 	exit 0 | ||||
| fi | ||||
|  | ||||
| if [ -f /usr/include/ncurses.h ]; then | ||||
| 	echo cflags=\"-D_GNU_SOURCE\" | ||||
| 	echo libs=\"-lncurses -lmenu -lpanel\" | ||||
| 	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,14 +1,14 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com? | ||||
|  * Released under the terms of the GNU GPL v2.0. | ||||
|  * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com> | ||||
|  * | ||||
|  * Derived from menuconfig. | ||||
|  * | ||||
|  */ | ||||
| #ifndef _GNU_SOURCE | ||||
| #define _GNU_SOURCE | ||||
| #endif | ||||
| #include <string.h> | ||||
| #include <strings.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "lkc.h" | ||||
| @@ -17,7 +17,7 @@ | ||||
|  | ||||
| int kconfig_warnings = 0; | ||||
|  | ||||
| static const char nconf_global_help[] = N_( | ||||
| static const char nconf_global_help[] = | ||||
| "Help windows\n" | ||||
| "------------\n" | ||||
| "o  Global help:  Unless in a data entry window, pressing <F1> will give \n" | ||||
| @@ -132,8 +132,8 @@ static const char nconf_global_help[] = N_( | ||||
| "\n" | ||||
| "Note that this mode can eventually be a little more CPU expensive than\n" | ||||
| "the default mode, especially with a larger number of unfolded submenus.\n" | ||||
| "\n"), | ||||
| menu_no_f_instructions[] = N_( | ||||
| "\n", | ||||
| menu_no_f_instructions[] = | ||||
| "Legend:  [*] built-in  [ ] excluded  <M> module  < > module capable.\n" | ||||
| "Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" | ||||
| "\n" | ||||
| @@ -149,8 +149,8 @@ menu_no_f_instructions[] = N_( | ||||
| "You do not have function keys support.\n" | ||||
| "Press <1> instead of <F1>, <2> instead of <F2>, etc.\n" | ||||
| "For verbose global help use key <1>.\n" | ||||
| "For help related to the current menu entry press <?> or <h>.\n"), | ||||
| menu_instructions[] = N_( | ||||
| "For help related to the current menu entry press <?> or <h>.\n", | ||||
| menu_instructions[] = | ||||
| "Legend:  [*] built-in  [ ] excluded  <M> module  < > module capable.\n" | ||||
| "Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" | ||||
| "\n" | ||||
| @@ -165,30 +165,30 @@ menu_instructions[] = N_( | ||||
| "\n" | ||||
| "Pressing <1> may be used instead of <F1>, <2> instead of <F2>, etc.\n" | ||||
| "For verbose global help press <F1>.\n" | ||||
| "For help related to the current menu entry press <?> or <h>.\n"), | ||||
| radiolist_instructions[] = N_( | ||||
| "For help related to the current menu entry press <?> or <h>.\n", | ||||
| radiolist_instructions[] = | ||||
| "Press <Up>, <Down>, <Home> or <End> to navigate a radiolist, select\n" | ||||
| "with <Space>.\n" | ||||
| "For help related to the current entry press <?> or <h>.\n" | ||||
| "For global help press <F1>.\n"), | ||||
| inputbox_instructions_int[] = N_( | ||||
| "For global help press <F1>.\n", | ||||
| inputbox_instructions_int[] = | ||||
| "Please enter a decimal value.\n" | ||||
| "Fractions will not be accepted.\n" | ||||
| "Press <Enter> to apply, <Esc> to cancel."), | ||||
| inputbox_instructions_hex[] = N_( | ||||
| "Press <Enter> to apply, <Esc> to cancel.", | ||||
| inputbox_instructions_hex[] = | ||||
| "Please enter a hexadecimal value.\n" | ||||
| "Press <Enter> to apply, <Esc> to cancel."), | ||||
| inputbox_instructions_string[] = N_( | ||||
| "Press <Enter> to apply, <Esc> to cancel.", | ||||
| inputbox_instructions_string[] = | ||||
| "Please enter a string value.\n" | ||||
| "Press <Enter> to apply, <Esc> to cancel."), | ||||
| setmod_text[] = N_( | ||||
| "Press <Enter> to apply, <Esc> to cancel.", | ||||
| setmod_text[] = | ||||
| "This feature depends on another feature which has been configured as a\n" | ||||
| "module.  As a result, the current feature will be built as a module too."), | ||||
| load_config_text[] = N_( | ||||
| "module.  As a result, the current feature will be built as a module too.", | ||||
| load_config_text[] = | ||||
| "Enter the name of the configuration file you wish to load.\n" | ||||
| "Accept the name shown to restore the configuration you last\n" | ||||
| "retrieved.  Leave empty to abort."), | ||||
| load_config_help[] = N_( | ||||
| "retrieved.  Leave empty to abort.", | ||||
| load_config_help[] = | ||||
| "For various reasons, one may wish to keep several different\n" | ||||
| "configurations available on a single machine.\n" | ||||
| "\n" | ||||
| @@ -196,11 +196,11 @@ load_config_help[] = N_( | ||||
| "default one, entering its name here will allow you to load and modify\n" | ||||
| "that configuration.\n" | ||||
| "\n" | ||||
| "Leave empty to abort.\n"), | ||||
| save_config_text[] = N_( | ||||
| "Leave empty to abort.\n", | ||||
| save_config_text[] = | ||||
| "Enter a filename to which this configuration should be saved\n" | ||||
| "as an alternate.  Leave empty to abort."), | ||||
| save_config_help[] = N_( | ||||
| "as an alternate.  Leave empty to abort.", | ||||
| save_config_help[] = | ||||
| "For various reasons, one may wish to keep several different\n" | ||||
| "configurations available on a single machine.\n" | ||||
| "\n" | ||||
| @@ -208,8 +208,8 @@ save_config_help[] = N_( | ||||
| "and use the current configuration as an alternate to whatever\n" | ||||
| "configuration options you have selected at that time.\n" | ||||
| "\n" | ||||
| "Leave empty to abort.\n"), | ||||
| search_help[] = N_( | ||||
| "Leave empty to abort.\n", | ||||
| search_help[] = | ||||
| "Search for symbols (configuration variable names CONFIG_*) and display\n" | ||||
| "their relations.  Regular expressions are supported.\n" | ||||
| "Example:  Search for \"^FOO\".\n" | ||||
| @@ -246,7 +246,7 @@ search_help[] = N_( | ||||
| "USB  => find all symbols containing USB\n" | ||||
| "^USB => find all symbols starting with USB\n" | ||||
| "USB$ => find all symbols ending with USB\n" | ||||
| "\n"); | ||||
| "\n"; | ||||
|  | ||||
| struct mitem { | ||||
| 	char str[256]; | ||||
| @@ -270,10 +270,10 @@ static int mwin_max_cols; | ||||
| static MENU *curses_menu; | ||||
| static ITEM *curses_menu_items[MAX_MENU_ITEMS]; | ||||
| static struct mitem k_menu_items[MAX_MENU_ITEMS]; | ||||
| static int items_num; | ||||
| static unsigned int items_num; | ||||
| static int global_exit; | ||||
| /* the currently selected button */ | ||||
| const char *current_instructions = menu_instructions; | ||||
| static const char *current_instructions = menu_instructions; | ||||
|  | ||||
| static char *dialog_input_result; | ||||
| static int dialog_input_result_len; | ||||
| @@ -307,7 +307,7 @@ struct function_keys { | ||||
| }; | ||||
|  | ||||
| static const int function_keys_num = 9; | ||||
| struct function_keys function_keys[] = { | ||||
| static struct function_keys function_keys[] = { | ||||
| 	{ | ||||
| 		.key_str = "F1", | ||||
| 		.func = "Help", | ||||
| @@ -372,25 +372,25 @@ static void print_function_line(void) | ||||
| 	int lines = getmaxy(stdscr); | ||||
|  | ||||
| 	for (i = 0; i < function_keys_num; i++) { | ||||
| 		(void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]); | ||||
| 		wattrset(main_window, attr_function_highlight); | ||||
| 		mvwprintw(main_window, lines-3, offset, | ||||
| 				"%s", | ||||
| 				function_keys[i].key_str); | ||||
| 		(void) wattrset(main_window, attributes[FUNCTION_TEXT]); | ||||
| 		wattrset(main_window, attr_function_text); | ||||
| 		offset += strlen(function_keys[i].key_str); | ||||
| 		mvwprintw(main_window, lines-3, | ||||
| 				offset, "%s", | ||||
| 				function_keys[i].func); | ||||
| 		offset += strlen(function_keys[i].func) + skip; | ||||
| 	} | ||||
| 	(void) wattrset(main_window, attributes[NORMAL]); | ||||
| 	wattrset(main_window, attr_normal); | ||||
| } | ||||
|  | ||||
| /* help */ | ||||
| static void handle_f1(int *key, struct menu *current_item) | ||||
| { | ||||
| 	show_scroll_win(main_window, | ||||
| 			_("Global help"), _(nconf_global_help)); | ||||
| 			"Global help", nconf_global_help); | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| @@ -405,8 +405,8 @@ static void handle_f2(int *key, struct menu *current_item) | ||||
| static void handle_f3(int *key, struct menu *current_item) | ||||
| { | ||||
| 	show_scroll_win(main_window, | ||||
| 			_("Short help"), | ||||
| 			_(current_instructions)); | ||||
| 			"Short help", | ||||
| 			current_instructions); | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| @@ -414,7 +414,7 @@ static void handle_f3(int *key, struct menu *current_item) | ||||
| static void handle_f4(int *key, struct menu *current_item) | ||||
| { | ||||
| 	int res = btn_dialog(main_window, | ||||
| 			_("Show all symbols?"), | ||||
| 			"Show all symbols?", | ||||
| 			2, | ||||
| 			"   <Show All>   ", | ||||
| 			"<Don't show all>"); | ||||
| @@ -498,19 +498,23 @@ typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN, | ||||
| /* return the index of the matched item, or -1 if no such item exists */ | ||||
| static int get_mext_match(const char *match_str, match_f flag) | ||||
| { | ||||
| 	int match_start = item_index(current_item(curses_menu)); | ||||
| 	int index; | ||||
| 	int match_start, index; | ||||
|  | ||||
| 	/* Do not search if the menu is empty (i.e. items_num == 0) */ | ||||
| 	match_start = item_index(current_item(curses_menu)); | ||||
| 	if (match_start == ERR) | ||||
| 		return -1; | ||||
|  | ||||
| 	if (flag == FIND_NEXT_MATCH_DOWN) | ||||
| 		++match_start; | ||||
| 	else if (flag == FIND_NEXT_MATCH_UP) | ||||
| 		--match_start; | ||||
|  | ||||
| 	match_start = (match_start + items_num) % items_num; | ||||
| 	index = match_start; | ||||
| 	index = (index + items_num) % items_num; | ||||
| 	while (true) { | ||||
| 		char *str = k_menu_items[index].str; | ||||
| 		if (strcasestr(str, match_str) != 0) | ||||
| 		if (strcasestr(str, match_str) != NULL) | ||||
| 			return index; | ||||
| 		if (flag == FIND_NEXT_MATCH_UP || | ||||
| 		    flag == MATCH_TINKER_PATTERN_UP) | ||||
| @@ -629,19 +633,12 @@ static int item_is_tag(char tag) | ||||
|  | ||||
| static char filename[PATH_MAX+1]; | ||||
| static char menu_backtitle[PATH_MAX+128]; | ||||
| static const char *set_config_filename(const char *config_filename) | ||||
| static void set_config_filename(const char *config_filename) | ||||
| { | ||||
| 	int size; | ||||
| 	snprintf(menu_backtitle, sizeof(menu_backtitle), "%s - %s", | ||||
| 		 config_filename, rootmenu.prompt->text); | ||||
|  | ||||
| 	size = snprintf(menu_backtitle, sizeof(menu_backtitle), | ||||
| 			"%s - %s", config_filename, rootmenu.prompt->text); | ||||
| 	if (size >= sizeof(menu_backtitle)) | ||||
| 		menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; | ||||
|  | ||||
| 	size = snprintf(filename, sizeof(filename), "%s", config_filename); | ||||
| 	if (size >= sizeof(filename)) | ||||
| 		filename[sizeof(filename)-1] = '\0'; | ||||
| 	return menu_backtitle; | ||||
| 	snprintf(filename, sizeof(filename), "%s", config_filename); | ||||
| } | ||||
|  | ||||
| /* return = 0 means we are successful. | ||||
| @@ -657,8 +654,8 @@ static int do_exit(void) | ||||
| 		return 0; | ||||
| 	} | ||||
| 	res = btn_dialog(main_window, | ||||
| 			_("Do you wish to save your new configuration?\n" | ||||
| 				"<ESC> to cancel and resume nconfig."), | ||||
| 			"Do you wish to save your new configuration?\n" | ||||
| 				"<ESC> to cancel and resume nconfig.", | ||||
| 			2, | ||||
| 			"   <save>   ", | ||||
| 			"<don't save>"); | ||||
| @@ -670,7 +667,7 @@ static int do_exit(void) | ||||
| 	env = getenv("KCONFIG_STRICT"); | ||||
| 	if (env && *env && kconfig_warnings) { | ||||
| 		btn_dialog(main_window, | ||||
| 			_("\nWarnings encountered, and warnings are errors.\n\n"), | ||||
| 			"\nWarnings encountered, and warnings are errors.\n\n", | ||||
| 			1, | ||||
| 			"<OK>"); | ||||
| 		res = 2; | ||||
| @@ -683,15 +680,16 @@ static int do_exit(void) | ||||
| 		if (res) | ||||
| 			btn_dialog( | ||||
| 				main_window, | ||||
| 				_("Error during writing of configuration.\n" | ||||
| 				  "Your configuration changes were NOT saved."), | ||||
| 				"Error during writing of configuration.\n" | ||||
| 				  "Your configuration changes were NOT saved.", | ||||
| 				  1, | ||||
| 				  "<OK>"); | ||||
| 		conf_write_autoconf(0); | ||||
| 		break; | ||||
| 	default: | ||||
| 		btn_dialog( | ||||
| 			main_window, | ||||
| 			_("Your configuration changes were NOT saved."), | ||||
| 			"Your configuration changes were NOT saved.", | ||||
| 			1, | ||||
| 			"<OK>"); | ||||
| 		break; | ||||
| @@ -710,12 +708,12 @@ static void search_conf(void) | ||||
| 	int dres; | ||||
|  | ||||
| 	title = str_new(); | ||||
| 	str_printf( &title, _("Enter (sub)string or regexp to search for " | ||||
| 			      "(with or without \"%s\")"), CONFIG_); | ||||
| 	str_printf( &title, "Enter (sub)string or regexp to search for " | ||||
| 			      "(with or without \"%s\")", CONFIG_); | ||||
|  | ||||
| again: | ||||
| 	dres = dialog_inputbox(main_window, | ||||
| 			_("Search Configuration Parameter"), | ||||
| 			"Search Configuration Parameter", | ||||
| 			str_get(&title), | ||||
| 			"", &dialog_input_result, &dialog_input_result_len); | ||||
| 	switch (dres) { | ||||
| @@ -723,7 +721,7 @@ again: | ||||
| 		break; | ||||
| 	case 1: | ||||
| 		show_scroll_win(main_window, | ||||
| 				_("Search Configuration"), search_help); | ||||
| 				"Search Configuration", search_help); | ||||
| 		goto again; | ||||
| 	default: | ||||
| 		str_free(&title); | ||||
| @@ -739,7 +737,7 @@ again: | ||||
| 	res = get_relations_str(sym_arr, NULL); | ||||
| 	free(sym_arr); | ||||
| 	show_scroll_win(main_window, | ||||
| 			_("Search Results"), str_get(&res)); | ||||
| 			"Search Results", str_get(&res)); | ||||
| 	str_free(&res); | ||||
| 	str_free(&title); | ||||
| } | ||||
| @@ -767,7 +765,6 @@ static void build_conf(struct menu *menu) | ||||
| 			switch (ptype) { | ||||
| 			case P_MENU: | ||||
| 				child_count++; | ||||
| 				prompt = _(prompt); | ||||
| 				if (single_menu_mode) { | ||||
| 					item_make(menu, 'm', | ||||
| 						"%s%*c%s", | ||||
| @@ -788,7 +785,7 @@ static void build_conf(struct menu *menu) | ||||
| 					item_make(menu, ':', | ||||
| 						"   %*c*** %s ***", | ||||
| 						indent + 1, ' ', | ||||
| 						_(prompt)); | ||||
| 						prompt); | ||||
| 				} | ||||
| 				break; | ||||
| 			default: | ||||
| @@ -796,7 +793,7 @@ static void build_conf(struct menu *menu) | ||||
| 					child_count++; | ||||
| 					item_make(menu, ':', "---%*c%s", | ||||
| 						indent + 1, ' ', | ||||
| 						_(prompt)); | ||||
| 						prompt); | ||||
| 				} | ||||
| 			} | ||||
| 		} else | ||||
| @@ -816,7 +813,7 @@ static void build_conf(struct menu *menu) | ||||
| 		} | ||||
|  | ||||
| 		val = sym_get_tristate_value(sym); | ||||
| 		if (sym_is_changable(sym)) { | ||||
| 		if (sym_is_changeable(sym)) { | ||||
| 			switch (type) { | ||||
| 			case S_BOOLEAN: | ||||
| 				item_make(menu, 't', "[%c]", | ||||
| @@ -842,11 +839,11 @@ static void build_conf(struct menu *menu) | ||||
| 		} | ||||
|  | ||||
| 		item_add_str("%*c%s", indent + 1, | ||||
| 				' ', _(menu_get_prompt(menu))); | ||||
| 				' ', menu_get_prompt(menu)); | ||||
| 		if (val == yes) { | ||||
| 			if (def_menu) { | ||||
| 				item_add_str(" (%s)", | ||||
| 					_(menu_get_prompt(def_menu))); | ||||
| 					menu_get_prompt(def_menu)); | ||||
| 				item_add_str("  --->"); | ||||
| 				if (def_menu->list) { | ||||
| 					indent += 2; | ||||
| @@ -860,7 +857,7 @@ static void build_conf(struct menu *menu) | ||||
| 		if (menu == current_menu) { | ||||
| 			item_make(menu, ':', | ||||
| 				"---%*c%s", indent + 1, | ||||
| 				' ', _(menu_get_prompt(menu))); | ||||
| 				' ', menu_get_prompt(menu)); | ||||
| 			goto conf_childs; | ||||
| 		} | ||||
| 		child_count++; | ||||
| @@ -870,7 +867,7 @@ static void build_conf(struct menu *menu) | ||||
| 		} else { | ||||
| 			switch (type) { | ||||
| 			case S_BOOLEAN: | ||||
| 				if (sym_is_changable(sym)) | ||||
| 				if (sym_is_changeable(sym)) | ||||
| 					item_make(menu, 't', "[%c]", | ||||
| 						val == no ? ' ' : '*'); | ||||
| 				else | ||||
| @@ -889,7 +886,7 @@ static void build_conf(struct menu *menu) | ||||
| 					ch = ' '; | ||||
| 					break; | ||||
| 				} | ||||
| 				if (sym_is_changable(sym)) { | ||||
| 				if (sym_is_changeable(sym)) { | ||||
| 					if (sym->rev_dep.tri == mod) | ||||
| 						item_make(menu, | ||||
| 							't', "{%c}", ch); | ||||
| @@ -907,17 +904,17 @@ static void build_conf(struct menu *menu) | ||||
| 				if (tmp < 0) | ||||
| 					tmp = 0; | ||||
| 				item_add_str("%*c%s%s", tmp, ' ', | ||||
| 						_(menu_get_prompt(menu)), | ||||
| 						menu_get_prompt(menu), | ||||
| 						(sym_has_value(sym) || | ||||
| 						 !sym_is_changable(sym)) ? "" : | ||||
| 						_(" (NEW)")); | ||||
| 						 !sym_is_changeable(sym)) ? "" : | ||||
| 						" (NEW)"); | ||||
| 				goto conf_childs; | ||||
| 			} | ||||
| 		} | ||||
| 		item_add_str("%*c%s%s", indent + 1, ' ', | ||||
| 				_(menu_get_prompt(menu)), | ||||
| 				(sym_has_value(sym) || !sym_is_changable(sym)) ? | ||||
| 				"" : _(" (NEW)")); | ||||
| 				menu_get_prompt(menu), | ||||
| 				(sym_has_value(sym) || !sym_is_changeable(sym)) ? | ||||
| 				"" : " (NEW)"); | ||||
| 		if (menu->prompt && menu->prompt->type == P_MENU) { | ||||
| 			item_add_str("  %s", menu_is_empty(menu) ? "----" : "--->"); | ||||
| 			return; | ||||
| @@ -969,16 +966,15 @@ static void show_menu(const char *prompt, const char *instructions, | ||||
| 	current_instructions = instructions; | ||||
|  | ||||
| 	clear(); | ||||
| 	(void) wattrset(main_window, attributes[NORMAL]); | ||||
| 	print_in_middle(stdscr, 1, 0, getmaxx(stdscr), | ||||
| 	print_in_middle(stdscr, 1, getmaxx(stdscr), | ||||
| 			menu_backtitle, | ||||
| 			attributes[MAIN_HEADING]); | ||||
| 			attr_main_heading); | ||||
|  | ||||
| 	(void) wattrset(main_window, attributes[MAIN_MENU_BOX]); | ||||
| 	wattrset(main_window, attr_main_menu_box); | ||||
| 	box(main_window, 0, 0); | ||||
| 	(void) wattrset(main_window, attributes[MAIN_MENU_HEADING]); | ||||
| 	wattrset(main_window, attr_main_menu_heading); | ||||
| 	mvwprintw(main_window, 0, 3, " %s ", prompt); | ||||
| 	(void) wattrset(main_window, attributes[NORMAL]); | ||||
| 	wattrset(main_window, attr_normal); | ||||
|  | ||||
| 	set_menu_items(curses_menu, curses_menu_items); | ||||
|  | ||||
| @@ -1061,7 +1057,7 @@ static int do_match(int key, struct match_state *state, int *ans) | ||||
| 		state->match_direction = FIND_NEXT_MATCH_UP; | ||||
| 		*ans = get_mext_match(state->pattern, | ||||
| 				state->match_direction); | ||||
| 	} else if (key == KEY_BACKSPACE || key == 127) { | ||||
| 	} else if (key == KEY_BACKSPACE || key == 8 || key == 127) { | ||||
| 		state->pattern[strlen(state->pattern)-1] = '\0'; | ||||
| 		adj_match_dir(&state->match_direction); | ||||
| 	} else | ||||
| @@ -1081,7 +1077,6 @@ static int do_match(int key, struct match_state *state, int *ans) | ||||
| static void conf(struct menu *menu) | ||||
| { | ||||
| 	struct menu *submenu = NULL; | ||||
| 	const char *prompt = menu_get_prompt(menu); | ||||
| 	struct symbol *sym; | ||||
| 	int res; | ||||
| 	int current_index = 0; | ||||
| @@ -1099,9 +1094,8 @@ static void conf(struct menu *menu) | ||||
| 		if (!child_count) | ||||
| 			break; | ||||
|  | ||||
| 		show_menu(prompt ? _(prompt) : _("Main Menu"), | ||||
| 				_(menu_instructions), | ||||
| 				current_index, &last_top_row); | ||||
| 		show_menu(menu_get_prompt(menu), menu_instructions, | ||||
| 			  current_index, &last_top_row); | ||||
| 		keypad((menu_win(curses_menu)), TRUE); | ||||
| 		while (!global_exit) { | ||||
| 			if (match_state.in_search) { | ||||
| @@ -1223,12 +1217,9 @@ static void conf(struct menu *menu) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void conf_message_callback(const char *fmt, va_list ap) | ||||
| static void conf_message_callback(const char *s) | ||||
| { | ||||
| 	char buf[1024]; | ||||
|  | ||||
| 	vsnprintf(buf, sizeof(buf), fmt, ap); | ||||
| 	btn_dialog(main_window, buf, 1, "<OK>"); | ||||
| 	btn_dialog(main_window, s, 1, "<OK>"); | ||||
| } | ||||
|  | ||||
| static void show_help(struct menu *menu) | ||||
| @@ -1240,13 +1231,13 @@ static void show_help(struct menu *menu) | ||||
|  | ||||
| 	help = str_new(); | ||||
| 	menu_get_ext_help(menu, &help); | ||||
| 	show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help)); | ||||
| 	show_scroll_win(main_window, menu_get_prompt(menu), str_get(&help)); | ||||
| 	str_free(&help); | ||||
| } | ||||
|  | ||||
| static void conf_choice(struct menu *menu) | ||||
| { | ||||
| 	const char *prompt = _(menu_get_prompt(menu)); | ||||
| 	const char *prompt = menu_get_prompt(menu); | ||||
| 	struct menu *child = NULL; | ||||
| 	struct symbol *active; | ||||
| 	int selected_index = 0; | ||||
| @@ -1269,13 +1260,13 @@ static void conf_choice(struct menu *menu) | ||||
|  | ||||
| 			if (child->sym == sym_get_choice_value(menu->sym)) | ||||
| 				item_make(child, ':', "<X> %s", | ||||
| 						_(menu_get_prompt(child))); | ||||
| 						menu_get_prompt(child)); | ||||
| 			else if (child->sym) | ||||
| 				item_make(child, ':', "    %s", | ||||
| 						_(menu_get_prompt(child))); | ||||
| 						menu_get_prompt(child)); | ||||
| 			else | ||||
| 				item_make(child, ':', "*** %s ***", | ||||
| 						_(menu_get_prompt(child))); | ||||
| 						menu_get_prompt(child)); | ||||
|  | ||||
| 			if (child->sym == active){ | ||||
| 				last_top_row = top_row(curses_menu); | ||||
| @@ -1283,8 +1274,8 @@ static void conf_choice(struct menu *menu) | ||||
| 			} | ||||
| 			i++; | ||||
| 		} | ||||
| 		show_menu(prompt ? _(prompt) : _("Choice Menu"), | ||||
| 				_(radiolist_instructions), | ||||
| 		show_menu(prompt ? prompt : "Choice Menu", | ||||
| 				radiolist_instructions, | ||||
| 				selected_index, | ||||
| 				&last_top_row); | ||||
| 		while (!global_exit) { | ||||
| @@ -1371,19 +1362,19 @@ static void conf_string(struct menu *menu) | ||||
|  | ||||
| 		switch (sym_get_type(menu->sym)) { | ||||
| 		case S_INT: | ||||
| 			heading = _(inputbox_instructions_int); | ||||
| 			heading = inputbox_instructions_int; | ||||
| 			break; | ||||
| 		case S_HEX: | ||||
| 			heading = _(inputbox_instructions_hex); | ||||
| 			heading = inputbox_instructions_hex; | ||||
| 			break; | ||||
| 		case S_STRING: | ||||
| 			heading = _(inputbox_instructions_string); | ||||
| 			heading = inputbox_instructions_string; | ||||
| 			break; | ||||
| 		default: | ||||
| 			heading = _("Internal nconf error!"); | ||||
| 			heading = "Internal nconf error!"; | ||||
| 		} | ||||
| 		res = dialog_inputbox(main_window, | ||||
| 				prompt ? _(prompt) : _("Main Menu"), | ||||
| 				prompt ? prompt : "Main Menu", | ||||
| 				heading, | ||||
| 				sym_get_string_value(menu->sym), | ||||
| 				&dialog_input_result, | ||||
| @@ -1394,7 +1385,7 @@ static void conf_string(struct menu *menu) | ||||
| 						dialog_input_result)) | ||||
| 				return; | ||||
| 			btn_dialog(main_window, | ||||
| 				_("You have made an invalid entry."), 0); | ||||
| 				"You have made an invalid entry.", 0); | ||||
| 			break; | ||||
| 		case 1: | ||||
| 			show_help(menu); | ||||
| @@ -1420,14 +1411,14 @@ static void conf_load(void) | ||||
| 				return; | ||||
| 			if (!conf_read(dialog_input_result)) { | ||||
| 				set_config_filename(dialog_input_result); | ||||
| 				sym_set_change_count(1); | ||||
| 				conf_set_changed(true); | ||||
| 				return; | ||||
| 			} | ||||
| 			btn_dialog(main_window, _("File does not exist!"), 0); | ||||
| 			btn_dialog(main_window, "File does not exist!", 0); | ||||
| 			break; | ||||
| 		case 1: | ||||
| 			show_scroll_win(main_window, | ||||
| 					_("Load Alternate Configuration"), | ||||
| 					"Load Alternate Configuration", | ||||
| 					load_config_help); | ||||
| 			break; | ||||
| 		case KEY_EXIT: | ||||
| @@ -1454,13 +1445,12 @@ static void conf_save(void) | ||||
| 				set_config_filename(dialog_input_result); | ||||
| 				return; | ||||
| 			} | ||||
| 			btn_dialog(main_window, _("Can't create file! " | ||||
| 				"Probably a nonexistent directory."), | ||||
| 			btn_dialog(main_window, "Can't create file!", | ||||
| 				1, "<OK>"); | ||||
| 			break; | ||||
| 		case 1: | ||||
| 			show_scroll_win(main_window, | ||||
| 				_("Save Alternate Configuration"), | ||||
| 				"Save Alternate Configuration", | ||||
| 				save_config_help); | ||||
| 			break; | ||||
| 		case KEY_EXIT: | ||||
| @@ -1469,7 +1459,7 @@ static void conf_save(void) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void setup_windows(void) | ||||
| static void setup_windows(void) | ||||
| { | ||||
| 	int lines, columns; | ||||
|  | ||||
| @@ -1493,10 +1483,11 @@ int main(int ac, char **av) | ||||
| 	int lines, columns; | ||||
| 	char *mode; | ||||
|  | ||||
| 	setlocale(LC_ALL, ""); | ||||
| 	bindtextdomain(PACKAGE, LOCALEDIR); | ||||
| 	textdomain(PACKAGE); | ||||
|  | ||||
| 	if (ac > 1 && strcmp(av[1], "-s") == 0) { | ||||
| 		/* Silence conf_read() until the real callback is set up */ | ||||
| 		conf_set_message_callback(NULL); | ||||
| 		av++; | ||||
| 	} | ||||
| 	conf_parse(av[1]); | ||||
| 	conf_read(NULL); | ||||
|  | ||||
| @@ -1539,9 +1530,9 @@ int main(int ac, char **av) | ||||
| 	menu_opts_on(curses_menu, O_NONCYCLIC); | ||||
| 	menu_opts_on(curses_menu, O_IGNORECASE); | ||||
| 	set_menu_mark(curses_menu, " "); | ||||
| 	set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]); | ||||
| 	set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]); | ||||
| 	set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]); | ||||
| 	set_menu_fore(curses_menu, attr_main_menu_fore); | ||||
| 	set_menu_back(curses_menu, attr_main_menu_back); | ||||
| 	set_menu_grey(curses_menu, attr_main_menu_grey); | ||||
|  | ||||
| 	set_config_filename(conf_get_configname()); | ||||
| 	setup_windows(); | ||||
| @@ -1549,8 +1540,8 @@ int main(int ac, char **av) | ||||
| 	/* check for KEY_FUNC(1) */ | ||||
| 	if (has_key(KEY_F(1)) == FALSE) { | ||||
| 		show_scroll_win(main_window, | ||||
| 				_("Instructions"), | ||||
| 				_(menu_no_f_instructions)); | ||||
| 				"Instructions", | ||||
| 				menu_no_f_instructions); | ||||
| 	} | ||||
|  | ||||
| 	conf_set_message_callback(conf_message_callback); | ||||
|   | ||||
| @@ -1,175 +1,126 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com? | ||||
|  * Released under the terms of the GNU GPL v2.0. | ||||
|  * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com> | ||||
|  * | ||||
|  * Derived from menuconfig. | ||||
|  * | ||||
|  */ | ||||
| #include "nconf.h" | ||||
| #include "lkc.h" | ||||
|  | ||||
| /* a list of all the different widgets we use */ | ||||
| attributes_t attributes[ATTR_MAX+1] = {0}; | ||||
| int attr_normal; | ||||
| int attr_main_heading; | ||||
| int attr_main_menu_box; | ||||
| int attr_main_menu_fore; | ||||
| int attr_main_menu_back; | ||||
| int attr_main_menu_grey; | ||||
| int attr_main_menu_heading; | ||||
| int attr_scrollwin_text; | ||||
| int attr_scrollwin_heading; | ||||
| int attr_scrollwin_box; | ||||
| int attr_dialog_text; | ||||
| int attr_dialog_menu_fore; | ||||
| int attr_dialog_menu_back; | ||||
| int attr_dialog_box; | ||||
| int attr_input_box; | ||||
| int attr_input_heading; | ||||
| int attr_input_text; | ||||
| int attr_input_field; | ||||
| int attr_function_text; | ||||
| int attr_function_highlight; | ||||
|  | ||||
| /* available colors: | ||||
|    COLOR_BLACK   0 | ||||
|    COLOR_RED     1 | ||||
|    COLOR_GREEN   2 | ||||
|    COLOR_YELLOW  3 | ||||
|    COLOR_BLUE    4 | ||||
|    COLOR_MAGENTA 5 | ||||
|    COLOR_CYAN    6 | ||||
|    COLOR_WHITE   7 | ||||
|    */ | ||||
| static void set_normal_colors(void) | ||||
| #define COLOR_ATTR(_at, _fg, _bg, _hl) \ | ||||
| 	{ .attr = &(_at), .has_color = true, .color_fg = _fg, .color_bg = _bg, .highlight = _hl } | ||||
| #define NO_COLOR_ATTR(_at, _hl) \ | ||||
| 	{ .attr = &(_at), .has_color = false, .highlight = _hl } | ||||
| #define COLOR_DEFAULT		-1 | ||||
|  | ||||
| struct nconf_attr_param { | ||||
| 	int *attr; | ||||
| 	bool has_color; | ||||
| 	int color_fg; | ||||
| 	int color_bg; | ||||
| 	int highlight; | ||||
| }; | ||||
|  | ||||
| static const struct nconf_attr_param color_theme_params[] = { | ||||
| 	COLOR_ATTR(attr_normal,			COLOR_DEFAULT,	COLOR_DEFAULT,	A_NORMAL), | ||||
| 	COLOR_ATTR(attr_main_heading,		COLOR_MAGENTA,	COLOR_DEFAULT,	A_BOLD | A_UNDERLINE), | ||||
| 	COLOR_ATTR(attr_main_menu_box,		COLOR_YELLOW,	COLOR_DEFAULT,	A_NORMAL), | ||||
| 	COLOR_ATTR(attr_main_menu_fore,		COLOR_DEFAULT,	COLOR_DEFAULT,	A_REVERSE), | ||||
| 	COLOR_ATTR(attr_main_menu_back,		COLOR_DEFAULT,	COLOR_DEFAULT,	A_NORMAL), | ||||
| 	COLOR_ATTR(attr_main_menu_grey,		COLOR_DEFAULT,	COLOR_DEFAULT,	A_NORMAL), | ||||
| 	COLOR_ATTR(attr_main_menu_heading,	COLOR_GREEN,	COLOR_DEFAULT,	A_BOLD), | ||||
| 	COLOR_ATTR(attr_scrollwin_text,		COLOR_DEFAULT,	COLOR_DEFAULT,	A_NORMAL), | ||||
| 	COLOR_ATTR(attr_scrollwin_heading,	COLOR_GREEN,	COLOR_DEFAULT,	A_BOLD), | ||||
| 	COLOR_ATTR(attr_scrollwin_box,		COLOR_YELLOW,	COLOR_DEFAULT,	A_BOLD), | ||||
| 	COLOR_ATTR(attr_dialog_text,		COLOR_DEFAULT,	COLOR_DEFAULT,	A_BOLD), | ||||
| 	COLOR_ATTR(attr_dialog_menu_fore,	COLOR_RED,	COLOR_DEFAULT,	A_STANDOUT), | ||||
| 	COLOR_ATTR(attr_dialog_menu_back,	COLOR_YELLOW,	COLOR_DEFAULT,	A_NORMAL), | ||||
| 	COLOR_ATTR(attr_dialog_box,		COLOR_YELLOW,	COLOR_DEFAULT,	A_BOLD), | ||||
| 	COLOR_ATTR(attr_input_box,		COLOR_YELLOW,	COLOR_DEFAULT,	A_NORMAL), | ||||
| 	COLOR_ATTR(attr_input_heading,		COLOR_GREEN,	COLOR_DEFAULT,	A_BOLD), | ||||
| 	COLOR_ATTR(attr_input_text,		COLOR_DEFAULT,	COLOR_DEFAULT,	A_NORMAL), | ||||
| 	COLOR_ATTR(attr_input_field,		COLOR_DEFAULT,	COLOR_DEFAULT,	A_UNDERLINE), | ||||
| 	COLOR_ATTR(attr_function_text,		COLOR_YELLOW,	COLOR_DEFAULT,	A_REVERSE), | ||||
| 	COLOR_ATTR(attr_function_highlight,	COLOR_DEFAULT,	COLOR_DEFAULT,	A_BOLD), | ||||
| 	{ /* sentinel */ } | ||||
| }; | ||||
|  | ||||
| static const struct nconf_attr_param no_color_theme_params[] = { | ||||
| 	NO_COLOR_ATTR(attr_normal,		A_NORMAL), | ||||
| 	NO_COLOR_ATTR(attr_main_heading,	A_BOLD | A_UNDERLINE), | ||||
| 	NO_COLOR_ATTR(attr_main_menu_box,	A_NORMAL), | ||||
| 	NO_COLOR_ATTR(attr_main_menu_fore,	A_STANDOUT), | ||||
| 	NO_COLOR_ATTR(attr_main_menu_back,	A_NORMAL), | ||||
| 	NO_COLOR_ATTR(attr_main_menu_grey,	A_NORMAL), | ||||
| 	NO_COLOR_ATTR(attr_main_menu_heading,	A_BOLD), | ||||
| 	NO_COLOR_ATTR(attr_scrollwin_text,	A_NORMAL), | ||||
| 	NO_COLOR_ATTR(attr_scrollwin_heading,	A_BOLD), | ||||
| 	NO_COLOR_ATTR(attr_scrollwin_box,	A_BOLD), | ||||
| 	NO_COLOR_ATTR(attr_dialog_text,		A_NORMAL), | ||||
| 	NO_COLOR_ATTR(attr_dialog_menu_fore,	A_STANDOUT), | ||||
| 	NO_COLOR_ATTR(attr_dialog_menu_back,	A_NORMAL), | ||||
| 	NO_COLOR_ATTR(attr_dialog_box,		A_BOLD), | ||||
| 	NO_COLOR_ATTR(attr_input_box,		A_BOLD), | ||||
| 	NO_COLOR_ATTR(attr_input_heading,	A_BOLD), | ||||
| 	NO_COLOR_ATTR(attr_input_text,		A_NORMAL), | ||||
| 	NO_COLOR_ATTR(attr_input_field,		A_UNDERLINE), | ||||
| 	NO_COLOR_ATTR(attr_function_text,	A_REVERSE), | ||||
| 	NO_COLOR_ATTR(attr_function_highlight,	A_BOLD), | ||||
| 	{ /* sentinel */ } | ||||
| }; | ||||
|  | ||||
| void set_colors(void) | ||||
| { | ||||
| 	init_pair(NORMAL, -1, -1); | ||||
| 	init_pair(MAIN_HEADING, COLOR_MAGENTA, -1); | ||||
| 	const struct nconf_attr_param *p; | ||||
| 	int pair = 0; | ||||
|  | ||||
| 	/* FORE is for the selected item */ | ||||
| 	init_pair(MAIN_MENU_FORE, -1, -1); | ||||
| 	/* BACK for all the rest */ | ||||
| 	init_pair(MAIN_MENU_BACK, -1, -1); | ||||
| 	init_pair(MAIN_MENU_GREY, -1, -1); | ||||
| 	init_pair(MAIN_MENU_HEADING, COLOR_GREEN, -1); | ||||
| 	init_pair(MAIN_MENU_BOX, COLOR_YELLOW, -1); | ||||
|  | ||||
| 	init_pair(SCROLLWIN_TEXT, -1, -1); | ||||
| 	init_pair(SCROLLWIN_HEADING, COLOR_GREEN, -1); | ||||
| 	init_pair(SCROLLWIN_BOX, COLOR_YELLOW, -1); | ||||
|  | ||||
| 	init_pair(DIALOG_TEXT, -1, -1); | ||||
| 	init_pair(DIALOG_BOX, COLOR_YELLOW, -1); | ||||
| 	init_pair(DIALOG_MENU_BACK, COLOR_YELLOW, -1); | ||||
| 	init_pair(DIALOG_MENU_FORE, COLOR_RED, -1); | ||||
|  | ||||
| 	init_pair(INPUT_BOX, COLOR_YELLOW, -1); | ||||
| 	init_pair(INPUT_HEADING, COLOR_GREEN, -1); | ||||
| 	init_pair(INPUT_TEXT, -1, -1); | ||||
| 	init_pair(INPUT_FIELD, -1, -1); | ||||
|  | ||||
| 	init_pair(FUNCTION_HIGHLIGHT, -1, -1); | ||||
| 	init_pair(FUNCTION_TEXT, COLOR_YELLOW, -1); | ||||
| } | ||||
|  | ||||
| /* available attributes: | ||||
|    A_NORMAL        Normal display (no highlight) | ||||
|    A_STANDOUT      Best highlighting mode of the terminal. | ||||
|    A_UNDERLINE     Underlining | ||||
|    A_REVERSE       Reverse video | ||||
|    A_BLINK         Blinking | ||||
|    A_DIM           Half bright | ||||
|    A_BOLD          Extra bright or bold | ||||
|    A_PROTECT       Protected mode | ||||
|    A_INVIS         Invisible or blank mode | ||||
|    A_ALTCHARSET    Alternate character set | ||||
|    A_CHARTEXT      Bit-mask to extract a character | ||||
|    COLOR_PAIR(n)   Color-pair number n | ||||
|    */ | ||||
| static void normal_color_theme(void) | ||||
| { | ||||
| 	/* automatically add color... */ | ||||
| #define mkattr(name, attr) do { \ | ||||
| attributes[name] = attr | COLOR_PAIR(name); } while (0) | ||||
| 	mkattr(NORMAL, NORMAL); | ||||
| 	mkattr(MAIN_HEADING, A_BOLD | A_UNDERLINE); | ||||
|  | ||||
| 	mkattr(MAIN_MENU_FORE, A_REVERSE); | ||||
| 	mkattr(MAIN_MENU_BACK, A_NORMAL); | ||||
| 	mkattr(MAIN_MENU_GREY, A_NORMAL); | ||||
| 	mkattr(MAIN_MENU_HEADING, A_BOLD); | ||||
| 	mkattr(MAIN_MENU_BOX, A_NORMAL); | ||||
|  | ||||
| 	mkattr(SCROLLWIN_TEXT, A_NORMAL); | ||||
| 	mkattr(SCROLLWIN_HEADING, A_BOLD); | ||||
| 	mkattr(SCROLLWIN_BOX, A_BOLD); | ||||
|  | ||||
| 	mkattr(DIALOG_TEXT, A_BOLD); | ||||
| 	mkattr(DIALOG_BOX, A_BOLD); | ||||
| 	mkattr(DIALOG_MENU_FORE, A_STANDOUT); | ||||
| 	mkattr(DIALOG_MENU_BACK, A_NORMAL); | ||||
|  | ||||
| 	mkattr(INPUT_BOX, A_NORMAL); | ||||
| 	mkattr(INPUT_HEADING, A_BOLD); | ||||
| 	mkattr(INPUT_TEXT, A_NORMAL); | ||||
| 	mkattr(INPUT_FIELD, A_UNDERLINE); | ||||
|  | ||||
| 	mkattr(FUNCTION_HIGHLIGHT, A_BOLD); | ||||
| 	mkattr(FUNCTION_TEXT, A_REVERSE); | ||||
| } | ||||
|  | ||||
| static void no_colors_theme(void) | ||||
| { | ||||
| 	/* automatically add highlight, no color */ | ||||
| #define mkattrn(name, attr) { attributes[name] = attr; } | ||||
|  | ||||
| 	mkattrn(NORMAL, NORMAL); | ||||
| 	mkattrn(MAIN_HEADING, A_BOLD | A_UNDERLINE); | ||||
|  | ||||
| 	mkattrn(MAIN_MENU_FORE, A_STANDOUT); | ||||
| 	mkattrn(MAIN_MENU_BACK, A_NORMAL); | ||||
| 	mkattrn(MAIN_MENU_GREY, A_NORMAL); | ||||
| 	mkattrn(MAIN_MENU_HEADING, A_BOLD); | ||||
| 	mkattrn(MAIN_MENU_BOX, A_NORMAL); | ||||
|  | ||||
| 	mkattrn(SCROLLWIN_TEXT, A_NORMAL); | ||||
| 	mkattrn(SCROLLWIN_HEADING, A_BOLD); | ||||
| 	mkattrn(SCROLLWIN_BOX, A_BOLD); | ||||
|  | ||||
| 	mkattrn(DIALOG_TEXT, A_NORMAL); | ||||
| 	mkattrn(DIALOG_BOX, A_BOLD); | ||||
| 	mkattrn(DIALOG_MENU_FORE, A_STANDOUT); | ||||
| 	mkattrn(DIALOG_MENU_BACK, A_NORMAL); | ||||
|  | ||||
| 	mkattrn(INPUT_BOX, A_BOLD); | ||||
| 	mkattrn(INPUT_HEADING, A_BOLD); | ||||
| 	mkattrn(INPUT_TEXT, A_NORMAL); | ||||
| 	mkattrn(INPUT_FIELD, A_UNDERLINE); | ||||
|  | ||||
| 	mkattrn(FUNCTION_HIGHLIGHT, A_BOLD); | ||||
| 	mkattrn(FUNCTION_TEXT, A_REVERSE); | ||||
| } | ||||
|  | ||||
| void set_colors() | ||||
| { | ||||
| 	start_color(); | ||||
| 	use_default_colors(); | ||||
| 	set_normal_colors(); | ||||
| 	if (has_colors()) { | ||||
| 		normal_color_theme(); | ||||
| 		start_color(); | ||||
| 		use_default_colors(); | ||||
| 		p = color_theme_params; | ||||
| 	} else { | ||||
| 		/* give defaults */ | ||||
| 		no_colors_theme(); | ||||
| 		p = no_color_theme_params; | ||||
| 	} | ||||
|  | ||||
| 	for (; p->attr; p++) { | ||||
| 		int attr = p->highlight; | ||||
|  | ||||
| 		if (p->has_color) { | ||||
| 			pair++; | ||||
| 			init_pair(pair, p->color_fg, p->color_bg); | ||||
| 			attr |= COLOR_PAIR(pair); | ||||
| 		} | ||||
|  | ||||
| 		*p->attr = attr; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| /* this changes the windows attributes !!! */ | ||||
| void print_in_middle(WINDOW *win, | ||||
| 		int starty, | ||||
| 		int startx, | ||||
| 		int width, | ||||
| 		const char *string, | ||||
| 		chtype color) | ||||
| {      int length, x, y; | ||||
| 	float temp; | ||||
|  | ||||
|  | ||||
| 	if (win == NULL) | ||||
| 		win = stdscr; | ||||
| 	getyx(win, y, x); | ||||
| 	if (startx != 0) | ||||
| 		x = startx; | ||||
| 	if (starty != 0) | ||||
| 		y = starty; | ||||
| 	if (width == 0) | ||||
| 		width = 80; | ||||
|  | ||||
| 	length = strlen(string); | ||||
| 	temp = (width - length) / 2; | ||||
| 	x = startx + (int)temp; | ||||
| 	(void) wattrset(win, color); | ||||
| 	mvwprintw(win, y, x, "%s", string); | ||||
| 	refresh(); | ||||
| void print_in_middle(WINDOW *win, int y, int width, const char *str, int attrs) | ||||
| { | ||||
| 	wattrset(win, attrs); | ||||
| 	mvwprintw(win, y, (width - strlen(str)) / 2, "%s", str); | ||||
| } | ||||
|  | ||||
| int get_line_no(const char *text) | ||||
| @@ -192,7 +143,7 @@ const char *get_line(const char *text, int line_no) | ||||
| 	int lines = 0; | ||||
|  | ||||
| 	if (!text) | ||||
| 		return 0; | ||||
| 		return NULL; | ||||
|  | ||||
| 	for (i = 0; text[i] != '\0' && lines < line_no; i++) | ||||
| 		if (text[i] == '\n') | ||||
| @@ -294,14 +245,14 @@ int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...) | ||||
| 	msg_win = derwin(win, win_rows-2, msg_width, 1, | ||||
| 			1+(total_width+2-msg_width)/2); | ||||
|  | ||||
| 	set_menu_fore(menu, attributes[DIALOG_MENU_FORE]); | ||||
| 	set_menu_back(menu, attributes[DIALOG_MENU_BACK]); | ||||
| 	set_menu_fore(menu, attr_dialog_menu_fore); | ||||
| 	set_menu_back(menu, attr_dialog_menu_back); | ||||
|  | ||||
| 	(void) wattrset(win, attributes[DIALOG_BOX]); | ||||
| 	wattrset(win, attr_dialog_box); | ||||
| 	box(win, 0, 0); | ||||
|  | ||||
| 	/* print message */ | ||||
| 	(void) wattrset(msg_win, attributes[DIALOG_TEXT]); | ||||
| 	wattrset(msg_win, attr_dialog_text); | ||||
| 	fill_window(msg_win, msg); | ||||
|  | ||||
| 	set_menu_win(menu, win); | ||||
| @@ -364,15 +315,17 @@ int dialog_inputbox(WINDOW *main_window, | ||||
| 	WINDOW *prompt_win; | ||||
| 	WINDOW *form_win; | ||||
| 	PANEL *panel; | ||||
| 	int i, x, y; | ||||
| 	int i, x, y, lines, columns, win_lines, win_cols; | ||||
| 	int res = -1; | ||||
| 	int cursor_position = strlen(init); | ||||
| 	int cursor_form_win; | ||||
| 	char *result = *resultp; | ||||
|  | ||||
| 	getmaxyx(stdscr, lines, columns); | ||||
|  | ||||
| 	if (strlen(init)+1 > *result_len) { | ||||
| 		*result_len = strlen(init)+1; | ||||
| 		*resultp = result = realloc(result, *result_len); | ||||
| 		*resultp = result = xrealloc(result, *result_len); | ||||
| 	} | ||||
|  | ||||
| 	/* find the widest line of msg: */ | ||||
| @@ -386,28 +339,33 @@ int dialog_inputbox(WINDOW *main_window, | ||||
| 	if (title) | ||||
| 		prompt_width = max(prompt_width, strlen(title)); | ||||
|  | ||||
| 	win_lines = min(prompt_lines+6, lines-2); | ||||
| 	win_cols = min(prompt_width+7, columns-2); | ||||
| 	prompt_lines = max(win_lines-6, 0); | ||||
| 	prompt_width = max(win_cols-7, 0); | ||||
|  | ||||
| 	/* place dialog in middle of screen */ | ||||
| 	y = (getmaxy(stdscr)-(prompt_lines+4))/2; | ||||
| 	x = (getmaxx(stdscr)-(prompt_width+4))/2; | ||||
| 	y = (lines-win_lines)/2; | ||||
| 	x = (columns-win_cols)/2; | ||||
|  | ||||
| 	strncpy(result, init, *result_len); | ||||
|  | ||||
| 	/* create the windows */ | ||||
| 	win = newwin(prompt_lines+6, prompt_width+7, y, x); | ||||
| 	win = newwin(win_lines, win_cols, y, x); | ||||
| 	prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2); | ||||
| 	form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2); | ||||
| 	keypad(form_win, TRUE); | ||||
|  | ||||
| 	(void) wattrset(form_win, attributes[INPUT_FIELD]); | ||||
| 	wattrset(form_win, attr_input_field); | ||||
|  | ||||
| 	(void) wattrset(win, attributes[INPUT_BOX]); | ||||
| 	wattrset(win, attr_input_box); | ||||
| 	box(win, 0, 0); | ||||
| 	(void) wattrset(win, attributes[INPUT_HEADING]); | ||||
| 	wattrset(win, attr_input_heading); | ||||
| 	if (title) | ||||
| 		mvwprintw(win, 0, 3, "%s", title); | ||||
|  | ||||
| 	/* print message */ | ||||
| 	(void) wattrset(prompt_win, attributes[INPUT_TEXT]); | ||||
| 	wattrset(prompt_win, attr_input_text); | ||||
| 	fill_window(prompt_win, prompt); | ||||
|  | ||||
| 	mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); | ||||
| @@ -432,7 +390,8 @@ int dialog_inputbox(WINDOW *main_window, | ||||
| 		case KEY_F(F_EXIT): | ||||
| 		case KEY_F(F_BACK): | ||||
| 			break; | ||||
| 		case 127: | ||||
| 		case 8:   /* ^H */ | ||||
| 		case 127: /* ^? */ | ||||
| 		case KEY_BACKSPACE: | ||||
| 			if (cursor_position > 0) { | ||||
| 				memmove(&result[cursor_position-1], | ||||
| @@ -568,7 +527,7 @@ void show_scroll_win(WINDOW *main_window, | ||||
|  | ||||
| 	/* create the pad */ | ||||
| 	pad = newpad(total_lines+10, total_cols+10); | ||||
| 	(void) wattrset(pad, attributes[SCROLLWIN_TEXT]); | ||||
| 	wattrset(pad, attr_scrollwin_text); | ||||
| 	fill_window(pad, text); | ||||
|  | ||||
| 	win_lines = min(total_lines+4, lines-2); | ||||
| @@ -583,9 +542,9 @@ void show_scroll_win(WINDOW *main_window, | ||||
| 	win = newwin(win_lines, win_cols, y, x); | ||||
| 	keypad(win, TRUE); | ||||
| 	/* show the help in the help window, and show the help panel */ | ||||
| 	(void) wattrset(win, attributes[SCROLLWIN_BOX]); | ||||
| 	wattrset(win, attr_scrollwin_box); | ||||
| 	box(win, 0, 0); | ||||
| 	(void) wattrset(win, attributes[SCROLLWIN_HEADING]); | ||||
| 	wattrset(win, attr_scrollwin_heading); | ||||
| 	mvwprintw(win, 0, 3, " %s ", title); | ||||
| 	panel = new_panel(win); | ||||
|  | ||||
| @@ -596,10 +555,9 @@ void show_scroll_win(WINDOW *main_window, | ||||
| 				text_cols, 0); | ||||
| 		print_in_middle(win, | ||||
| 				text_lines+2, | ||||
| 				0, | ||||
| 				text_cols, | ||||
| 				"<OK>", | ||||
| 				attributes[DIALOG_MENU_FORE]); | ||||
| 				attr_dialog_menu_fore); | ||||
| 		wrefresh(win); | ||||
|  | ||||
| 		res = wgetch(win); | ||||
|   | ||||
| @@ -1,9 +1,8 @@ | ||||
| /* SPDX-License-Identifier: GPL-2.0 */ | ||||
| /* | ||||
|  * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com? | ||||
|  * Released under the terms of the GNU GPL v2.0. | ||||
|  * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com> | ||||
|  * | ||||
|  * Derived from menuconfig. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include <ctype.h> | ||||
| @@ -14,8 +13,7 @@ | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <locale.h> | ||||
| #include <curses.h> | ||||
| #include <ncurses.h> | ||||
| #include <menu.h> | ||||
| #include <panel.h> | ||||
| #include <form.h> | ||||
| @@ -24,8 +22,6 @@ | ||||
| #include <time.h> | ||||
| #include <sys/time.h> | ||||
|  | ||||
| #include "ncurses.h" | ||||
|  | ||||
| #define max(a, b) ({\ | ||||
| 		typeof(a) _a = a;\ | ||||
| 		typeof(b) _b = b;\ | ||||
| @@ -36,30 +32,26 @@ | ||||
| 		typeof(b) _b = b;\ | ||||
| 		_a < _b ? _a : _b; }) | ||||
|  | ||||
| typedef enum { | ||||
| 	NORMAL = 1, | ||||
| 	MAIN_HEADING, | ||||
| 	MAIN_MENU_BOX, | ||||
| 	MAIN_MENU_FORE, | ||||
| 	MAIN_MENU_BACK, | ||||
| 	MAIN_MENU_GREY, | ||||
| 	MAIN_MENU_HEADING, | ||||
| 	SCROLLWIN_TEXT, | ||||
| 	SCROLLWIN_HEADING, | ||||
| 	SCROLLWIN_BOX, | ||||
| 	DIALOG_TEXT, | ||||
| 	DIALOG_MENU_FORE, | ||||
| 	DIALOG_MENU_BACK, | ||||
| 	DIALOG_BOX, | ||||
| 	INPUT_BOX, | ||||
| 	INPUT_HEADING, | ||||
| 	INPUT_TEXT, | ||||
| 	INPUT_FIELD, | ||||
| 	FUNCTION_TEXT, | ||||
| 	FUNCTION_HIGHLIGHT, | ||||
| 	ATTR_MAX | ||||
| } attributes_t; | ||||
| extern attributes_t attributes[]; | ||||
| extern int attr_normal; | ||||
| extern int attr_main_heading; | ||||
| extern int attr_main_menu_box; | ||||
| extern int attr_main_menu_fore; | ||||
| extern int attr_main_menu_back; | ||||
| extern int attr_main_menu_grey; | ||||
| extern int attr_main_menu_heading; | ||||
| extern int attr_scrollwin_text; | ||||
| extern int attr_scrollwin_heading; | ||||
| extern int attr_scrollwin_box; | ||||
| extern int attr_dialog_text; | ||||
| extern int attr_dialog_menu_fore; | ||||
| extern int attr_dialog_menu_back; | ||||
| extern int attr_dialog_box; | ||||
| extern int attr_input_box; | ||||
| extern int attr_input_heading; | ||||
| extern int attr_input_text; | ||||
| extern int attr_input_field; | ||||
| extern int attr_function_text; | ||||
| extern int attr_function_highlight; | ||||
|  | ||||
| typedef enum { | ||||
| 	F_HELP = 1, | ||||
| @@ -76,12 +68,7 @@ typedef enum { | ||||
| void set_colors(void); | ||||
|  | ||||
| /* this changes the windows attributes !!! */ | ||||
| void print_in_middle(WINDOW *win, | ||||
| 		int starty, | ||||
| 		int startx, | ||||
| 		int width, | ||||
| 		const char *string, | ||||
| 		chtype color); | ||||
| void print_in_middle(WINDOW *win, int y, int width, const char *str, int attrs); | ||||
| int get_line_length(const char *line); | ||||
| int get_line_no(const char *text); | ||||
| const char *get_line(const char *text, int line_no); | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| %{ | ||||
| /* SPDX-License-Identifier: GPL-2.0 */ | ||||
| /* | ||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||
|  * Released under the terms of the GNU GPL v2.0. | ||||
|  */ | ||||
| %{ | ||||
| 
 | ||||
| #include <ctype.h> | ||||
| #include <stdarg.h> | ||||
| @@ -12,6 +12,7 @@ | ||||
| #include <stdbool.h> | ||||
| 
 | ||||
| #include "lkc.h" | ||||
| #include "internal.h" | ||||
| 
 | ||||
| #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) | ||||
| 
 | ||||
| @@ -20,72 +21,82 @@ | ||||
| 
 | ||||
| int cdebug = PRINTD; | ||||
| 
 | ||||
| extern int zconflex(void); | ||||
| static void yyerror(const char *err); | ||||
| static void zconfprint(const char *err, ...); | ||||
| static void zconf_error(const char *err, ...); | ||||
| static void zconferror(const char *err); | ||||
| static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken); | ||||
| static bool zconf_endtoken(const char *tokenname, | ||||
| 			   const char *expected_tokenname); | ||||
| 
 | ||||
| struct symbol *symbol_hash[SYMBOL_HASHSIZE]; | ||||
| 
 | ||||
| static struct menu *current_menu, *current_entry; | ||||
| struct menu *current_menu, *current_entry; | ||||
| 
 | ||||
| %} | ||||
| %expect 30 | ||||
| 
 | ||||
| %union | ||||
| { | ||||
| 	char *string; | ||||
| 	struct file *file; | ||||
| 	struct symbol *symbol; | ||||
| 	struct expr *expr; | ||||
| 	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 <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 <string> T_WORD | ||||
| %token <string> T_WORD_QUOTE | ||||
| %token T_UNEQUAL | ||||
| %token T_BOOL | ||||
| %token T_CHOICE | ||||
| %token T_CLOSE_PAREN | ||||
| %token T_COLON_EQUAL | ||||
| %token T_COMMENT | ||||
| %token T_CONFIG | ||||
| %token T_DEFAULT | ||||
| %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_OPTIONAL | ||||
| %token T_PLUS_EQUAL | ||||
| %token T_PROMPT | ||||
| %token T_RANGE | ||||
| %token T_SELECT | ||||
| %token T_SOURCE | ||||
| %token T_STRING | ||||
| %token T_TRISTATE | ||||
| %token T_VISIBLE | ||||
| %token T_EOL | ||||
| %token <string> T_ASSIGN_VAL | ||||
| 
 | ||||
| %left T_OR | ||||
| %left T_AND | ||||
| %left T_EQUAL T_UNEQUAL | ||||
| %left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL | ||||
| %nonassoc T_NOT | ||||
| 
 | ||||
| %type <string> prompt | ||||
| %type <symbol> nonconst_symbol | ||||
| %type <symbol> symbol | ||||
| %type <type> type logic_type default | ||||
| %type <expr> expr | ||||
| %type <expr> if_expr | ||||
| %type <id> end | ||||
| %type <id> option_name | ||||
| %type <string> end | ||||
| %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 { | ||||
| 	fprintf(stderr, "%s:%d: missing end statement for this entry\n", | ||||
| @@ -94,71 +105,58 @@ static struct menu *current_menu, *current_entry; | ||||
| 		menu_end_menu(); | ||||
| } 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: | ||||
| 	  /* empty */ | ||||
| 	| stmt_list common_stmt | ||||
| 	| stmt_list assignment_stmt | ||||
| 	| stmt_list choice_stmt | ||||
| 	| stmt_list comment_stmt | ||||
| 	| stmt_list config_stmt | ||||
| 	| stmt_list if_stmt | ||||
| 	| stmt_list menu_stmt | ||||
| 	| stmt_list end			{ zconf_error("unexpected end statement"); } | ||||
| 	| stmt_list menuconfig_stmt | ||||
| 	| stmt_list source_stmt | ||||
| 	| 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"); } | ||||
| ; | ||||
| 
 | ||||
| option_name: | ||||
| 	T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE | ||||
| stmt_list_in_choice: | ||||
| 	  /* empty */ | ||||
| 	| stmt_list_in_choice comment_stmt | ||||
| 	| stmt_list_in_choice config_stmt | ||||
| 	| stmt_list_in_choice if_stmt_in_choice | ||||
| 	| stmt_list_in_choice source_stmt | ||||
| 	| stmt_list_in_choice error T_EOL	{ zconf_error("invalid statement"); } | ||||
| ; | ||||
| 
 | ||||
| common_stmt: | ||||
| 	  T_EOL | ||||
| 	| if_stmt | ||||
| 	| comment_stmt | ||||
| 	| config_stmt | ||||
| 	| menuconfig_stmt | ||||
| 	| source_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_entry_start: T_CONFIG T_WORD T_EOL | ||||
| config_entry_start: T_CONFIG nonconst_symbol T_EOL | ||||
| { | ||||
| 	struct symbol *sym = sym_lookup($2, 0); | ||||
| 	sym->flags |= SYMBOL_OPTIONAL; | ||||
| 	menu_add_entry(sym); | ||||
| 	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2); | ||||
| 	$2->flags |= SYMBOL_OPTIONAL; | ||||
| 	menu_add_entry($2); | ||||
| 	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2->name); | ||||
| }; | ||||
| 
 | ||||
| config_stmt: config_entry_start config_option_list | ||||
| { | ||||
| 	menu_end_entry(); | ||||
| 	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); | ||||
| 	sym->flags |= SYMBOL_OPTIONAL; | ||||
| 	menu_add_entry(sym); | ||||
| 	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2); | ||||
| 	$2->flags |= SYMBOL_OPTIONAL; | ||||
| 	menu_add_entry($2); | ||||
| 	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2->name); | ||||
| }; | ||||
| 
 | ||||
| menuconfig_stmt: menuconfig_entry_start config_option_list | ||||
| @@ -167,84 +165,75 @@ menuconfig_stmt: menuconfig_entry_start config_option_list | ||||
| 		current_entry->prompt->type = P_MENU; | ||||
| 	else | ||||
| 		zconfprint("warning: menuconfig statement without prompt"); | ||||
| 	menu_end_entry(); | ||||
| 	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); | ||||
| }; | ||||
| 
 | ||||
| config_option_list: | ||||
| 	  /* empty */ | ||||
| 	| config_option_list config_option | ||||
| 	| config_option_list symbol_option | ||||
| 	| config_option_list depends | ||||
| 	| 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", | ||||
| 		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); | ||||
| 	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); | ||||
| 	if ($1->stype != S_UNKNOWN) | ||||
| 		menu_set_type($1->stype); | ||||
| 	if ($1 != S_UNKNOWN) | ||||
| 		menu_set_type($1); | ||||
| 	printd(DEBUG_PARSE, "%s:%d:default(%u)\n", | ||||
| 		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()); | ||||
| }; | ||||
| 
 | ||||
| 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 | ||||
| { | ||||
| 	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4); | ||||
| 	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); | ||||
| }; | ||||
| 
 | ||||
| symbol_option: T_OPTION symbol_option_list T_EOL | ||||
| ; | ||||
| 
 | ||||
| symbol_option_list: | ||||
| 	  /* empty */ | ||||
| 	| symbol_option_list T_WORD symbol_option_arg | ||||
| config_option: T_MODULES T_EOL | ||||
| { | ||||
| 	const struct kconf_id *id = kconf_id_lookup($2, strlen($2)); | ||||
| 	if (id && id->flags & TF_OPTION) | ||||
| 		menu_add_option(id->token, $3); | ||||
| 	else | ||||
| 		zconfprint("warning: ignoring unknown option %s", $2); | ||||
| 	free($2); | ||||
| 	if (modules_sym) | ||||
| 		zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'", | ||||
| 			    current_entry->sym->name, modules_sym->name); | ||||
| 	modules_sym = current_entry->sym; | ||||
| }; | ||||
| 
 | ||||
| symbol_option_arg: | ||||
| 	  /* empty */		{ $$ = NULL; } | ||||
| 	| T_EQUAL prompt	{ $$ = $2; } | ||||
| ; | ||||
| 
 | ||||
| /* choice entry */ | ||||
| 
 | ||||
| choice: T_CHOICE word_opt T_EOL | ||||
| { | ||||
| 	struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); | ||||
| 	sym->flags |= SYMBOL_AUTO; | ||||
| 	sym->flags |= SYMBOL_NO_WRITE; | ||||
| 	menu_add_entry(sym); | ||||
| 	menu_add_expr(P_CHOICE, NULL, NULL); | ||||
| 	free($2); | ||||
| 	printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); | ||||
| }; | ||||
| 
 | ||||
| @@ -255,13 +244,13 @@ choice_entry: choice choice_option_list | ||||
| 
 | ||||
| choice_end: end | ||||
| { | ||||
| 	if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) { | ||||
| 	if (zconf_endtoken($1, "choice")) { | ||||
| 		menu_end_menu(); | ||||
| 		printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| choice_stmt: choice_entry choice_block choice_end | ||||
| choice_stmt: choice_entry stmt_list_in_choice choice_end | ||||
| ; | ||||
| 
 | ||||
| choice_option_list: | ||||
| @@ -269,25 +258,19 @@ choice_option_list: | ||||
| 	| choice_option_list choice_option | ||||
| 	| choice_option_list depends | ||||
| 	| 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); | ||||
| 	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->stype); | ||||
| 		printd(DEBUG_PARSE, "%s:%d:type(%u)\n", | ||||
| 			zconf_curname(), zconf_lineno(), | ||||
| 			$1->stype); | ||||
| 	} else | ||||
| 		YYERROR; | ||||
| 	menu_set_type($1); | ||||
| 	printd(DEBUG_PARSE, "%s:%d:type(%u)\n", | ||||
| 	       zconf_curname(), zconf_lineno(), $1); | ||||
| }; | ||||
| 
 | ||||
| choice_option: T_OPTIONAL T_EOL | ||||
| @@ -296,24 +279,31 @@ choice_option: T_OPTIONAL T_EOL | ||||
| 	printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); | ||||
| }; | ||||
| 
 | ||||
| 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, sym_lookup($2, 0), $3); | ||||
| 		printd(DEBUG_PARSE, "%s:%d:default\n", | ||||
| 			zconf_curname(), zconf_lineno()); | ||||
| 	} else | ||||
| 		YYERROR; | ||||
| 	menu_add_symbol(P_DEFAULT, $2, $3); | ||||
| 	printd(DEBUG_PARSE, "%s:%d:default\n", | ||||
| 	       zconf_curname(), zconf_lineno()); | ||||
| }; | ||||
| 
 | ||||
| choice_block: | ||||
| 	  /* empty */ | ||||
| 	| choice_block common_stmt | ||||
| ; | ||||
| 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; } | ||||
| 
 | ||||
| /* 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()); | ||||
| 	menu_add_entry(NULL); | ||||
| @@ -323,80 +313,72 @@ if_entry: T_IF expr nl | ||||
| 
 | ||||
| if_end: end | ||||
| { | ||||
| 	if (zconf_endtoken($1, T_IF, T_ENDIF)) { | ||||
| 	if (zconf_endtoken($1, "if")) { | ||||
| 		menu_end_menu(); | ||||
| 		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 | ||||
| if_stmt_in_choice: if_entry stmt_list_in_choice if_end | ||||
| ; | ||||
| 
 | ||||
| /* mainmenu entry */ | ||||
| 
 | ||||
| mainmenu_stmt: T_MAINMENU prompt nl | ||||
| { | ||||
| 	menu_add_prompt(P_MENU, $2, NULL); | ||||
| }; | ||||
| 
 | ||||
| /* menu entry */ | ||||
| 
 | ||||
| menu: T_MENU prompt T_EOL | ||||
| menu: T_MENU T_WORD_QUOTE T_EOL | ||||
| { | ||||
| 	menu_add_entry(NULL); | ||||
| 	menu_add_prompt(P_MENU, $2, NULL); | ||||
| 	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_end: end | ||||
| { | ||||
| 	if (zconf_endtoken($1, T_MENU, T_ENDMENU)) { | ||||
| 	if (zconf_endtoken($1, "menu")) { | ||||
| 		menu_end_menu(); | ||||
| 		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 */ | ||||
| 	| menu_block common_stmt | ||||
| 	| menu_block menu_stmt | ||||
| 	| menu_block choice_stmt | ||||
| 	| menu_option_list visible | ||||
| 	| menu_option_list depends | ||||
| ; | ||||
| 
 | ||||
| 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); | ||||
| 	zconf_nextfiles($2); | ||||
| 	free($2); | ||||
| }; | ||||
| 
 | ||||
| /* comment entry */ | ||||
| 
 | ||||
| comment: T_COMMENT prompt T_EOL | ||||
| comment: T_COMMENT T_WORD_QUOTE T_EOL | ||||
| { | ||||
| 	menu_add_entry(NULL); | ||||
| 	menu_add_prompt(P_COMMENT, $2, NULL); | ||||
| 	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); | ||||
| }; | ||||
| 
 | ||||
| comment_stmt: comment depends_list | ||||
| { | ||||
| 	menu_end_entry(); | ||||
| }; | ||||
| comment_stmt: comment comment_option_list | ||||
| ; | ||||
| 
 | ||||
| comment_option_list: | ||||
| 	  /* empty */ | ||||
| 	| comment_option_list depends | ||||
| ; | ||||
| 
 | ||||
| /* help option */ | ||||
| 
 | ||||
| @@ -408,18 +390,22 @@ help_start: T_HELP T_EOL | ||||
| 
 | ||||
| help: help_start T_HELPTEXT | ||||
| { | ||||
| 	if (current_entry->help) { | ||||
| 		free(current_entry->help); | ||||
| 		zconfprint("warning: '%s' defined with more than one help text -- only the last one will be used", | ||||
| 			   current_entry->sym->name ?: "<choice>"); | ||||
| 	} | ||||
| 
 | ||||
| 	/* 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; | ||||
| }; | ||||
| 
 | ||||
| /* depends option */ | ||||
| 
 | ||||
| depends_list: | ||||
| 	  /* empty */ | ||||
| 	| depends_list depends | ||||
| 	| depends_list T_EOL | ||||
| 	| depends_list option_error | ||||
| ; | ||||
| 
 | ||||
| depends: T_DEPENDS T_ON expr T_EOL | ||||
| { | ||||
| 	menu_add_dep($3); | ||||
| @@ -427,14 +413,7 @@ depends: T_DEPENDS T_ON expr T_EOL | ||||
| }; | ||||
| 
 | ||||
| /* visibility option */ | ||||
| 
 | ||||
| visibility_list: | ||||
| 	  /* empty */ | ||||
| 	| visibility_list visible | ||||
| 	| visibility_list T_EOL | ||||
| ; | ||||
| 
 | ||||
| visible: T_VISIBLE if_expr | ||||
| visible: T_VISIBLE if_expr T_EOL | ||||
| { | ||||
| 	menu_add_visibility($2); | ||||
| }; | ||||
| @@ -443,23 +422,14 @@ visible: T_VISIBLE if_expr | ||||
| 
 | ||||
| prompt_stmt_opt: | ||||
| 	  /* empty */ | ||||
| 	| prompt if_expr | ||||
| 	| T_WORD_QUOTE if_expr | ||||
| { | ||||
| 	menu_add_prompt(P_PROMPT, $1, $2); | ||||
| }; | ||||
| 
 | ||||
| prompt:	  T_WORD | ||||
| 	| T_WORD_QUOTE | ||||
| ; | ||||
| 
 | ||||
| end:	  T_ENDMENU T_EOL	{ $$ = $1; } | ||||
| 	| T_ENDCHOICE T_EOL	{ $$ = $1; } | ||||
| 	| T_ENDIF T_EOL		{ $$ = $1; } | ||||
| ; | ||||
| 
 | ||||
| nl: | ||||
| 	  T_EOL | ||||
| 	| nl T_EOL | ||||
| end:	  T_ENDMENU T_EOL	{ $$ = "menu"; } | ||||
| 	| T_ENDCHOICE T_EOL	{ $$ = "choice"; } | ||||
| 	| T_ENDIF T_EOL		{ $$ = "if"; } | ||||
| ; | ||||
| 
 | ||||
| if_expr:  /* empty */			{ $$ = NULL; } | ||||
| @@ -467,6 +437,10 @@ if_expr:  /* empty */			{ $$ = NULL; } | ||||
| ; | ||||
| 
 | ||||
| expr:	  symbol				{ $$ = expr_alloc_symbol($1); } | ||||
| 	| symbol T_LESS symbol			{ $$ = expr_alloc_comp(E_LTH, $1, $3); } | ||||
| 	| symbol T_LESS_EQUAL symbol		{ $$ = expr_alloc_comp(E_LEQ, $1, $3); } | ||||
| 	| symbol T_GREATER symbol		{ $$ = expr_alloc_comp(E_GTH, $1, $3); } | ||||
| 	| symbol T_GREATER_EQUAL symbol		{ $$ = expr_alloc_comp(E_GEQ, $1, $3); } | ||||
| 	| symbol T_EQUAL symbol			{ $$ = expr_alloc_comp(E_EQUAL, $1, $3); } | ||||
| 	| symbol T_UNEQUAL symbol		{ $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); } | ||||
| 	| T_OPEN_PAREN expr T_CLOSE_PAREN	{ $$ = $2; } | ||||
| @@ -475,13 +449,31 @@ expr:	  symbol				{ $$ = expr_alloc_symbol($1); } | ||||
| 	| 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); } | ||||
| ; | ||||
| 
 | ||||
| word_opt: /* empty */			{ $$ = NULL; } | ||||
| 	| 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) | ||||
| @@ -491,61 +483,51 @@ void conf_parse(const char *name) | ||||
| 
 | ||||
| 	zconf_initscan(name); | ||||
| 
 | ||||
| 	sym_init(); | ||||
| 	_menu_init(); | ||||
| 	rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); | ||||
| 
 | ||||
| 	if (getenv("ZCONF_DEBUG")) | ||||
| 		zconfdebug = 1; | ||||
| 	zconfparse(); | ||||
| 	if (zconfnerrs) | ||||
| 		yydebug = 1; | ||||
| 	yyparse(); | ||||
| 
 | ||||
| 	/* Variables are expanded in the parse phase. We can free them here. */ | ||||
| 	variable_all_del(); | ||||
| 
 | ||||
| 	if (yynerrs) | ||||
| 		exit(1); | ||||
| 	if (!modules_sym) | ||||
| 		modules_sym = sym_find( "n" ); | ||||
| 
 | ||||
| 	rootmenu.prompt->text = _(rootmenu.prompt->text); | ||||
| 	rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); | ||||
| 	if (!menu_has_prompt(&rootmenu)) { | ||||
| 		current_entry = &rootmenu; | ||||
| 		menu_add_prompt(P_MENU, "Main menu", NULL); | ||||
| 	} | ||||
| 
 | ||||
| 	menu_finalize(&rootmenu); | ||||
| 	for_all_symbols(i, sym) { | ||||
| 		if (sym_check_deps(sym)) | ||||
| 			zconfnerrs++; | ||||
| 			yynerrs++; | ||||
| 	} | ||||
| 	if (zconfnerrs) | ||||
| 	if (yynerrs) | ||||
| 		exit(1); | ||||
| 	sym_set_change_count(1); | ||||
| 	conf_set_changed(true); | ||||
| } | ||||
| 
 | ||||
| static const char *zconf_tokenname(int token) | ||||
| static bool zconf_endtoken(const char *tokenname, | ||||
| 			   const char *expected_tokenname) | ||||
| { | ||||
| 	switch (token) { | ||||
| 	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) { | ||||
| 	if (strcmp(tokenname, expected_tokenname)) { | ||||
| 		zconf_error("unexpected '%s' within %s block", | ||||
| 			kconf_id_strings + id->name, zconf_tokenname(starttoken)); | ||||
| 		zconfnerrs++; | ||||
| 			    tokenname, expected_tokenname); | ||||
| 		yynerrs++; | ||||
| 		return false; | ||||
| 	} | ||||
| 	if (current_menu->file != current_file) { | ||||
| 		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", | ||||
| 			current_menu->file->name, current_menu->lineno, | ||||
| 			zconf_tokenname(starttoken)); | ||||
| 		zconfnerrs++; | ||||
| 			expected_tokenname); | ||||
| 		yynerrs++; | ||||
| 		return false; | ||||
| 	} | ||||
| 	return true; | ||||
| @@ -566,7 +548,7 @@ static void zconf_error(const char *err, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 
 | ||||
| 	zconfnerrs++; | ||||
| 	yynerrs++; | ||||
| 	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); | ||||
| 	va_start(ap, err); | ||||
| 	vfprintf(stderr, err, ap); | ||||
| @@ -574,7 +556,7 @@ static void zconf_error(const char *err, ...) | ||||
| 	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); | ||||
| } | ||||
| @@ -607,7 +589,7 @@ static void print_symbol(FILE *out, struct menu *menu) | ||||
| 		fprintf(out, "\nconfig %s\n", sym->name); | ||||
| 	switch (sym->type) { | ||||
| 	case S_BOOLEAN: | ||||
| 		fputs("  boolean\n", out); | ||||
| 		fputs("  bool\n", out); | ||||
| 		break; | ||||
| 	case S_TRISTATE: | ||||
| 		fputs("  tristate\n", out); | ||||
| @@ -655,6 +637,11 @@ static void print_symbol(FILE *out, struct menu *menu) | ||||
| 			expr_fprint(prop->expr, out); | ||||
| 			fputc('\n', out); | ||||
| 			break; | ||||
| 		case P_IMPLY: | ||||
| 			fputs( "  imply ", out); | ||||
| 			expr_fprint(prop->expr, out); | ||||
| 			fputc('\n', out); | ||||
| 			break; | ||||
| 		case P_RANGE: | ||||
| 			fputs( "  range ", out); | ||||
| 			expr_fprint(prop->expr, out); | ||||
| @@ -665,6 +652,10 @@ static void print_symbol(FILE *out, struct menu *menu) | ||||
| 			print_quoted_string(out, prop->text); | ||||
| 			fputc('\n', out); | ||||
| 			break; | ||||
| 		case P_SYMBOL: | ||||
| 			fputs( "  symbol ", out); | ||||
| 			fprintf(out, "%s\n", prop->menu->sym->name); | ||||
| 			break; | ||||
| 		default: | ||||
| 			fprintf(out, "  unknown prop %d!\n", prop->type); | ||||
| 			break; | ||||
| @@ -724,10 +715,3 @@ void zconfdump(FILE *out) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #include "zconf.lex.c" | ||||
| #include "util.c" | ||||
| #include "confdata.c" | ||||
| #include "expr.c" | ||||
| #include "symbol.c" | ||||
| #include "menu.c" | ||||
| @@ -0,0 +1,43 @@ | ||||
| From c822f47921feb53b97f48f3aa8d1e843f5099c63 Mon Sep 17 00:00:00 2001 | ||||
| From: Stefan Reinauer <stefan.reinauer@coreboot.org> | ||||
| Date: Fri, 17 Jul 2015 17:26:48 -0700 | ||||
| Subject: [PATCH] Kconfig: Add KCONFIG_STRICT mode | ||||
|  | ||||
| This is basically a -Werror mode for Kconfig. When exporting | ||||
| KCONFIG_STRICT in the Makefile, warnings in Kconfig will produce | ||||
| errors instead. | ||||
|  | ||||
| This will make it easier to spot unclean Kconfig files, settings | ||||
| and dependencies. | ||||
|  | ||||
| Signed-off-by: Stefan Reinauer <stefan.reinauer@coreboot.org> | ||||
| --- | ||||
|  util/kconfig/confdata.c | 8 ++++++++ | ||||
|  1 file changed, 8 insertions(+) | ||||
|  | ||||
| Index: kconfig/confdata.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/confdata.c | ||||
| +++ kconfig/confdata.c | ||||
| @@ -439,6 +439,7 @@ load: | ||||
|  			if (def == S_DEF_USER) { | ||||
|  				sym = sym_find(line + 2 + strlen(CONFIG_)); | ||||
|  				if (!sym) { | ||||
| +					conf_warning("trying to assign non-existent symbol %s", line + strlen(CONFIG_)); | ||||
|  					conf_set_changed(true); | ||||
|  					continue; | ||||
|  				} | ||||
| @@ -521,6 +522,13 @@ load: | ||||
|  	} | ||||
|  	free(line); | ||||
|  	fclose(in); | ||||
| + | ||||
| +	name = getenv("KCONFIG_STRICT"); | ||||
| +	if (name && *name && conf_warnings) { | ||||
| +		fprintf(stderr, "\nERROR: %d warnings encountered, and warnings are errors.\n\n", conf_warnings); | ||||
| +		return 1; | ||||
| +	} | ||||
| + | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| @@ -0,0 +1,69 @@ | ||||
| From 20df4491aa88eb4a7f97090fbc4ff53f81926861 Mon Sep 17 00:00:00 2001 | ||||
| From: Martin Roth <martinroth@google.com> | ||||
| Date: Wed, 21 Sep 2016 14:27:26 -0600 | ||||
| Subject: [PATCH] Kconfig: Change symbol override from warning to notice | ||||
|  | ||||
| Overriding symbols within a .config is pretty common when doing | ||||
| automated builds with various different options.  The warning | ||||
| text makes it sound like this is an issue, so change it to say | ||||
| 'notice' instead.  We could get rid of it completely, but it's | ||||
| not a bad thing to know that we have two copies of the same symbol | ||||
| in the .config. | ||||
|  | ||||
| BUG=chrome-os-partner:54059 | ||||
| TEST=copy a disabled kconfig option to the end and set it to y. | ||||
| See notice text instead of warning. | ||||
|  | ||||
| Signed-off-by: Martin Roth <martinroth@google.com> | ||||
| --- | ||||
|  util/kconfig/confdata.c | 16 +++++++++++++--- | ||||
|  1 file changed, 13 insertions(+), 3 deletions(-) | ||||
|  | ||||
| Index: kconfig/confdata.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/confdata.c | ||||
| +++ kconfig/confdata.c | ||||
| @@ -184,6 +184,16 @@ static void conf_warning(const char *fmt | ||||
|  	conf_warnings++; | ||||
|  } | ||||
|   | ||||
| +static void conf_notice(const char *fmt, ...) | ||||
| +{ | ||||
| +	va_list ap; | ||||
| +	va_start(ap, fmt); | ||||
| +	fprintf(stderr, "%s:%d:notice: ", conf_filename, conf_lineno); | ||||
| +	vfprintf(stderr, fmt, ap); | ||||
| +	fprintf(stderr, "\n"); | ||||
| +	va_end(ap); | ||||
| +} | ||||
| + | ||||
|  static void conf_default_message_callback(const char *s) | ||||
|  { | ||||
|  	printf("#\n# "); | ||||
| @@ -449,7 +459,7 @@ load: | ||||
|  					sym->type = S_BOOLEAN; | ||||
|  			} | ||||
|  			if (sym->flags & def_flags) { | ||||
| -				conf_warning("override: reassigning to symbol %s", sym->name); | ||||
| +				conf_notice("override: reassigning to symbol %s", sym->name); | ||||
|  			} | ||||
|  			switch (sym->type) { | ||||
|  			case S_BOOLEAN: | ||||
| @@ -488,7 +498,7 @@ load: | ||||
|  			} | ||||
|   | ||||
|  			if (sym->flags & def_flags) { | ||||
| -				conf_warning("override: reassigning to symbol %s", sym->name); | ||||
| +				conf_notice("override: reassigning to symbol %s", sym->name); | ||||
|  			} | ||||
|  			if (conf_set_sym_val(sym, def, def_flags, p)) | ||||
|  				continue; | ||||
| @@ -513,7 +523,7 @@ load: | ||||
|  				break; | ||||
|  			case yes: | ||||
|  				if (cs->def[def].tri != no) | ||||
| -					conf_warning("override: %s changes choice state", sym->name); | ||||
| +					conf_notice("override: %s changes choice state", sym->name); | ||||
|  				cs->def[def].val = sym; | ||||
|  				break; | ||||
|  			} | ||||
| @@ -0,0 +1,25 @@ | ||||
| From 887ae0ac3dc53fc73488a4dbc1fbf36fa620ce8b Mon Sep 17 00:00:00 2001 | ||||
| From: Martin Roth <martinroth@google.com> | ||||
| Date: Tue, 6 Dec 2016 14:28:44 -0700 | ||||
| Subject: [PATCH] util/kconfig/conf.c: Fix newline in error printf | ||||
|  | ||||
| For some reason the \n in the defconfig save error was not escaped. | ||||
|  | ||||
| Signed-off-by: Martin Roth <martinroth@google.com> | ||||
| --- | ||||
|  util/kconfig/conf.c | 2 +- | ||||
|  1 file changed, 1 insertion(+), 1 deletion(-) | ||||
|  | ||||
| Index: kconfig/conf.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/conf.c | ||||
| +++ kconfig/conf.c | ||||
| @@ -900,7 +900,7 @@ int main(int ac, char **av) | ||||
|   | ||||
|  	if (input_mode == savedefconfig) { | ||||
|  		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); | ||||
|  			return 1; | ||||
|  		} | ||||
| @@ -0,0 +1,46 @@ | ||||
| From e8287a030fc8fcec7404aa6731aef21a48035786 Mon Sep 17 00:00:00 2001 | ||||
| From: Elyes HAOUAS <ehaouas@noos.fr> | ||||
| Date: Tue, 5 Jun 2018 08:41:29 +0200 | ||||
| Subject: [PATCH] {src,util}: Use NULL instead of 0 for pointer | ||||
|  | ||||
| Signed-off-by: Elyes HAOUAS <ehaouas@noos.fr> | ||||
| --- | ||||
|  util/kconfig/lxdialog/util.c | 2 +- | ||||
|  util/kconfig/qconf.h         | 8 ++++---- | ||||
|  2 files changed, 5 insertions(+), 5 deletions(-) | ||||
|  | ||||
| Index: kconfig/lxdialog/util.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/lxdialog/util.c | ||||
| +++ kconfig/lxdialog/util.c | ||||
| @@ -370,7 +370,7 @@ void print_autowrap(WINDOW * win, const | ||||
|  { | ||||
|  	int newl, cur_x, cur_y; | ||||
|  	int prompt_len, room, wlen; | ||||
| -	char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0; | ||||
| +	char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = NULL; | ||||
|   | ||||
|  	strcpy(tempstr, prompt); | ||||
|   | ||||
| Index: kconfig/qconf.h | ||||
| =================================================================== | ||||
| --- kconfig.orig/qconf.h | ||||
| +++ kconfig/qconf.h | ||||
| @@ -42,7 +42,7 @@ class ConfigList : public QTreeWidget { | ||||
|  	Q_OBJECT | ||||
|  	typedef class QTreeWidget Parent; | ||||
|  public: | ||||
| -	ConfigList(QWidget *parent, const char *name = 0); | ||||
| +	ConfigList(QWidget *parent, const char *name = NULL); | ||||
|  	~ConfigList(); | ||||
|  	void reinit(void); | ||||
|  	ConfigItem* findConfigItem(struct menu *); | ||||
| @@ -188,7 +188,7 @@ class ConfigInfoView : public QTextBrows | ||||
|  	typedef class QTextBrowser Parent; | ||||
|  	QMenu *contextMenu; | ||||
|  public: | ||||
| -	ConfigInfoView(QWidget* parent, const char *name = 0); | ||||
| +	ConfigInfoView(QWidget* parent, const char *name = NULL); | ||||
|  	bool showDebug(void) const { return _showDebug; } | ||||
|   | ||||
|  public slots: | ||||
| @@ -0,0 +1,37 @@ | ||||
| From 2796443d5a2194400e56e6762e0f748ed0f0470c Mon Sep 17 00:00:00 2001 | ||||
| From: Martin Roth <martinroth@google.com> | ||||
| Date: Wed, 10 Feb 2016 16:06:00 -0700 | ||||
| Subject: [PATCH] util/kconfig: Ignore extra symbols in configs instead of | ||||
|  failing | ||||
|  | ||||
| When updating an old .config file that has a symbol that has been | ||||
| removed from the current Kconfig tree, kconfig will generate a warning | ||||
| and fail to save the updated file.  This is incredibly annoying, and | ||||
| not the goal when trying to eliminate Kconfig warnings. | ||||
|  | ||||
| Instead of generating a warning, just print a message that it's being | ||||
| ignored.  This will remove the offending symbol, while allowing the | ||||
| updated config file to be saved. | ||||
|  | ||||
| Split the change from 1 line to 3 lines to keep it at 80 characters. | ||||
|  | ||||
| Signed-off-by: Martin Roth <martinroth@google.com> | ||||
| --- | ||||
|  util/kconfig/confdata.c | 4 +++- | ||||
|  1 file changed, 3 insertions(+), 1 deletion(-) | ||||
|  | ||||
| Index: kconfig/confdata.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/confdata.c | ||||
| +++ kconfig/confdata.c | ||||
| @@ -449,7 +449,9 @@ load: | ||||
|  			if (def == S_DEF_USER) { | ||||
|  				sym = sym_find(line + 2 + strlen(CONFIG_)); | ||||
|  				if (!sym) { | ||||
| -					conf_warning("trying to assign non-existent symbol %s", line + strlen(CONFIG_)); | ||||
| +					conf_message( | ||||
| +						"ignoring nonexistent symbol %s", | ||||
| +						line + 2 + strlen(CONFIG_)); | ||||
|  					conf_set_changed(true); | ||||
|  					continue; | ||||
|  				} | ||||
| @@ -0,0 +1,28 @@ | ||||
| From d470f1069744c3e6ef2e928217c1a4a23a87efa2 Mon Sep 17 00:00:00 2001 | ||||
| From: zbao <fishbaozi@gmail.com> | ||||
| Date: Sat, 26 Sep 2015 06:20:53 -0400 | ||||
| Subject: [PATCH] util/kconfig: Set parameter of mkdir to only one for mingw. | ||||
|  | ||||
| The second parameter is to set file permissions for the directory, which | ||||
| is not needed in mingw. | ||||
|  | ||||
| Signed-off-by: Zheng Bao <fishbaozi@gmail.com> | ||||
| --- | ||||
|  util/kconfig/confdata.c | 4 ++++ | ||||
|  1 file changed, 4 insertions(+) | ||||
|  | ||||
| Index: kconfig/confdata.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/confdata.c | ||||
| +++ kconfig/confdata.c | ||||
| @@ -164,6 +164,10 @@ struct conf_printer { | ||||
|  	void (*print_comment)(FILE *, const char *, void *); | ||||
|  }; | ||||
|   | ||||
| +#ifdef __MINGW32__ | ||||
| +#define mkdir(_n,_p) mkdir((_n)) | ||||
| +#endif | ||||
| + | ||||
|  static void conf_warning(const char *fmt, ...) | ||||
|  	__attribute__ ((format (printf, 1, 2))); | ||||
|   | ||||
| @@ -0,0 +1,189 @@ | ||||
| From af6c23be63d14860c8c1f0d9fcbc020f7c11d84d Mon Sep 17 00:00:00 2001 | ||||
| From: Stefan Reinauer <reinauer@chromium.org> | ||||
| Date: Thu, 20 Aug 2015 11:19:34 -0700 | ||||
| Subject: [PATCH] kconfig: Allow KCONFIG_STRICT outside of confdata.c | ||||
|  | ||||
| To catch dependency errors in symbol.c (such as the ones | ||||
| fixed by I51b4ee326f082c6a656a813ee5772e9c34f5c343) we need | ||||
| to check for global kconfig warnings before saving config | ||||
| files. | ||||
|  | ||||
| This patch will produce errors for wrong dependencies and | ||||
| add catching of errors to conf, nconf and mconf. Sorry, | ||||
| gconf users, you will have to wait. | ||||
|  | ||||
| Signed-off-by: Stefan Reinauer <stefan.reinauer@coreboot.org> | ||||
| --- | ||||
|  util/kconfig/conf.c     | 10 ++++++++++ | ||||
|  util/kconfig/confdata.c |  6 +----- | ||||
|  util/kconfig/lkc.h      |  3 +++ | ||||
|  util/kconfig/mconf.c    | 10 ++++++++++ | ||||
|  util/kconfig/nconf.c    | 13 +++++++++++++ | ||||
|  util/kconfig/qconf.cc   |  2 ++ | ||||
|  util/kconfig/symbol.c   |  1 + | ||||
|  7 files changed, 40 insertions(+), 5 deletions(-) | ||||
|  | ||||
| Index: kconfig/conf.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/conf.c | ||||
| +++ kconfig/conf.c | ||||
| @@ -16,6 +16,8 @@ | ||||
|   | ||||
|  #include "lkc.h" | ||||
|   | ||||
| +int kconfig_warnings = 0; | ||||
| + | ||||
|  static void conf(struct menu *menu); | ||||
|  static void check_conf(struct menu *menu); | ||||
|   | ||||
| @@ -732,6 +734,7 @@ int main(int ac, char **av) | ||||
|  	const char *progname = av[0]; | ||||
|  	int opt; | ||||
|  	const char *name, *defconfig_file = NULL /* gcc uninit */; | ||||
| +	char *env; | ||||
|  	int no_conf_write = 0; | ||||
|   | ||||
|  	tty_stdio = isatty(0) && isatty(1); | ||||
| @@ -838,6 +841,13 @@ int main(int ac, char **av) | ||||
|  		break; | ||||
|  	} | ||||
|   | ||||
| +	env = getenv("KCONFIG_STRICT"); | ||||
| +	if (env && *env && kconfig_warnings) { | ||||
| +		fprintf(stderr, "\n*** ERROR: %d warnings encountered, and " | ||||
| +			"warnings are errors.\n\n", kconfig_warnings); | ||||
| +		exit(1); | ||||
| +	} | ||||
| + | ||||
|  	if (sync_kconfig) { | ||||
|  		name = getenv("KCONFIG_NOSILENTUPDATE"); | ||||
|  		if (name && *name) { | ||||
| Index: kconfig/confdata.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/confdata.c | ||||
| +++ kconfig/confdata.c | ||||
| @@ -539,11 +539,7 @@ load: | ||||
|  	free(line); | ||||
|  	fclose(in); | ||||
|   | ||||
| -	name = getenv("KCONFIG_STRICT"); | ||||
| -	if (name && *name && conf_warnings) { | ||||
| -		fprintf(stderr, "\nERROR: %d warnings encountered, and warnings are errors.\n\n", conf_warnings); | ||||
| -		return 1; | ||||
| -	} | ||||
| +	kconfig_warnings += conf_warnings; | ||||
|   | ||||
|  	return 0; | ||||
|  } | ||||
| Index: kconfig/lkc.h | ||||
| =================================================================== | ||||
| --- kconfig.orig/lkc.h | ||||
| +++ kconfig/lkc.h | ||||
| @@ -39,6 +39,9 @@ void zconf_nextfile(const char *name); | ||||
|  int zconf_lineno(void); | ||||
|  const char *zconf_curname(void); | ||||
|   | ||||
| +/* conf.c */ | ||||
| +extern int kconfig_warnings; | ||||
| + | ||||
|  /* confdata.c */ | ||||
|  const char *conf_get_configname(void); | ||||
|  void set_all_choice_values(struct symbol *csym); | ||||
| Index: kconfig/mconf.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/mconf.c | ||||
| +++ kconfig/mconf.c | ||||
| @@ -24,6 +24,8 @@ | ||||
|   | ||||
|  #define JUMP_NB			9 | ||||
|   | ||||
| +int kconfig_warnings = 0; | ||||
| + | ||||
|  static const char mconf_readme[] = | ||||
|  "Overview\n" | ||||
|  "--------\n" | ||||
| @@ -948,6 +950,7 @@ static void conf_save(void) | ||||
|  static int handle_exit(void) | ||||
|  { | ||||
|  	int res; | ||||
| +	char *env; | ||||
|   | ||||
|  	save_and_exit = 1; | ||||
|  	reset_subtitle(); | ||||
| @@ -962,6 +965,13 @@ static int handle_exit(void) | ||||
|   | ||||
|  	end_dialog(saved_x, saved_y); | ||||
|   | ||||
| +	env = getenv("KCONFIG_STRICT"); | ||||
| +	if (env && *env && kconfig_warnings) { | ||||
| +		fprintf(stderr, "\n*** ERROR: %d warnings encountered, and " | ||||
| +			"warnings are errors.\n\n", kconfig_warnings); | ||||
| +		res = 2; | ||||
| +	} | ||||
| + | ||||
|  	switch (res) { | ||||
|  	case 0: | ||||
|  		if (conf_write(filename)) { | ||||
| Index: kconfig/nconf.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/nconf.c | ||||
| +++ kconfig/nconf.c | ||||
| @@ -15,6 +15,8 @@ | ||||
|  #include "nconf.h" | ||||
|  #include <ctype.h> | ||||
|   | ||||
| +int kconfig_warnings = 0; | ||||
| + | ||||
|  static const char nconf_global_help[] = | ||||
|  "Help windows\n" | ||||
|  "------------\n" | ||||
| @@ -645,6 +647,8 @@ static void set_config_filename(const ch | ||||
|  static int do_exit(void) | ||||
|  { | ||||
|  	int res; | ||||
| +	char *env; | ||||
| + | ||||
|  	if (!conf_get_changed()) { | ||||
|  		global_exit = 1; | ||||
|  		return 0; | ||||
| @@ -660,6 +664,15 @@ static int do_exit(void) | ||||
|  		return -1; | ||||
|  	} | ||||
|   | ||||
| +	env = getenv("KCONFIG_STRICT"); | ||||
| +	if (env && *env && kconfig_warnings) { | ||||
| +		btn_dialog(main_window, | ||||
| +			"\nWarnings encountered, and warnings are errors.\n\n", | ||||
| +			1, | ||||
| +			"<OK>"); | ||||
| +		res = 2; | ||||
| +	} | ||||
| + | ||||
|  	/* if we got here, the user really wants to exit */ | ||||
|  	switch (res) { | ||||
|  	case 0: | ||||
| Index: kconfig/qconf.cc | ||||
| =================================================================== | ||||
| --- kconfig.orig/qconf.cc | ||||
| +++ kconfig/qconf.cc | ||||
| @@ -26,6 +26,8 @@ | ||||
|  #include "images.h" | ||||
|   | ||||
|   | ||||
| +int kconfig_warnings = 0; | ||||
| + | ||||
|  static QApplication *configApp; | ||||
|  static ConfigSettings *configSettings; | ||||
|   | ||||
| Index: kconfig/symbol.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/symbol.c | ||||
| +++ kconfig/symbol.c | ||||
| @@ -319,6 +319,7 @@ static void sym_warn_unmet_dep(struct sy | ||||
|  			       "  Selected by [m]:\n"); | ||||
|   | ||||
|  	fputs(str_get(&gs), stderr); | ||||
| +	kconfig_warnings++; | ||||
|  } | ||||
|   | ||||
|  void sym_calc_value(struct symbol *sym) | ||||
| @@ -0,0 +1,94 @@ | ||||
| From 5e2355bf017b3347b29126a0eeb866558334f704 Mon Sep 17 00:00:00 2001 | ||||
| From: Stefan Reinauer <stefan.reinauer@coreboot.org> | ||||
| Date: Fri, 3 Apr 2015 20:01:38 +0200 | ||||
| Subject: [PATCH] kconfig: Add wildcard support for "source" | ||||
|  | ||||
| Kconfig's include directive "source" does not support | ||||
| wildcards (e.g. source src/mainboard/*/Kconfig) which | ||||
| makes automatic inclusion of all boards a tedious task | ||||
| and prevents us from implementing "drop in" boards. | ||||
|  | ||||
| In our Makefile.inc files we already include mainboard | ||||
| directories per wildcard, so let's add the infrastructure | ||||
| to do the same with Kconfig. | ||||
|  | ||||
| v2: change from wordexp to glob for better portability. | ||||
|  | ||||
| Signed-off-by: Stefan Reinauer <stefan.reinauer@coreboot.org> | ||||
| Signed-off-by: Patrick Georgi <pgeorgi@google.com> | ||||
| --- | ||||
|  util/kconfig/lexer.l  | 27 +++++++++++++++++++++++++++ | ||||
|  util/kconfig/lkc.h    |  1 + | ||||
|  util/kconfig/parser.y |  2 +- | ||||
|  3 files changed, 29 insertions(+), 1 deletion(-) | ||||
|  | ||||
| Index: kconfig/lexer.l | ||||
| =================================================================== | ||||
| --- kconfig.orig/lexer.l | ||||
| +++ kconfig/lexer.l | ||||
| @@ -8,6 +8,7 @@ | ||||
|  %{ | ||||
|   | ||||
|  #include <assert.h> | ||||
| +#include <glob.h> | ||||
|  #include <limits.h> | ||||
|  #include <stdio.h> | ||||
|  #include <stdlib.h> | ||||
| @@ -438,6 +439,32 @@ void zconf_nextfile(const char *name) | ||||
|  	current_file = file; | ||||
|  } | ||||
|   | ||||
| +void zconf_nextfiles(const char *wildcard) | ||||
| +{ | ||||
| +	glob_t g; | ||||
| +	char **w; | ||||
| +	int i; | ||||
| + | ||||
| +	if (glob(wildcard, 0, NULL, &g) != 0) { | ||||
| +		return; | ||||
| +	} | ||||
| +	if (g.gl_pathv == NULL) { | ||||
| +		globfree(&g); | ||||
| +		return; | ||||
| +	} | ||||
| + | ||||
| +	/* working through files backwards, since | ||||
| +	 * we're first pushing them on a stack | ||||
| +	 * before actually handling them. | ||||
| +	 */ | ||||
| +	for (i = g.gl_pathc; i > 0; i--) { | ||||
| +		w = &g.gl_pathv[i - 1]; | ||||
| +		zconf_nextfile(*w); | ||||
| +	} | ||||
| + | ||||
| +	globfree(&g); | ||||
| +} | ||||
| + | ||||
|  static void zconf_endfile(void) | ||||
|  { | ||||
|  	struct buffer *parent; | ||||
| Index: kconfig/lkc.h | ||||
| =================================================================== | ||||
| --- kconfig.orig/lkc.h | ||||
| +++ kconfig/lkc.h | ||||
| @@ -36,6 +36,7 @@ void zconf_starthelp(void); | ||||
|  FILE *zconf_fopen(const char *name); | ||||
|  void zconf_initscan(const char *name); | ||||
|  void zconf_nextfile(const char *name); | ||||
| +void zconf_nextfiles(const char *name); | ||||
|  int zconf_lineno(void); | ||||
|  const char *zconf_curname(void); | ||||
|   | ||||
| Index: kconfig/parser.y | ||||
| =================================================================== | ||||
| --- kconfig.orig/parser.y | ||||
| +++ kconfig/parser.y | ||||
| @@ -358,7 +358,7 @@ menu_option_list: | ||||
|  source_stmt: T_SOURCE T_WORD_QUOTE T_EOL | ||||
|  { | ||||
|  	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); | ||||
| -	zconf_nextfile($2); | ||||
| +	zconf_nextfiles($2); | ||||
|  	free($2); | ||||
|  }; | ||||
|   | ||||
| @@ -0,0 +1,93 @@ | ||||
| commit ab0cc6067d5a00182e89fbec82b942eb3d803204 | ||||
| Author: Patrick Georgi <pgeorgi@google.com> | ||||
| Date:   Fri Nov 22 22:08:15 2019 +0100 | ||||
|  | ||||
|     util/kconfig: Allow emitting false booleans into kconfig output | ||||
|  | ||||
|     This is controlled by an environment variable so the same tool is | ||||
|     useful in different contexts. | ||||
|  | ||||
|     Change-Id: I9e62b05e45709f1539e455e2eed37308609be15e | ||||
|     Signed-off-by: Patrick Georgi <pgeorgi@google.com> | ||||
|  | ||||
| Index: kconfig/confdata.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/confdata.c | ||||
| +++ kconfig/confdata.c | ||||
| @@ -687,6 +687,9 @@ header_print_symbol(FILE *fp, struct sym | ||||
|   | ||||
|  		switch (*value) { | ||||
|  		case 'n': | ||||
| +			if (getenv("KCONFIG_NEGATIVES") != NULL) | ||||
| +				fprintf(fp, "#define %s%s%s 0\n", | ||||
| +				    CONFIG_, sym->name, suffix); | ||||
|  			break; | ||||
|  		case 'm': | ||||
|  			suffix = "_MODULE"; | ||||
| @@ -702,14 +705,28 @@ header_print_symbol(FILE *fp, struct sym | ||||
|   | ||||
|  		if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) | ||||
|  			prefix = "0x"; | ||||
| +		if (value[0] == '\0') { | ||||
| +			/* | ||||
| +			 * prefix is reset to remain closer to the older | ||||
| +			 * coreboot patch. No need to keep this once kconfig | ||||
| +			 * is fully upreved | ||||
| +			 */ | ||||
| +			prefix = ""; | ||||
| +			value = "0"; | ||||
| +		} | ||||
|  		fprintf(fp, "#define %s%s %s%s\n", | ||||
|  		    CONFIG_, sym->name, prefix, value); | ||||
|  		break; | ||||
|  	} | ||||
|  	case S_STRING: | ||||
| +		if (value[0] == '\0') | ||||
| +			break; | ||||
| +		if (!(sym->flags & SYMBOL_WRITE)) | ||||
| +			break; | ||||
| +		/* fall through */ | ||||
|  	case S_INT: | ||||
|  		fprintf(fp, "#define %s%s %s\n", | ||||
| -		    CONFIG_, sym->name, value); | ||||
| +		    CONFIG_, sym->name, value[0]?value:"0"); | ||||
|  		break; | ||||
|  	default: | ||||
|  		break; | ||||
| @@ -1080,6 +1097,7 @@ int conf_write_autoconf(int overwrite) | ||||
|  	const char *autoconf_name = conf_get_autoconfig_name(); | ||||
|  	FILE *out, *out_h; | ||||
|  	int i; | ||||
| +	int print_negatives = getenv("KCONFIG_NEGATIVES") != NULL; | ||||
|   | ||||
|  	if (!overwrite && is_present(autoconf_name)) | ||||
|  		return 0; | ||||
| @@ -1104,11 +1122,13 @@ int conf_write_autoconf(int overwrite) | ||||
|   | ||||
|  	for_all_symbols(i, sym) { | ||||
|  		sym_calc_value(sym); | ||||
| -		if (!(sym->flags & SYMBOL_WRITE) || !sym->name) | ||||
| +		if (!(sym->flags & SYMBOL_WRITE) && !print_negatives) | ||||
| +			continue; | ||||
| +		if (!sym->name) | ||||
|  			continue; | ||||
|   | ||||
|  		/* 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, print_negatives?NULL:(void *)1); | ||||
|  		conf_write_symbol(out_h, sym, &header_printer_cb, NULL); | ||||
|  	} | ||||
|  	fclose(out); | ||||
| Index: kconfig/symbol.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/symbol.c | ||||
| +++ kconfig/symbol.c | ||||
| @@ -757,7 +757,7 @@ const char *sym_get_string_default(struc | ||||
|  		} | ||||
|  	case S_INT: | ||||
|  	case S_HEX: | ||||
| -		return str; | ||||
| +		return "0"; | ||||
|  	case S_STRING: | ||||
|  		return str; | ||||
|  	case S_UNKNOWN: | ||||
							
								
								
									
										16
									
								
								util/kconfig/patches/0010-reenable-source-in-choice.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								util/kconfig/patches/0010-reenable-source-in-choice.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| Kconfig 5.8 (since commit 09d5873e4d1f70202314b5fe40160f9b14b9d2d0) | ||||
| blocks using the source statement within choice but that's a pattern we | ||||
| use intensively. Re-enable it. | ||||
|  | ||||
| Index: kconfig/parser.y | ||||
| =================================================================== | ||||
| --- kconfig.orig/parser.y | ||||
| +++ kconfig/parser.y | ||||
| @@ -134,6 +134,7 @@ stmt_list_in_choice: | ||||
|  	| stmt_list_in_choice comment_stmt | ||||
|  	| stmt_list_in_choice config_stmt | ||||
|  	| stmt_list_in_choice if_stmt_in_choice | ||||
| +	| stmt_list_in_choice source_stmt | ||||
|  	| stmt_list_in_choice error T_EOL	{ zconf_error("invalid statement"); } | ||||
|  ; | ||||
|   | ||||
| @@ -0,0 +1,39 @@ | ||||
| Index: kconfig/confdata.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/confdata.c | ||||
| +++ kconfig/confdata.c | ||||
| @@ -241,6 +241,13 @@ static const char *conf_get_autoconfig_n | ||||
|  	return name ? name : "include/config/auto.conf"; | ||||
|  } | ||||
|   | ||||
| +static const char *conf_get_autobase_name(void) | ||||
| +{ | ||||
| +	char *name = getenv("KCONFIG_SPLITCONFIG"); | ||||
| + | ||||
| +	return name ? name : "include/config/"; | ||||
| +} | ||||
| + | ||||
|  static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) | ||||
|  { | ||||
|  	char *p2; | ||||
| @@ -1024,7 +1031,7 @@ static int conf_touch_deps(void) | ||||
|  	struct symbol *sym; | ||||
|  	int res, i; | ||||
|   | ||||
| -	strcpy(depfile_path, "include/config/"); | ||||
| +	strcpy(depfile_path, conf_get_autobase_name()); | ||||
|  	depfile_prefix_len = strlen(depfile_path); | ||||
|   | ||||
|  	name = conf_get_autoconfig_name(); | ||||
| @@ -1102,7 +1109,10 @@ int conf_write_autoconf(int overwrite) | ||||
|  	if (!overwrite && is_present(autoconf_name)) | ||||
|  		return 0; | ||||
|   | ||||
| -	conf_write_dep("include/config/auto.conf.cmd"); | ||||
| +	char autoconfcmd_path[PATH_MAX]; | ||||
| +	snprintf(autoconfcmd_path, sizeof(autoconfcmd_path), "%s%s", | ||||
| +		conf_get_autobase_name(), "auto.conf.cmd"); | ||||
| +	conf_write_dep(autoconfcmd_path); | ||||
|   | ||||
|  	if (conf_touch_deps()) | ||||
|  		return 1; | ||||
							
								
								
									
										124
									
								
								util/kconfig/patches/0012-safer-tmpfiles.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								util/kconfig/patches/0012-safer-tmpfiles.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,124 @@ | ||||
| commit 7b2deddbb0ef350e189fe42c025b07c943aedc4c | ||||
| Author: Raul E Rangel <rrangel@chromium.org> | ||||
| Date:   Thu Jul 25 15:49:52 2019 -0600 | ||||
|  | ||||
|     Kconfig: Write tmp files into same directory as target files | ||||
|  | ||||
|     This removes the need for COREBOOT_BUILD_DIR in Kconfig. Since the | ||||
|     original files will be replaced with the tmp file, the parent directory | ||||
|     already needs to be writable. | ||||
|  | ||||
|     Before this change, the tmp files would be created in the CWD (src) if | ||||
|     COREBOOT_BUILD_DIR was not specified. | ||||
|  | ||||
|     BUG=b:112267918 | ||||
|     TEST=emerge-grunt coreboot and verified no tmp files were created in the | ||||
|     src directory. | ||||
|  | ||||
|     Change-Id: Icdaf2ff3dd1ec98813b75ef55b96e38e1ca19ec7 | ||||
|     Signed-off-by: Raul E Rangel <rrangel@chromium.org> | ||||
|     Reviewed-on: https://review.coreboot.org/c/coreboot/+/34244 | ||||
|     Reviewed-by: Martin Roth <martinroth@google.com> | ||||
|     Tested-by: build bot (Jenkins) <no-reply@coreboot.org> | ||||
|  | ||||
| Index: kconfig/confdata.c | ||||
| =================================================================== | ||||
| --- kconfig.orig/confdata.c | ||||
| +++ kconfig/confdata.c | ||||
| @@ -880,6 +880,16 @@ next_menu: | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| + | ||||
| +static int conf_mktemp(const char *path, char *tmpfile) | ||||
| +{ | ||||
| +	if (snprintf(tmpfile, PATH_MAX, "%s.tmp.XXXXXX", path) >= PATH_MAX) { | ||||
| +		errno = EOVERFLOW; | ||||
| +		return -1; | ||||
| +	} | ||||
| +	return mkstemp(tmpfile); | ||||
| +} | ||||
| + | ||||
|  int conf_write(const char *name) | ||||
|  { | ||||
|  	FILE *out; | ||||
| @@ -1001,7 +1011,14 @@ static int conf_write_dep(const char *na | ||||
|  	struct file *file; | ||||
|  	FILE *out; | ||||
|   | ||||
| -	out = fopen("..config.tmp", "w"); | ||||
| +	if (make_parent_dir(name)) | ||||
| +		return 1; | ||||
| +	char filename[PATH_MAX]; | ||||
| +	int fd = conf_mktemp(name, filename); | ||||
| +	if (fd == -1) | ||||
| +		return 1; | ||||
| + | ||||
| +	out = fdopen(fd, "w"); | ||||
|  	if (!out) | ||||
|  		return 1; | ||||
|  	fprintf(out, "deps_config := \\\n"); | ||||
| @@ -1019,9 +1036,7 @@ static int conf_write_dep(const char *na | ||||
|  	fprintf(out, "\n$(deps_config): ;\n"); | ||||
|  	fclose(out); | ||||
|   | ||||
| -	if (make_parent_dir(name)) | ||||
| -		return 1; | ||||
| -	rename("..config.tmp", name); | ||||
| +	rename(filename, name); | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| @@ -1117,11 +1132,26 @@ int conf_write_autoconf(int overwrite) | ||||
|  	if (conf_touch_deps()) | ||||
|  		return 1; | ||||
|   | ||||
| -	out = fopen(".tmpconfig", "w"); | ||||
| +	if (make_parent_dir(autoconf_name)) | ||||
| +		return 1; | ||||
| +	char filename[PATH_MAX]; | ||||
| +	int fd = conf_mktemp(autoconf_name, filename); | ||||
| +	if (fd == -1) | ||||
| +		return 1; | ||||
| +	out = fdopen(fd, "w"); | ||||
|  	if (!out) | ||||
|  		return 1; | ||||
|   | ||||
| -	out_h = fopen(".tmpconfig.h", "w"); | ||||
| +	name = getenv("KCONFIG_AUTOHEADER"); | ||||
| +	if (!name) | ||||
| +		name = "include/generated/autoconf.h"; | ||||
| +	if (make_parent_dir(name)) | ||||
| +		return 1; | ||||
| +	char filename_h[PATH_MAX]; | ||||
| +	int fd_h = conf_mktemp(name, filename_h); | ||||
| +	if (fd_h == -1) | ||||
| +		return 1; | ||||
| +	out_h = fdopen(fd_h, "w"); | ||||
|  	if (!out_h) { | ||||
|  		fclose(out); | ||||
|  		return 1; | ||||
| @@ -1144,21 +1174,14 @@ int conf_write_autoconf(int overwrite) | ||||
|  	fclose(out); | ||||
|  	fclose(out_h); | ||||
|   | ||||
| -	name = getenv("KCONFIG_AUTOHEADER"); | ||||
| -	if (!name) | ||||
| -		name = "include/generated/autoconf.h"; | ||||
| -	if (make_parent_dir(name)) | ||||
| -		return 1; | ||||
| -	if (rename(".tmpconfig.h", name)) | ||||
| +	if (rename(filename_h, name)) | ||||
|  		return 1; | ||||
|   | ||||
| -	if (make_parent_dir(autoconf_name)) | ||||
| -		return 1; | ||||
|  	/* | ||||
|  	 * This must be the last step, kbuild has a dependency on auto.conf | ||||
|  	 * and this marks the successful completion of the previous steps. | ||||
|  	 */ | ||||
| -	if (rename(".tmpconfig", autoconf_name)) | ||||
| +	if (rename(filename, autoconf_name)) | ||||
|  		return 1; | ||||
|   | ||||
|  	return 0; | ||||
							
								
								
									
										12
									
								
								util/kconfig/patches/series
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								util/kconfig/patches/series
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| 0001-Kconfig-Add-KCONFIG_STRICT-mode.patch | ||||
| 0002-Kconfig-Change-symbol-override-from-warning-to-notic.patch | ||||
| 0003-util-kconfig-conf.c-Fix-newline-in-error-printf.patch | ||||
| 0004-src-util-Use-NULL-instead-of-0-for-pointer.patch | ||||
| 0005-util-kconfig-Ignore-extra-symbols-in-configs-instead.patch | ||||
| 0006-util-kconfig-Set-parameter-of-mkdir-to-only-one-for-.patch | ||||
| 0007-kconfig-Allow-KCONFIG_STRICT-outside-of-confdata.c.patch | ||||
| 0008-kconfig-Add-wildcard-support-for-source.patch | ||||
| 0009-util-kconfig-Allow-emitting-false-booleans-into-kconfig-output.patch | ||||
| 0010-reenable-source-in-choice.patch | ||||
| 0011-remove-include-config-hardcodes.patch | ||||
| 0012-safer-tmpfiles.patch | ||||
							
								
								
									
										574
									
								
								util/kconfig/preprocess.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										574
									
								
								util/kconfig/preprocess.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,574 @@ | ||||
| // 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 xstrdup(""); | ||||
| } | ||||
|  | ||||
| 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) | ||||
| { | ||||
| 	return !(isalnum(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); | ||||
| } | ||||
							
								
								
									
										24
									
								
								util/kconfig/qconf-cfg.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										24
									
								
								util/kconfig/qconf-cfg.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| #!/bin/sh | ||||
| # SPDX-License-Identifier: GPL-2.0 | ||||
|  | ||||
| PKG="Qt5Core Qt5Gui Qt5Widgets" | ||||
|  | ||||
| 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 $PKG)\" | ||||
| 	echo libs=\"$(pkg-config --libs $PKG)\" | ||||
| 	echo moc=\"$(pkg-config --variable=host_bins Qt5Core)/moc\" | ||||
| 	exit 0 | ||||
| fi | ||||
|  | ||||
| echo >&2 "*" | ||||
| echo >&2 "* Could not find Qt5 via pkg-config." | ||||
| echo >&2 "* Please install Qt5 and make sure it's in PKG_CONFIG_PATH" | ||||
| echo >&2 "*" | ||||
| exit 1 | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,25 +1,24 @@ | ||||
| /* SPDX-License-Identifier: GPL-2.0 */ | ||||
| /* | ||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||
|  * Released under the terms of the GNU GPL v2.0. | ||||
|  */ | ||||
|  | ||||
| #include <QTextBrowser> | ||||
| #include <QTreeWidget> | ||||
| #include <QMainWindow> | ||||
| #include <QHeaderView> | ||||
| #include <qsettings.h> | ||||
| #include <QPushButton> | ||||
| #include <QSettings> | ||||
| #include <QLineEdit> | ||||
| #include <QSplitter> | ||||
| #include <QCheckBox> | ||||
| #include <QDialog> | ||||
| #include <QHeaderView> | ||||
| #include <QLineEdit> | ||||
| #include <QMainWindow> | ||||
| #include <QPushButton> | ||||
| #include <QSettings> | ||||
| #include <QSplitter> | ||||
| #include <QStyledItemDelegate> | ||||
| #include <QTextBrowser> | ||||
| #include <QTreeWidget> | ||||
|  | ||||
| #include "expr.h" | ||||
|  | ||||
| class ConfigView; | ||||
| class ConfigList; | ||||
| class ConfigItem; | ||||
| class ConfigLineEdit; | ||||
| class ConfigMainWindow; | ||||
|  | ||||
| class ConfigSettings : public QSettings { | ||||
| @@ -30,7 +29,7 @@ public: | ||||
| }; | ||||
|  | ||||
| enum colIdx { | ||||
| 	promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr | ||||
| 	promptColIdx, nameColIdx, dataColIdx | ||||
| }; | ||||
| enum listMode { | ||||
| 	singleMode, menuMode, symbolMode, fullMode, listMode | ||||
| @@ -43,13 +42,16 @@ class ConfigList : public QTreeWidget { | ||||
| 	Q_OBJECT | ||||
| 	typedef class QTreeWidget Parent; | ||||
| public: | ||||
| 	ConfigList(ConfigView* p, const char *name = NULL); | ||||
| 	ConfigList(QWidget *parent, const char *name = NULL); | ||||
| 	~ConfigList(); | ||||
| 	void reinit(void); | ||||
| 	ConfigView* parent(void) const | ||||
| 	{ | ||||
| 		return (ConfigView*)Parent::parent(); | ||||
| 	} | ||||
| 	ConfigItem* findConfigItem(struct menu *); | ||||
| 	void setSelected(QTreeWidgetItem *item, bool enable) { | ||||
| 		for (int i = 0; i < selectedItems().size(); i++) | ||||
| 			selectedItems().at(i)->setSelected(false); | ||||
|  | ||||
| 		item->setSelected(enable); | ||||
| 	} | ||||
|  | ||||
| protected: | ||||
| 	void keyPressEvent(QKeyEvent *e); | ||||
| @@ -63,61 +65,52 @@ protected: | ||||
| public slots: | ||||
| 	void setRootMenu(struct menu *menu); | ||||
|  | ||||
| 	void updateList(ConfigItem *item); | ||||
| 	void updateList(); | ||||
| 	void setValue(ConfigItem* item, tristate val); | ||||
| 	void changeValue(ConfigItem* item); | ||||
| 	void updateSelection(void); | ||||
| 	void saveSettings(void); | ||||
| 	void setOptionMode(QAction *action); | ||||
| 	void setShowName(bool on); | ||||
|  | ||||
| signals: | ||||
| 	void menuChanged(struct menu *menu); | ||||
| 	void menuSelected(struct menu *menu); | ||||
| 	void itemSelected(struct menu *menu); | ||||
| 	void parentSelected(void); | ||||
| 	void gotFocus(struct menu *); | ||||
| 	void showNameChanged(bool on); | ||||
|  | ||||
| public: | ||||
| 	void updateListAll(void) | ||||
| 	{ | ||||
| 		updateAll = true; | ||||
| 		updateList(NULL); | ||||
| 		updateList(); | ||||
| 		updateAll = false; | ||||
| 	} | ||||
| 	ConfigList* listView() | ||||
| 	{ | ||||
| 		return this; | ||||
| 	} | ||||
| 	ConfigItem* firstChild() const | ||||
| 	{ | ||||
| 		return (ConfigItem *)children().first(); | ||||
| 	} | ||||
| 	void addColumn(colIdx idx) | ||||
| 	{ | ||||
| 		showColumn(idx); | ||||
| 	} | ||||
| 	void removeColumn(colIdx idx) | ||||
| 	{ | ||||
| 		hideColumn(idx); | ||||
| 	} | ||||
| 	void setAllOpen(bool open); | ||||
| 	void setParentMenu(void); | ||||
|  | ||||
| 	bool menuSkip(struct menu *); | ||||
|  | ||||
| 	void updateMenuList(ConfigItem *parent, struct menu*); | ||||
| 	void updateMenuList(ConfigList *parent, struct menu*); | ||||
| 	void updateMenuList(struct menu *menu); | ||||
|  | ||||
| 	bool updateAll; | ||||
|  | ||||
| 	QPixmap symbolYesPix, symbolModPix, symbolNoPix; | ||||
| 	QPixmap choiceYesPix, choiceNoPix; | ||||
| 	QPixmap menuPix, menuInvPix, menuBackPix, voidPix; | ||||
|  | ||||
| 	bool showName, showRange, showData; | ||||
| 	bool showName; | ||||
| 	enum listMode mode; | ||||
| 	enum optionMode optMode; | ||||
| 	struct menu *rootEntry; | ||||
| 	QPalette disabledColorGroup; | ||||
| 	QPalette inactivedColorGroup; | ||||
| 	QMenu* headerPopup; | ||||
|  | ||||
| 	static QList<ConfigList *> allLists; | ||||
| 	static void updateListForAll(); | ||||
| 	static void updateListAllForAll(); | ||||
|  | ||||
| 	static QAction *showNormalAction, *showAllAction, *showPromptAction; | ||||
| }; | ||||
|  | ||||
| class ConfigItem : public QTreeWidgetItem { | ||||
| @@ -140,7 +133,6 @@ public: | ||||
| 	} | ||||
| 	~ConfigItem(void); | ||||
| 	void init(void); | ||||
| 	void okRename(int col); | ||||
| 	void updateMenu(void); | ||||
| 	void testUpdateMenu(bool v); | ||||
| 	ConfigList* listView() const | ||||
| @@ -165,82 +157,36 @@ public: | ||||
|  | ||||
| 		return ret; | ||||
| 	} | ||||
| 	void setText(colIdx idx, const QString& text) | ||||
| 	{ | ||||
| 		Parent::setText(idx, text); | ||||
| 	} | ||||
| 	QString text(colIdx idx) const | ||||
| 	{ | ||||
| 		return Parent::text(idx); | ||||
| 	} | ||||
| 	void setPixmap(colIdx idx, const QIcon &icon) | ||||
| 	{ | ||||
| 		Parent::setIcon(idx, icon); | ||||
| 	} | ||||
| 	const QIcon pixmap(colIdx idx) const | ||||
| 	{ | ||||
| 		return icon(idx); | ||||
| 	} | ||||
| 	// TODO: Implement paintCell | ||||
|  | ||||
| 	ConfigItem* nextItem; | ||||
| 	struct menu *menu; | ||||
| 	bool visible; | ||||
| 	bool goParent; | ||||
|  | ||||
| 	static QIcon symbolYesIcon, symbolModIcon, symbolNoIcon; | ||||
| 	static QIcon choiceYesIcon, choiceNoIcon; | ||||
| 	static QIcon menuIcon, menubackIcon; | ||||
| }; | ||||
|  | ||||
| class ConfigLineEdit : public QLineEdit { | ||||
| 	Q_OBJECT | ||||
| 	typedef class QLineEdit Parent; | ||||
| class ConfigItemDelegate : public QStyledItemDelegate | ||||
| { | ||||
| private: | ||||
| 	struct menu *menu; | ||||
| public: | ||||
| 	ConfigLineEdit(ConfigView* parent); | ||||
| 	ConfigView* parent(void) const | ||||
| 	{ | ||||
| 		return (ConfigView*)Parent::parent(); | ||||
| 	} | ||||
| 	void show(ConfigItem *i); | ||||
| 	void keyPressEvent(QKeyEvent *e); | ||||
|  | ||||
| public: | ||||
| 	ConfigItem *item; | ||||
| }; | ||||
|  | ||||
| class ConfigView : public QWidget { | ||||
| 	Q_OBJECT | ||||
| 	typedef class QWidget Parent; | ||||
| public: | ||||
| 	ConfigView(QWidget* parent, const char *name = NULL); | ||||
| 	~ConfigView(void); | ||||
| 	static void updateList(ConfigItem* item); | ||||
| 	static void updateListAll(void); | ||||
|  | ||||
| 	bool showName(void) const { return list->showName; } | ||||
| 	bool showRange(void) const { return list->showRange; } | ||||
| 	bool showData(void) const { return list->showData; } | ||||
| public slots: | ||||
| 	void setShowName(bool); | ||||
| 	void setShowRange(bool); | ||||
| 	void setShowData(bool); | ||||
| 	void setOptionMode(QAction *); | ||||
| signals: | ||||
| 	void showNameChanged(bool); | ||||
| 	void showRangeChanged(bool); | ||||
| 	void showDataChanged(bool); | ||||
| public: | ||||
| 	ConfigList* list; | ||||
| 	ConfigLineEdit* lineEdit; | ||||
|  | ||||
| 	static ConfigView* viewList; | ||||
| 	ConfigView* nextView; | ||||
|  | ||||
| 	static QAction *showNormalAction; | ||||
| 	static QAction *showAllAction; | ||||
| 	static QAction *showPromptAction; | ||||
| 	ConfigItemDelegate(QObject *parent = nullptr) | ||||
| 		: QStyledItemDelegate(parent) {} | ||||
| 	QWidget *createEditor(QWidget *parent, | ||||
| 			      const QStyleOptionViewItem &option, | ||||
| 			      const QModelIndex &index) const override; | ||||
| 	void setModelData(QWidget *editor, QAbstractItemModel *model, | ||||
| 			  const QModelIndex &index) const override; | ||||
| }; | ||||
|  | ||||
| class ConfigInfoView : public QTextBrowser { | ||||
| 	Q_OBJECT | ||||
| 	typedef class QTextBrowser Parent; | ||||
| 	QMenu *contextMenu; | ||||
| public: | ||||
| 	ConfigInfoView(QWidget* parent, const char *name = NULL); | ||||
| 	bool showDebug(void) const { return _showDebug; } | ||||
| @@ -249,6 +195,7 @@ public slots: | ||||
| 	void setInfo(struct menu *menu); | ||||
| 	void saveSettings(void); | ||||
| 	void setShowDebug(bool); | ||||
| 	void clicked (const QUrl &url); | ||||
|  | ||||
| signals: | ||||
| 	void showDebugChanged(bool); | ||||
| @@ -260,8 +207,7 @@ protected: | ||||
| 	QString debug_info(struct symbol *sym); | ||||
| 	static QString print_filter(const QString &str); | ||||
| 	static void expr_print_help(void *data, struct symbol *sym, const char *str); | ||||
| 	QMenu *createStandardContextMenu(const QPoint & pos); | ||||
| 	void contextMenuEvent(QContextMenuEvent *e); | ||||
| 	void contextMenuEvent(QContextMenuEvent *event); | ||||
|  | ||||
| 	struct symbol *sym; | ||||
| 	struct menu *_menu; | ||||
| @@ -272,7 +218,7 @@ class ConfigSearchWindow : public QDialog { | ||||
| 	Q_OBJECT | ||||
| 	typedef class QDialog Parent; | ||||
| public: | ||||
| 	ConfigSearchWindow(ConfigMainWindow* parent, const char *name = NULL); | ||||
| 	ConfigSearchWindow(ConfigMainWindow *parent); | ||||
|  | ||||
| public slots: | ||||
| 	void saveSettings(void); | ||||
| @@ -282,7 +228,7 @@ protected: | ||||
| 	QLineEdit* editField; | ||||
| 	QPushButton* searchButton; | ||||
| 	QSplitter* split; | ||||
| 	ConfigView* list; | ||||
| 	ConfigList *list; | ||||
| 	ConfigInfoView* info; | ||||
|  | ||||
| 	struct symbol **result; | ||||
| @@ -291,12 +237,14 @@ protected: | ||||
| class ConfigMainWindow : public QMainWindow { | ||||
| 	Q_OBJECT | ||||
|  | ||||
| 	char *configname; | ||||
| 	static QAction *saveAction; | ||||
| 	static void conf_changed(void); | ||||
| public: | ||||
| 	ConfigMainWindow(void); | ||||
| public slots: | ||||
| 	void changeMenu(struct menu *); | ||||
| 	void changeItens(struct menu *); | ||||
| 	void setMenuLink(struct menu *); | ||||
| 	void listFocusChanged(void); | ||||
| 	void goBack(void); | ||||
| @@ -315,12 +263,9 @@ protected: | ||||
| 	void closeEvent(QCloseEvent *e); | ||||
|  | ||||
| 	ConfigSearchWindow *searchWindow; | ||||
| 	ConfigView *menuView; | ||||
| 	ConfigList *menuList; | ||||
| 	ConfigView *configView; | ||||
| 	ConfigList *configList; | ||||
| 	ConfigInfoView *helpText; | ||||
| 	QToolBar *toolBar; | ||||
| 	QAction *backAction; | ||||
| 	QAction *singleViewAction; | ||||
| 	QAction *splitViewAction; | ||||
|   | ||||
							
								
								
									
										704
									
								
								util/kconfig/streamline_config.pl
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										704
									
								
								util/kconfig/streamline_config.pl
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,704 @@ | ||||
| #!/usr/bin/env perl | ||||
| # SPDX-License-Identifier: GPL-2.0 | ||||
| # | ||||
| # Copyright 2005-2009 - Steven Rostedt | ||||
| # | ||||
| #  It's simple enough to figure out how this works. | ||||
| #  If not, then you can ask me at stripconfig@goodmis.org | ||||
| # | ||||
| # What it does? | ||||
| # | ||||
| #   If you have installed a Linux kernel from a distribution | ||||
| #   that turns on way too many modules than you need, and | ||||
| #   you only want the modules you use, then this program | ||||
| #   is perfect for you. | ||||
| # | ||||
| #   It gives you the ability to turn off all the modules that are | ||||
| #   not loaded on your system. | ||||
| # | ||||
| # Howto: | ||||
| # | ||||
| #  1. Boot up the kernel that you want to stream line the config on. | ||||
| #  2. Change directory to the directory holding the source of the | ||||
| #       kernel that you just booted. | ||||
| #  3. Copy the configuration file to this directory as .config | ||||
| #  4. Have all your devices that you need modules for connected and | ||||
| #      operational (make sure that their corresponding modules are loaded) | ||||
| #  5. Run this script redirecting the output to some other file | ||||
| #       like config_strip. | ||||
| #  6. Back up your old config (if you want too). | ||||
| #  7. copy the config_strip file to .config | ||||
| #  8. Run "make oldconfig" | ||||
| # | ||||
| #  Now your kernel is ready to be built with only the modules that | ||||
| #  are loaded. | ||||
| # | ||||
| # Here's what I did with my Debian distribution. | ||||
| # | ||||
| #    cd /usr/src/linux-2.6.10 | ||||
| #    cp /boot/config-2.6.10-1-686-smp .config | ||||
| #    ~/bin/streamline_config > config_strip | ||||
| #    mv .config config_sav | ||||
| #    mv config_strip .config | ||||
| #    make oldconfig | ||||
| # | ||||
| use warnings; | ||||
| use strict; | ||||
| use Getopt::Long; | ||||
|  | ||||
| # set the environment variable LOCALMODCONFIG_DEBUG to get | ||||
| # debug output. | ||||
| my $debugprint = 0; | ||||
| $debugprint = 1 if (defined($ENV{LOCALMODCONFIG_DEBUG})); | ||||
|  | ||||
| sub dprint { | ||||
|     return if (!$debugprint); | ||||
|     print STDERR @_; | ||||
| } | ||||
|  | ||||
| my $uname = `uname -r`; | ||||
| chomp $uname; | ||||
|  | ||||
| my @searchconfigs = ( | ||||
| 	{ | ||||
| 	    "file" => ".config", | ||||
| 	    "exec" => "cat", | ||||
| 	}, | ||||
| 	{ | ||||
| 	    "file" => "/proc/config.gz", | ||||
| 	    "exec" => "zcat", | ||||
| 	}, | ||||
| 	{ | ||||
| 	    "file" => "/boot/config-$uname", | ||||
| 	    "exec" => "cat", | ||||
| 	}, | ||||
| 	{ | ||||
| 	    "file" => "/boot/vmlinuz-$uname", | ||||
| 	    "exec" => "scripts/extract-ikconfig", | ||||
| 	    "test" => "scripts/extract-ikconfig", | ||||
| 	}, | ||||
| 	{ | ||||
| 	    "file" => "vmlinux", | ||||
| 	    "exec" => "scripts/extract-ikconfig", | ||||
| 	    "test" => "scripts/extract-ikconfig", | ||||
| 	}, | ||||
| 	{ | ||||
| 	    "file" => "/lib/modules/$uname/kernel/kernel/configs.ko", | ||||
| 	    "exec" => "scripts/extract-ikconfig", | ||||
| 	    "test" => "scripts/extract-ikconfig", | ||||
| 	}, | ||||
| 	{ | ||||
| 	    "file" => "kernel/configs.ko", | ||||
| 	    "exec" => "scripts/extract-ikconfig", | ||||
| 	    "test" => "scripts/extract-ikconfig", | ||||
| 	}, | ||||
| 	{ | ||||
| 	    "file" => "kernel/configs.o", | ||||
| 	    "exec" => "scripts/extract-ikconfig", | ||||
| 	    "test" => "scripts/extract-ikconfig", | ||||
| 	}, | ||||
| ); | ||||
|  | ||||
| sub read_config { | ||||
|     foreach my $conf (@searchconfigs) { | ||||
| 	my $file = $conf->{"file"}; | ||||
|  | ||||
| 	next if ( ! -f "$file"); | ||||
|  | ||||
| 	if (defined($conf->{"test"})) { | ||||
| 	    `$conf->{"test"} $conf->{"file"} 2>/dev/null`; | ||||
| 	    next if ($?); | ||||
| 	} | ||||
|  | ||||
| 	my $exec = $conf->{"exec"}; | ||||
|  | ||||
| 	print STDERR "using config: '$file'\n"; | ||||
|  | ||||
| 	open(my $infile, '-|', "$exec $file") || die "Failed to run $exec $file"; | ||||
| 	my @x = <$infile>; | ||||
| 	close $infile; | ||||
| 	return @x; | ||||
|     } | ||||
|     die "No config file found"; | ||||
| } | ||||
|  | ||||
| my @config_file = read_config; | ||||
|  | ||||
| # Parse options | ||||
| my $localmodconfig = 0; | ||||
| my $localyesconfig = 0; | ||||
|  | ||||
| GetOptions("localmodconfig" => \$localmodconfig, | ||||
| 	   "localyesconfig" => \$localyesconfig); | ||||
|  | ||||
| # Get the build source and top level Kconfig file (passed in) | ||||
| my $ksource = ($ARGV[0] ? $ARGV[0] : '.'); | ||||
| my $kconfig = $ARGV[1]; | ||||
| my $lsmod_file = $ENV{'LSMOD'}; | ||||
|  | ||||
| my @makefiles = `find $ksource -name Makefile -or -name Kbuild 2>/dev/null`; | ||||
| chomp @makefiles; | ||||
|  | ||||
| my %depends; | ||||
| my %selects; | ||||
| my %prompts; | ||||
| my %objects; | ||||
| my %config2kfile; | ||||
| my $var; | ||||
| my $iflevel = 0; | ||||
| my @ifdeps; | ||||
|  | ||||
| # prevent recursion | ||||
| my %read_kconfigs; | ||||
|  | ||||
| sub read_kconfig { | ||||
|     my ($kconfig) = @_; | ||||
|  | ||||
|     my $state = "NONE"; | ||||
|     my $config; | ||||
|  | ||||
|     my $cont = 0; | ||||
|     my $line; | ||||
|  | ||||
|     my $source = "$ksource/$kconfig"; | ||||
|     my $last_source = ""; | ||||
|  | ||||
|     # Check for any environment variables used | ||||
|     while ($source =~ /\$\((\w+)\)/ && $last_source ne $source) { | ||||
| 	my $env = $1; | ||||
| 	$last_source = $source; | ||||
| 	$source =~ s/\$\($env\)/$ENV{$env}/; | ||||
|     } | ||||
|  | ||||
|     open(my $kinfile, '<', $source) || die "Can't open $kconfig"; | ||||
|     while (<$kinfile>) { | ||||
| 	chomp; | ||||
|  | ||||
| 	# Make sure that lines ending with \ continue | ||||
| 	if ($cont) { | ||||
| 	    $_ = $line . " " . $_; | ||||
| 	} | ||||
|  | ||||
| 	if (s/\\$//) { | ||||
| 	    $cont = 1; | ||||
| 	    $line = $_; | ||||
| 	    next; | ||||
| 	} | ||||
|  | ||||
| 	$cont = 0; | ||||
|  | ||||
| 	# collect any Kconfig sources | ||||
| 	if (/^source\s+"?([^"]+)/) { | ||||
| 	    my $kconfig = $1; | ||||
| 	    # prevent reading twice. | ||||
| 	    if (!defined($read_kconfigs{$kconfig})) { | ||||
| 		$read_kconfigs{$kconfig} = 1; | ||||
| 		read_kconfig($kconfig); | ||||
| 	    } | ||||
| 	    next; | ||||
| 	} | ||||
|  | ||||
| 	# configs found | ||||
| 	if (/^\s*(menu)?config\s+(\S+)\s*$/) { | ||||
| 	    $state = "NEW"; | ||||
| 	    $config = $2; | ||||
| 	    $config2kfile{"CONFIG_$config"} = $kconfig; | ||||
|  | ||||
| 	    # Add depends for 'if' nesting | ||||
| 	    for (my $i = 0; $i < $iflevel; $i++) { | ||||
| 		if ($i) { | ||||
| 		    $depends{$config} .= " " . $ifdeps[$i]; | ||||
| 		} else { | ||||
| 		    $depends{$config} = $ifdeps[$i]; | ||||
| 		} | ||||
| 		$state = "DEP"; | ||||
| 	    } | ||||
|  | ||||
| 	# collect the depends for the config | ||||
| 	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { | ||||
| 	    $state = "DEP"; | ||||
| 	    $depends{$config} = $1; | ||||
| 	} elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) { | ||||
| 	    $depends{$config} .= " " . $1; | ||||
| 	} elsif ($state eq "DEP" && /^\s*def(_(bool|tristate)|ault)\s+(\S.*)$/) { | ||||
| 	    my $dep = $3; | ||||
| 	    if ($dep !~ /^\s*(y|m|n)\s*$/) { | ||||
| 		$dep =~ s/.*\sif\s+//; | ||||
| 		$depends{$config} .= " " . $dep; | ||||
| 		dprint "Added default depends $dep to $config\n"; | ||||
| 	    } | ||||
|  | ||||
| 	# Get the configs that select this config | ||||
| 	} elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) { | ||||
| 	    my $conf = $1; | ||||
| 	    if (defined($selects{$conf})) { | ||||
| 		$selects{$conf} .= " " . $config; | ||||
| 	    } else { | ||||
| 		$selects{$conf} = $config; | ||||
| 	    } | ||||
|  | ||||
| 	# configs without prompts must be selected | ||||
| 	} elsif ($state ne "NONE" && /^\s*(tristate\s+\S|prompt\b)/) { | ||||
| 	    # note if the config has a prompt | ||||
| 	    $prompts{$config} = 1; | ||||
|  | ||||
| 	# Check for if statements | ||||
| 	} elsif (/^if\s+(.*\S)\s*$/) { | ||||
| 	    my $deps = $1; | ||||
| 	    # remove beginning and ending non text | ||||
| 	    $deps =~ s/^[^a-zA-Z0-9_]*//; | ||||
| 	    $deps =~ s/[^a-zA-Z0-9_]*$//; | ||||
|  | ||||
| 	    my @deps = split /[^a-zA-Z0-9_]+/, $deps; | ||||
|  | ||||
| 	    $ifdeps[$iflevel++] = join ':', @deps; | ||||
|  | ||||
| 	} elsif (/^endif/) { | ||||
|  | ||||
| 	    $iflevel-- if ($iflevel); | ||||
|  | ||||
| 	# stop on "help" and keywords that end a menu entry | ||||
| 	} elsif (/^\s*(---)?help(---)?\s*$/ || /^(comment|choice|menu)\b/) { | ||||
| 	    $state = "NONE"; | ||||
| 	} | ||||
|     } | ||||
|     close($kinfile); | ||||
| } | ||||
|  | ||||
| if ($kconfig) { | ||||
|     read_kconfig($kconfig); | ||||
| } | ||||
|  | ||||
| # Makefiles can use variables to define their dependencies | ||||
| sub convert_vars { | ||||
|     my ($line, %vars) = @_; | ||||
|  | ||||
|     my $process = ""; | ||||
|  | ||||
|     while ($line =~ s/^(.*?)(\$\((.*?)\))//) { | ||||
| 	my $start = $1; | ||||
| 	my $variable = $2; | ||||
| 	my $var = $3; | ||||
|  | ||||
| 	if (defined($vars{$var})) { | ||||
| 	    $process .= $start . $vars{$var}; | ||||
| 	} else { | ||||
| 	    $process .= $start . $variable; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|     $process .= $line; | ||||
|  | ||||
|     return $process; | ||||
| } | ||||
|  | ||||
| # Read all Makefiles to map the configs to the objects | ||||
| foreach my $makefile (@makefiles) { | ||||
|  | ||||
|     my $line = ""; | ||||
|     my %make_vars; | ||||
|  | ||||
|     open(my $infile, '<', $makefile) || die "Can't open $makefile"; | ||||
|     while (<$infile>) { | ||||
| 	# if this line ends with a backslash, continue | ||||
| 	chomp; | ||||
| 	if (/^(.*)\\$/) { | ||||
| 	    $line .= $1; | ||||
| 	    next; | ||||
| 	} | ||||
|  | ||||
| 	$line .= $_; | ||||
| 	$_ = $line; | ||||
| 	$line = ""; | ||||
|  | ||||
| 	my $objs; | ||||
|  | ||||
| 	# Convert variables in a line (could define configs) | ||||
| 	$_ = convert_vars($_, %make_vars); | ||||
|  | ||||
| 	# collect objects after obj-$(CONFIG_FOO_BAR) | ||||
| 	if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) { | ||||
| 	    $var = $1; | ||||
| 	    $objs = $2; | ||||
|  | ||||
| 	# check if variables are set | ||||
| 	} elsif (/^\s*(\S+)\s*[:]?=\s*(.*\S)/) { | ||||
| 	    $make_vars{$1} = $2; | ||||
| 	} | ||||
| 	if (defined($objs)) { | ||||
| 	    foreach my $obj (split /\s+/,$objs) { | ||||
| 		$obj =~ s/-/_/g; | ||||
| 		if ($obj =~ /(.*)\.o$/) { | ||||
| 		    # Objects may be enabled by more than one config. | ||||
| 		    # Store configs in an array. | ||||
| 		    my @arr; | ||||
|  | ||||
| 		    if (defined($objects{$1})) { | ||||
| 			@arr = @{$objects{$1}}; | ||||
| 		    } | ||||
|  | ||||
| 		    $arr[$#arr+1] = $var; | ||||
|  | ||||
| 		    # The objects have a hash mapping to a reference | ||||
| 		    # of an array of configs. | ||||
| 		    $objects{$1} = \@arr; | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|     close($infile); | ||||
| } | ||||
|  | ||||
| my %modules; | ||||
| my $linfile; | ||||
|  | ||||
| if (defined($lsmod_file)) { | ||||
|     if ( ! -f $lsmod_file) { | ||||
| 	if ( -f $ENV{'objtree'}."/".$lsmod_file) { | ||||
| 	    $lsmod_file = $ENV{'objtree'}."/".$lsmod_file; | ||||
| 	} else { | ||||
| 		die "$lsmod_file not found"; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|     my $otype = ( -x $lsmod_file) ? '-|' : '<'; | ||||
|     open($linfile, $otype, $lsmod_file); | ||||
|  | ||||
| } else { | ||||
|  | ||||
|     # see what modules are loaded on this system | ||||
|     my $lsmod; | ||||
|  | ||||
|     foreach my $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) { | ||||
| 	if ( -x "$dir/lsmod" ) { | ||||
| 	    $lsmod = "$dir/lsmod"; | ||||
| 	    last; | ||||
| 	} | ||||
|     } | ||||
|     if (!defined($lsmod)) { | ||||
| 	# try just the path | ||||
| 	$lsmod = "lsmod"; | ||||
|     } | ||||
|  | ||||
|     open($linfile, '-|', $lsmod) || die "Can not call lsmod with $lsmod"; | ||||
| } | ||||
|  | ||||
| while (<$linfile>) { | ||||
| 	next if (/^Module/);  # Skip the first line. | ||||
| 	if (/^(\S+)/) { | ||||
| 		$modules{$1} = 1; | ||||
| 	} | ||||
| } | ||||
| close ($linfile); | ||||
|  | ||||
| # add to the configs hash all configs that are needed to enable | ||||
| # a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o | ||||
| # where we know we need bar.o so we add FOO to the list. | ||||
| my %configs; | ||||
| foreach my $module (keys(%modules)) { | ||||
|     if (defined($objects{$module})) { | ||||
| 	my @arr = @{$objects{$module}}; | ||||
| 	foreach my $conf (@arr) { | ||||
| 	    $configs{$conf} = $module; | ||||
| 	    dprint "$conf added by direct ($module)\n"; | ||||
| 	    if ($debugprint) { | ||||
| 		my $c=$conf; | ||||
| 		$c =~ s/^CONFIG_//; | ||||
| 		if (defined($depends{$c})) { | ||||
| 		    dprint " deps = $depends{$c}\n"; | ||||
| 		} else { | ||||
| 		    dprint " no deps\n"; | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|     } else { | ||||
| 	# Most likely, someone has a custom (binary?) module loaded. | ||||
| 	print STDERR "$module config not found!!\n"; | ||||
|     } | ||||
| } | ||||
|  | ||||
| # Read the current config, and see what is enabled. We want to | ||||
| # ignore configs that we would not enable anyway. | ||||
|  | ||||
| my %orig_configs; | ||||
| my $valid = "A-Za-z_0-9"; | ||||
|  | ||||
| foreach my $line (@config_file) { | ||||
|     $_ = $line; | ||||
|  | ||||
|     if (/(CONFIG_[$valid]*)=(m|y)/) { | ||||
| 	$orig_configs{$1} = $2; | ||||
|     } | ||||
| } | ||||
|  | ||||
| my $repeat = 1; | ||||
|  | ||||
| my $depconfig; | ||||
|  | ||||
| # | ||||
| # Note, we do not care about operands (like: &&, ||, !) we want to add any | ||||
| # config that is in the depend list of another config. This script does | ||||
| # not enable configs that are not already enabled. If we come across a | ||||
| # config A that depends on !B, we can still add B to the list of depends | ||||
| # to keep on. If A was on in the original config, B would not have been | ||||
| # and B would not be turned on by this script. | ||||
| # | ||||
| sub parse_config_depends | ||||
| { | ||||
|     my ($p) = @_; | ||||
|  | ||||
|     while ($p =~ /[$valid]/) { | ||||
|  | ||||
| 	if ($p =~ /^[^$valid]*([$valid]+)/) { | ||||
| 	    my $conf = "CONFIG_" . $1; | ||||
|  | ||||
| 	    $p =~ s/^[^$valid]*[$valid]+//; | ||||
|  | ||||
| 	    # We only need to process if the depend config is a module | ||||
| 	    if (!defined($orig_configs{$conf}) || $orig_configs{$conf} eq "y") { | ||||
| 		next; | ||||
| 	    } | ||||
|  | ||||
| 	    if (!defined($configs{$conf})) { | ||||
| 		# We must make sure that this config has its | ||||
| 		# dependencies met. | ||||
| 		$repeat = 1; # do again | ||||
| 		dprint "$conf selected by depend $depconfig\n"; | ||||
| 		$configs{$conf} = 1; | ||||
| 	    } | ||||
| 	} else { | ||||
| 	    die "this should never happen"; | ||||
| 	} | ||||
|     } | ||||
| } | ||||
|  | ||||
| # Select is treated a bit differently than depends. We call this | ||||
| # when a config has no prompt and requires another config to be | ||||
| # selected. We use to just select all configs that selected this | ||||
| # config, but found that that can balloon into enabling hundreds | ||||
| # of configs that we do not care about. | ||||
| # | ||||
| # The idea is we look at all the configs that select it. If one | ||||
| # is already in our list of configs to enable, then there's nothing | ||||
| # else to do. If there isn't, we pick the first config that was | ||||
| # enabled in the original config and use that. | ||||
| sub parse_config_selects | ||||
| { | ||||
|     my ($config, $p) = @_; | ||||
|  | ||||
|     my $next_config; | ||||
|  | ||||
|     while ($p =~ /[$valid]/) { | ||||
|  | ||||
| 	if ($p =~ /^[^$valid]*([$valid]+)/) { | ||||
| 	    my $conf = "CONFIG_" . $1; | ||||
|  | ||||
| 	    $p =~ s/^[^$valid]*[$valid]+//; | ||||
|  | ||||
| 	    # Make sure that this config exists in the current .config file | ||||
| 	    if (!defined($orig_configs{$conf})) { | ||||
| 		dprint "$conf not set for $config select\n"; | ||||
| 		next; | ||||
| 	    } | ||||
|  | ||||
| 	    # Check if something other than a module selects this config | ||||
| 	    if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne "m") { | ||||
| 		dprint "$conf (non module) selects config, we are good\n"; | ||||
| 		# we are good with this | ||||
| 		return; | ||||
| 	    } | ||||
| 	    if (defined($configs{$conf})) { | ||||
| 		dprint "$conf selects $config so we are good\n"; | ||||
| 		# A set config selects this config, we are good | ||||
| 		return; | ||||
| 	    } | ||||
| 	    # Set this config to be selected | ||||
| 	    if (!defined($next_config)) { | ||||
| 		$next_config = $conf; | ||||
| 	    } | ||||
| 	} else { | ||||
| 	    die "this should never happen"; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|     # If no possible config selected this, then something happened. | ||||
|     if (!defined($next_config)) { | ||||
| 	print STDERR "WARNING: $config is required, but nothing in the\n"; | ||||
| 	print STDERR "  current config selects it.\n"; | ||||
| 	return; | ||||
|     } | ||||
|  | ||||
|     # If we are here, then we found no config that is set and | ||||
|     # selects this config. Repeat. | ||||
|     $repeat = 1; | ||||
|     # Make this config need to be selected | ||||
|     $configs{$next_config} = 1; | ||||
|     dprint "$next_config selected by select $config\n"; | ||||
| } | ||||
|  | ||||
| my %process_selects; | ||||
|  | ||||
| # loop through all configs, select their dependencies. | ||||
| sub loop_depend { | ||||
|     $repeat = 1; | ||||
|  | ||||
|     while ($repeat) { | ||||
| 	$repeat = 0; | ||||
|  | ||||
|       forloop: | ||||
| 	foreach my $config (keys %configs) { | ||||
|  | ||||
| 	    # If this config is not a module, we do not need to process it | ||||
| 	    if (defined($orig_configs{$config}) && $orig_configs{$config} ne "m") { | ||||
| 		next forloop; | ||||
| 	    } | ||||
|  | ||||
| 	    $config =~ s/^CONFIG_//; | ||||
| 	    $depconfig = $config; | ||||
|  | ||||
| 	    if (defined($depends{$config})) { | ||||
| 		# This config has dependencies. Make sure they are also included | ||||
| 		parse_config_depends $depends{$config}; | ||||
| 	    } | ||||
|  | ||||
| 	    # If the config has no prompt, then we need to check if a config | ||||
| 	    # that is enabled selected it. Or if we need to enable one. | ||||
| 	    if (!defined($prompts{$config}) && defined($selects{$config})) { | ||||
| 		$process_selects{$config} = 1; | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
| } | ||||
|  | ||||
| sub loop_select { | ||||
|  | ||||
|     foreach my $config (keys %process_selects) { | ||||
| 	$config =~ s/^CONFIG_//; | ||||
|  | ||||
| 	dprint "Process select $config\n"; | ||||
|  | ||||
| 	# config has no prompt and must be selected. | ||||
| 	parse_config_selects $config, $selects{$config}; | ||||
|     } | ||||
| } | ||||
|  | ||||
| while ($repeat) { | ||||
|     # Get the first set of configs and their dependencies. | ||||
|     loop_depend; | ||||
|  | ||||
|     $repeat = 0; | ||||
|  | ||||
|     # Now we need to see if we have to check selects; | ||||
|     loop_select; | ||||
| } | ||||
|  | ||||
| my %setconfigs; | ||||
| my @preserved_kconfigs; | ||||
| if (defined($ENV{'LMC_KEEP'})) { | ||||
| 	@preserved_kconfigs = split(/:/,$ENV{LMC_KEEP}); | ||||
| } | ||||
|  | ||||
| sub in_preserved_kconfigs { | ||||
|     my $kconfig = $config2kfile{$_[0]}; | ||||
|     if (!defined($kconfig)) { | ||||
|         return 0; | ||||
|     } | ||||
|     foreach my $excl (@preserved_kconfigs) { | ||||
|         if($kconfig =~ /^$excl/) { | ||||
|             return 1; | ||||
|         } | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| # Finally, read the .config file and turn off any module enabled that | ||||
| # we could not find a reason to keep enabled. | ||||
| foreach my $line (@config_file) { | ||||
|     $_ = $line; | ||||
|  | ||||
|     if (/CONFIG_IKCONFIG/) { | ||||
| 	if (/# CONFIG_IKCONFIG is not set/) { | ||||
| 	    # enable IKCONFIG at least as a module | ||||
| 	    print "CONFIG_IKCONFIG=m\n"; | ||||
| 	    # don't ask about PROC | ||||
| 	    print "# CONFIG_IKCONFIG_PROC is not set\n"; | ||||
| 	} else { | ||||
| 	    print; | ||||
| 	} | ||||
| 	next; | ||||
|     } | ||||
|  | ||||
|     if (/CONFIG_MODULE_SIG_KEY="(.+)"/) { | ||||
|         my $orig_cert = $1; | ||||
|         my $default_cert = "certs/signing_key.pem"; | ||||
|  | ||||
|         # Check that the logic in this script still matches the one in Kconfig | ||||
|         if (!defined($depends{"MODULE_SIG_KEY"}) || | ||||
|             $depends{"MODULE_SIG_KEY"} !~ /"\Q$default_cert\E"/) { | ||||
|             print STDERR "WARNING: MODULE_SIG_KEY assertion failure, ", | ||||
|                 "update needed to ", __FILE__, " line ", __LINE__, "\n"; | ||||
|             print; | ||||
|         } elsif ($orig_cert ne $default_cert && ! -f $orig_cert) { | ||||
|             print STDERR "Module signature verification enabled but ", | ||||
|                 "module signing key \"$orig_cert\" not found. Resetting ", | ||||
|                 "signing key to default value.\n"; | ||||
|             print "CONFIG_MODULE_SIG_KEY=\"$default_cert\"\n"; | ||||
|         } else { | ||||
|             print; | ||||
|         } | ||||
|         next; | ||||
|     } | ||||
|  | ||||
|     if (/CONFIG_SYSTEM_TRUSTED_KEYS="(.+)"/) { | ||||
|         my $orig_keys = $1; | ||||
|  | ||||
|         if (! -f $orig_keys) { | ||||
|             print STDERR "System keyring enabled but keys \"$orig_keys\" ", | ||||
|                 "not found. Resetting keys to default value.\n"; | ||||
|             print "CONFIG_SYSTEM_TRUSTED_KEYS=\"\"\n"; | ||||
|         } else { | ||||
|             print; | ||||
|         } | ||||
|         next; | ||||
|     } | ||||
|  | ||||
|     if (/^(CONFIG.*)=(m|y)/) { | ||||
|         if (in_preserved_kconfigs($1)) { | ||||
|             dprint "Preserve config $1"; | ||||
|             print; | ||||
|             next; | ||||
|         } | ||||
| 	if (defined($configs{$1})) { | ||||
| 	    if ($localyesconfig) { | ||||
| 	        $setconfigs{$1} = 'y'; | ||||
| 		print "$1=y\n"; | ||||
| 		next; | ||||
| 	    } else { | ||||
| 	        $setconfigs{$1} = $2; | ||||
| 	    } | ||||
| 	} elsif ($2 eq "m") { | ||||
| 	    print "# $1 is not set\n"; | ||||
| 	    next; | ||||
| 	} | ||||
|     } | ||||
|     print; | ||||
| } | ||||
|  | ||||
| # Integrity check, make sure all modules that we want enabled do | ||||
| # indeed have their configs set. | ||||
| loop: | ||||
| foreach my $module (keys(%modules)) { | ||||
|     if (defined($objects{$module})) { | ||||
| 	my @arr = @{$objects{$module}}; | ||||
| 	foreach my $conf (@arr) { | ||||
| 	    if (defined($setconfigs{$conf})) { | ||||
| 		next loop; | ||||
| 	    } | ||||
| 	} | ||||
| 	print STDERR "module $module did not have configs"; | ||||
| 	foreach my $conf (@arr) { | ||||
| 	    print STDERR " " , $conf; | ||||
| 	} | ||||
| 	print STDERR "\n"; | ||||
|     } | ||||
| } | ||||
| @@ -1,15 +1,13 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0 | ||||
| /* | ||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||
|  * Released under the terms of the GNU GPL v2.0. | ||||
|  */ | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <ctype.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <regex.h> | ||||
| #ifndef __MINGW32__ | ||||
| #include <sys/utsname.h> | ||||
| #endif | ||||
|  | ||||
| #include "lkc.h" | ||||
|  | ||||
| @@ -17,58 +15,28 @@ struct symbol symbol_yes = { | ||||
| 	.name = "y", | ||||
| 	.curr = { "y", yes }, | ||||
| 	.flags = SYMBOL_CONST|SYMBOL_VALID, | ||||
| }, symbol_mod = { | ||||
| }; | ||||
|  | ||||
| struct symbol symbol_mod = { | ||||
| 	.name = "m", | ||||
| 	.curr = { "m", mod }, | ||||
| 	.flags = SYMBOL_CONST|SYMBOL_VALID, | ||||
| }, symbol_no = { | ||||
| }; | ||||
|  | ||||
| struct symbol symbol_no = { | ||||
| 	.name = "n", | ||||
| 	.curr = { "n", no }, | ||||
| 	.flags = SYMBOL_CONST|SYMBOL_VALID, | ||||
| }, symbol_empty = { | ||||
| }; | ||||
|  | ||||
| static struct symbol symbol_empty = { | ||||
| 	.name = "", | ||||
| 	.curr = { "", no }, | ||||
| 	.flags = SYMBOL_VALID, | ||||
| }; | ||||
|  | ||||
| struct symbol *sym_defconfig_list; | ||||
| struct symbol *modules_sym; | ||||
| 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; | ||||
| #ifndef __MINGW32__ | ||||
| 	struct utsname uts; | ||||
| #endif | ||||
| 	static bool inited = false; | ||||
|  | ||||
| 	if (inited) | ||||
| 		return; | ||||
| 	inited = true; | ||||
|  | ||||
| #ifndef __MINGW32__ | ||||
| 	uname(&uts); | ||||
| #endif | ||||
|  | ||||
| 	sym = sym_lookup("UNAME_RELEASE", 0); | ||||
| 	sym->type = S_STRING; | ||||
| 	sym->flags |= SYMBOL_AUTO; | ||||
| #ifndef __MINGW32__ | ||||
| 	sym_add_default(sym, uts.release); | ||||
| #else | ||||
| 	sym_add_default(sym, "mingw-unknown"); | ||||
| #endif | ||||
| } | ||||
| static tristate modules_val; | ||||
|  | ||||
| enum symbol_type sym_get_type(struct symbol *sym) | ||||
| { | ||||
| @@ -87,7 +55,7 @@ const char *sym_type_name(enum symbol_type type) | ||||
| { | ||||
| 	switch (type) { | ||||
| 	case S_BOOLEAN: | ||||
| 		return "boolean"; | ||||
| 		return "bool"; | ||||
| 	case S_TRISTATE: | ||||
| 		return "tristate"; | ||||
| 	case S_INT: | ||||
| @@ -98,8 +66,6 @@ const char *sym_type_name(enum symbol_type type) | ||||
| 		return "string"; | ||||
| 	case S_UNKNOWN: | ||||
| 		return "unknown"; | ||||
| 	case S_OTHER: | ||||
| 		break; | ||||
| 	} | ||||
| 	return "???"; | ||||
| } | ||||
| @@ -113,16 +79,7 @@ struct property *sym_get_choice_prop(struct symbol *sym) | ||||
| 	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; | ||||
| } | ||||
|  | ||||
| struct property *sym_get_default_prop(struct symbol *sym) | ||||
| static struct property *sym_get_default_prop(struct symbol *sym) | ||||
| { | ||||
| 	struct property *prop; | ||||
|  | ||||
| @@ -134,7 +91,7 @@ struct property *sym_get_default_prop(struct symbol *sym) | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| static struct property *sym_get_range_prop(struct symbol *sym) | ||||
| struct property *sym_get_range_prop(struct symbol *sym) | ||||
| { | ||||
| 	struct property *prop; | ||||
|  | ||||
| @@ -193,18 +150,52 @@ static void sym_validate_range(struct symbol *sym) | ||||
| 		sprintf(str, "%lld", val2); | ||||
| 	else | ||||
| 		sprintf(str, "0x%llx", val2); | ||||
| 	sym->curr.val = strdup(str); | ||||
| 	sym->curr.val = xstrdup(str); | ||||
| } | ||||
|  | ||||
| static void sym_set_changed(struct symbol *sym) | ||||
| { | ||||
| 	struct property *prop; | ||||
|  | ||||
| 	sym->flags |= SYMBOL_CHANGED; | ||||
| 	for (prop = sym->prop; prop; prop = prop->next) { | ||||
| 		if (prop->menu) | ||||
| 			prop->menu->flags |= MENU_CHANGED; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void sym_set_all_changed(void) | ||||
| { | ||||
| 	struct symbol *sym; | ||||
| 	int i; | ||||
|  | ||||
| 	for_all_symbols(i, sym) | ||||
| 		sym_set_changed(sym); | ||||
| } | ||||
|  | ||||
| static void sym_calc_visibility(struct symbol *sym) | ||||
| { | ||||
| 	struct property *prop; | ||||
| 	struct symbol *choice_sym = NULL; | ||||
| 	tristate tri; | ||||
|  | ||||
| 	/* any prompt visible? */ | ||||
| 	tri = no; | ||||
|  | ||||
| 	if (sym_is_choice_value(sym)) | ||||
| 		choice_sym = prop_get_symbol(sym_get_choice_prop(sym)); | ||||
|  | ||||
| 	for_all_prompts(sym, prop) { | ||||
| 		prop->visible.tri = expr_calc_value(prop->visible.expr); | ||||
| 		/* | ||||
| 		 * Tristate choice_values with visibility 'mod' are | ||||
| 		 * not visible if the corresponding choice's value is | ||||
| 		 * 'yes'. | ||||
| 		 */ | ||||
| 		if (choice_sym && sym->type == S_TRISTATE && | ||||
| 		    prop->visible.tri == mod && choice_sym->curr.tri == yes) | ||||
| 			prop->visible.tri = no; | ||||
|  | ||||
| 		tri = EXPR_OR(tri, prop->visible.tri); | ||||
| 	} | ||||
| 	if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) | ||||
| @@ -219,7 +210,7 @@ static void sym_calc_visibility(struct symbol *sym) | ||||
| 	tri = yes; | ||||
| 	if (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; | ||||
| 	if (sym->dir_dep.tri != tri) { | ||||
| 		sym->dir_dep.tri = tri; | ||||
| @@ -234,6 +225,15 @@ static void sym_calc_visibility(struct symbol *sym) | ||||
| 		sym->rev_dep.tri = tri; | ||||
| 		sym_set_changed(sym); | ||||
| 	} | ||||
| 	tri = no; | ||||
| 	if (sym->implied.expr) | ||||
| 		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); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
| @@ -300,6 +300,28 @@ static struct symbol *sym_calc_choice(struct symbol *sym) | ||||
| 	return def_sym; | ||||
| } | ||||
|  | ||||
| static void sym_warn_unmet_dep(struct symbol *sym) | ||||
| { | ||||
| 	struct gstr gs = str_new(); | ||||
|  | ||||
| 	str_printf(&gs, | ||||
| 		   "\nWARNING: unmet direct dependencies detected for %s\n", | ||||
| 		   sym->name); | ||||
| 	str_printf(&gs, | ||||
| 		   "  Depends on [%c]: ", | ||||
| 		   sym->dir_dep.tri == mod ? 'm' : 'n'); | ||||
| 	expr_gstr_print(sym->dir_dep.expr, &gs); | ||||
| 	str_printf(&gs, "\n"); | ||||
|  | ||||
| 	expr_gstr_print_revdep(sym->rev_dep.expr, &gs, yes, | ||||
| 			       "  Selected by [y]:\n"); | ||||
| 	expr_gstr_print_revdep(sym->rev_dep.expr, &gs, mod, | ||||
| 			       "  Selected by [m]:\n"); | ||||
|  | ||||
| 	fputs(str_get(&gs), stderr); | ||||
| 	kconfig_warnings++; | ||||
| } | ||||
|  | ||||
| void sym_calc_value(struct symbol *sym) | ||||
| { | ||||
| 	struct symbol_value newval, oldval; | ||||
| @@ -338,11 +360,13 @@ void sym_calc_value(struct symbol *sym) | ||||
| 		sym->curr.tri = no; | ||||
| 		return; | ||||
| 	} | ||||
| 	if (!sym_is_choice_value(sym)) | ||||
| 		sym->flags &= ~SYMBOL_WRITE; | ||||
| 	sym->flags &= ~SYMBOL_WRITE; | ||||
|  | ||||
| 	sym_calc_visibility(sym); | ||||
|  | ||||
| 	if (sym->visible != no) | ||||
| 		sym->flags |= SYMBOL_WRITE; | ||||
|  | ||||
| 	/* set default if recursively called */ | ||||
| 	sym->curr = newval; | ||||
|  | ||||
| @@ -357,7 +381,6 @@ void sym_calc_value(struct symbol *sym) | ||||
| 				/* if the symbol is visible use the user value | ||||
| 				 * if available, otherwise try the default value | ||||
| 				 */ | ||||
| 				sym->flags |= SYMBOL_WRITE; | ||||
| 				if (sym_has_value(sym)) { | ||||
| 					newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, | ||||
| 							      sym->visible); | ||||
| @@ -369,25 +392,21 @@ void sym_calc_value(struct symbol *sym) | ||||
| 			if (!sym_is_choice(sym)) { | ||||
| 				prop = sym_get_default_prop(sym); | ||||
| 				if (prop) { | ||||
| 					sym->flags |= SYMBOL_WRITE; | ||||
| 					newval.tri = EXPR_AND(expr_calc_value(prop->expr), | ||||
| 							      prop->visible.tri); | ||||
| 					if (newval.tri != no) | ||||
| 						sym->flags |= SYMBOL_WRITE; | ||||
| 				} | ||||
| 				if (sym->implied.tri != no) { | ||||
| 					sym->flags |= SYMBOL_WRITE; | ||||
| 					newval.tri = EXPR_OR(newval.tri, sym->implied.tri); | ||||
| 					newval.tri = EXPR_AND(newval.tri, | ||||
| 							      sym->dir_dep.tri); | ||||
| 				} | ||||
| 			} | ||||
| 		calc_newval: | ||||
| 			if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) { | ||||
| 				struct expr *e; | ||||
| 				e = expr_simplify_unmet_dep(sym->rev_dep.expr, | ||||
| 				    sym->dir_dep.expr); | ||||
| 				fprintf(stderr, "warning: ("); | ||||
| 				expr_fprint(e, stderr); | ||||
| 				fprintf(stderr, ") selects %s which has unmet direct dependencies (", | ||||
| 					sym->name); | ||||
| 				expr_fprint(sym->dir_dep.expr, stderr); | ||||
| 				fprintf(stderr, ")\n"); | ||||
| 				kconfig_warnings++; | ||||
| 				expr_free(e); | ||||
| 			} | ||||
| 			if (sym->dir_dep.tri < sym->rev_dep.tri) | ||||
| 				sym_warn_unmet_dep(sym); | ||||
| 			newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); | ||||
| 		} | ||||
| 		if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) | ||||
| @@ -396,12 +415,9 @@ void sym_calc_value(struct symbol *sym) | ||||
| 	case S_STRING: | ||||
| 	case S_HEX: | ||||
| 	case S_INT: | ||||
| 		if (sym->visible != no) { | ||||
| 			sym->flags |= SYMBOL_WRITE; | ||||
| 			if (sym_has_value(sym)) { | ||||
| 				newval.val = sym->def[S_DEF_USER].val; | ||||
| 				break; | ||||
| 			} | ||||
| 		if (sym->visible != no && sym_has_value(sym)) { | ||||
| 			newval.val = sym->def[S_DEF_USER].val; | ||||
| 			break; | ||||
| 		} | ||||
| 		prop = sym_get_default_prop(sym); | ||||
| 		if (prop) { | ||||
| @@ -443,7 +459,7 @@ void sym_calc_value(struct symbol *sym) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (sym->flags & SYMBOL_AUTO) | ||||
| 	if (sym->flags & SYMBOL_NO_WRITE) | ||||
| 		sym->flags &= ~SYMBOL_WRITE; | ||||
|  | ||||
| 	if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) | ||||
| @@ -457,29 +473,8 @@ void sym_clear_all_valid(void) | ||||
|  | ||||
| 	for_all_symbols(i, sym) | ||||
| 		sym->flags &= ~SYMBOL_VALID; | ||||
| 	sym_add_change_count(1); | ||||
| 	if (modules_sym) | ||||
| 		sym_calc_value(modules_sym); | ||||
| } | ||||
|  | ||||
| void sym_set_changed(struct symbol *sym) | ||||
| { | ||||
| 	struct property *prop; | ||||
|  | ||||
| 	sym->flags |= SYMBOL_CHANGED; | ||||
| 	for (prop = sym->prop; prop; prop = prop->next) { | ||||
| 		if (prop->menu) | ||||
| 			prop->menu->flags |= MENU_CHANGED; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void sym_set_all_changed(void) | ||||
| { | ||||
| 	struct symbol *sym; | ||||
| 	int i; | ||||
|  | ||||
| 	for_all_symbols(i, sym) | ||||
| 		sym_set_changed(sym); | ||||
| 	conf_set_changed(true); | ||||
| 	sym_calc_value(modules_sym); | ||||
| } | ||||
|  | ||||
| bool sym_tristate_within_range(struct symbol *sym, tristate val) | ||||
| @@ -748,6 +743,10 @@ const char *sym_get_string_default(struct symbol *sym) | ||||
| 	if (sym->type == S_BOOLEAN && val == mod) | ||||
| 		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) { | ||||
| 	case S_BOOLEAN: | ||||
| 	case S_TRISTATE: | ||||
| @@ -758,10 +757,9 @@ const char *sym_get_string_default(struct symbol *sym) | ||||
| 		} | ||||
| 	case S_INT: | ||||
| 	case S_HEX: | ||||
| 		return str; | ||||
| 		return "0"; | ||||
| 	case S_STRING: | ||||
| 		return str; | ||||
| 	case S_OTHER: | ||||
| 	case S_UNKNOWN: | ||||
| 		break; | ||||
| 	} | ||||
| @@ -792,7 +790,7 @@ const char *sym_get_string_value(struct symbol *sym) | ||||
| 	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; | ||||
| } | ||||
| @@ -829,7 +827,7 @@ struct symbol *sym_lookup(const char *name, int flags) | ||||
| 				   : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) | ||||
| 				return symbol; | ||||
| 		} | ||||
| 		new_name = strdup(name); | ||||
| 		new_name = xstrdup(name); | ||||
| 	} else { | ||||
| 		new_name = NULL; | ||||
| 		hash = 0; | ||||
| @@ -839,7 +837,7 @@ struct symbol *sym_lookup(const char *name, int flags) | ||||
| 	memset(symbol, 0, sizeof(*symbol)); | ||||
| 	symbol->name = new_name; | ||||
| 	symbol->type = S_UNKNOWN; | ||||
| 	symbol->flags |= flags; | ||||
| 	symbol->flags = flags; | ||||
|  | ||||
| 	symbol->next = symbol_hash[hash]; | ||||
| 	symbol_hash[hash] = symbol; | ||||
| @@ -874,55 +872,6 @@ struct symbol *sym_find(const char *name) | ||||
| 	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 *p; | ||||
| @@ -1039,7 +988,7 @@ struct symbol **sym_re_search(const char *pattern) | ||||
| 	} | ||||
| 	if (sym_match_arr) { | ||||
| 		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) | ||||
| 			goto sym_re_search_free; | ||||
| 		for (i = 0; i < cnt; i++) | ||||
| @@ -1064,7 +1013,7 @@ static struct dep_stack { | ||||
| 	struct dep_stack *prev, *next; | ||||
| 	struct symbol *sym; | ||||
| 	struct property *prop; | ||||
| 	struct expr *expr; | ||||
| 	struct expr **expr; | ||||
| } *check_top; | ||||
|  | ||||
| static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym) | ||||
| @@ -1128,18 +1077,8 @@ static void sym_check_print_recursive(struct symbol *last_sym) | ||||
| 		if (stack->sym == last_sym) | ||||
| 			fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", | ||||
| 				prop->file->name, prop->lineno); | ||||
| 		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)) { | ||||
|  | ||||
| 		if (sym_is_choice(sym)) { | ||||
| 			fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", | ||||
| 				menu->file->name, menu->lineno, | ||||
| 				sym->name ? sym->name : "<choice>", | ||||
| @@ -1149,14 +1088,41 @@ static void sym_check_print_recursive(struct symbol *last_sym) | ||||
| 				menu->file->name, menu->lineno, | ||||
| 				sym->name ? 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", | ||||
| 				prop->file->name, prop->lineno, | ||||
| 				sym->name ? 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) | ||||
| 		dep_stack_remove(); | ||||
| } | ||||
| @@ -1177,6 +1143,10 @@ static struct symbol *sym_check_expr_deps(struct expr *e) | ||||
| 	case E_NOT: | ||||
| 		return sym_check_expr_deps(e->left.expr); | ||||
| 	case E_EQUAL: | ||||
| 	case E_GEQ: | ||||
| 	case E_GTH: | ||||
| 	case E_LEQ: | ||||
| 	case E_LTH: | ||||
| 	case E_UNEQUAL: | ||||
| 		sym = sym_check_deps(e->left.sym); | ||||
| 		if (sym) | ||||
| @@ -1187,7 +1157,7 @@ static struct symbol *sym_check_expr_deps(struct expr *e) | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
| 	printf("Oops! How to check %d?\n", e->type); | ||||
| 	fprintf(stderr, "Oops! How to check %d?\n", e->type); | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| @@ -1200,12 +1170,26 @@ static struct symbol *sym_check_sym_deps(struct symbol *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); | ||||
| 	if (sym2) | ||||
| 		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) { | ||||
| 		if (prop->type == P_CHOICE || prop->type == P_SELECT) | ||||
| 		if (prop->type == P_CHOICE || prop->type == P_SELECT || | ||||
| 		    prop->type == P_IMPLY) | ||||
| 			continue; | ||||
| 		stack.prop = prop; | ||||
| 		sym2 = sym_check_expr_deps(prop->visible.expr); | ||||
| @@ -1213,7 +1197,7 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym) | ||||
| 			break; | ||||
| 		if (prop->type != P_DEFAULT || sym_is_choice(sym)) | ||||
| 			continue; | ||||
| 		stack.expr = prop->expr; | ||||
| 		stack.expr = &prop->expr; | ||||
| 		sym2 = sym_check_expr_deps(prop->expr); | ||||
| 		if (sym2) | ||||
| 			break; | ||||
| @@ -1291,34 +1275,9 @@ struct symbol *sym_check_deps(struct symbol *sym) | ||||
| 		sym->flags &= ~SYMBOL_CHECK; | ||||
| 	} | ||||
|  | ||||
| 	if (sym2 && sym2 == sym) | ||||
| 		sym2 = NULL; | ||||
|  | ||||
| 	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) | ||||
| { | ||||
| 	if (prop->expr && (prop->expr->type == E_SYMBOL || | ||||
| @@ -1332,8 +1291,6 @@ const char *prop_get_type_name(enum prop_type type) | ||||
| 	switch (type) { | ||||
| 	case P_PROMPT: | ||||
| 		return "prompt"; | ||||
| 	case P_ENV: | ||||
| 		return "env"; | ||||
| 	case P_COMMENT: | ||||
| 		return "comment"; | ||||
| 	case P_MENU: | ||||
| @@ -1344,6 +1301,8 @@ const char *prop_get_type_name(enum prop_type type) | ||||
| 		return "choice"; | ||||
| 	case P_SELECT: | ||||
| 		return "select"; | ||||
| 	case P_IMPLY: | ||||
| 		return "imply"; | ||||
| 	case P_RANGE: | ||||
| 		return "range"; | ||||
| 	case P_SYMBOL: | ||||
| @@ -1353,32 +1312,3 @@ const char *prop_get_type_name(enum prop_type type) | ||||
| 	} | ||||
| 	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 Sam Ravnborg <sam@ravnborg.org> | ||||
|  * | ||||
|  * Released under the terms of the GNU GPL v2.0. | ||||
|  */ | ||||
|  | ||||
| #include <stdarg.h> | ||||
| @@ -14,73 +13,21 @@ | ||||
| struct file *file_lookup(const char *name) | ||||
| { | ||||
| 	struct file *file; | ||||
| 	const char *file_name = sym_expand_string_value(name); | ||||
|  | ||||
| 	for (file = file_list; file; file = file->next) { | ||||
| 		if (!strcmp(name, file->name)) { | ||||
| 			free((void *)file_name); | ||||
| 			return file; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	file = xmalloc(sizeof(*file)); | ||||
| 	memset(file, 0, sizeof(*file)); | ||||
| 	file->name = file_name; | ||||
| 	file->name = xstrdup(name); | ||||
| 	file->next = file_list; | ||||
| 	file_list = 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; | ||||
| 	int i; | ||||
|  | ||||
| 	if (!name) | ||||
| 		name = ".kconfig.d"; | ||||
| 	char *config_tmp_name = strdup("..config.tmp.XXXXXX"); | ||||
| 	if ((i = mkstemp(config_tmp_name)) == -1) | ||||
| 		return 1; | ||||
| 	out = fdopen(i, "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, name); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Allocate initial growable string */ | ||||
| struct gstr str_new(void) | ||||
| { | ||||
| @@ -92,16 +39,6 @@ struct gstr str_new(void) | ||||
| 	return gs; | ||||
| } | ||||
|  | ||||
| /* Allocate and assign growable string */ | ||||
| struct gstr str_assign(const char *s) | ||||
| { | ||||
| 	struct gstr gs; | ||||
| 	gs.s = strdup(s); | ||||
| 	gs.len = strlen(s) + 1; | ||||
| 	gs.max_width = 0; | ||||
| 	return gs; | ||||
| } | ||||
|  | ||||
| /* Free storage for growable string */ | ||||
| void str_free(struct gstr *gs) | ||||
| { | ||||
| @@ -118,7 +55,7 @@ void str_append(struct gstr *gs, const char *s) | ||||
| 	if (s) { | ||||
| 		l = strlen(gs->s) + strlen(s) + 1; | ||||
| 		if (l > gs->len) { | ||||
| 			gs->s   = realloc(gs->s, l); | ||||
| 			gs->s = xrealloc(gs->s, l); | ||||
| 			gs->len = l; | ||||
| 		} | ||||
| 		strcat(gs->s, s); | ||||
| @@ -159,3 +96,34 @@ void *xcalloc(size_t nmemb, size_t size) | ||||
| 	fprintf(stderr, "Out of memory.\n"); | ||||
| 	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,48 +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; | ||||
|  | ||||
| static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); | ||||
|  | ||||
| %% | ||||
| 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 | ||||
| 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 | ||||
| %% | ||||
| @@ -1,288 +0,0 @@ | ||||
| /* ANSI-C code produced by gperf version 3.0.4 */ | ||||
| /* Command-line: gperf -t --output-file scripts/kconfig/zconf.hash.c_shipped -a -C -E -g -k '1,3,$' -p -t scripts/kconfig/zconf.gperf  */ | ||||
|  | ||||
| #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 | ||||
|  | ||||
| #line 10 "scripts/kconfig/zconf.gperf" | ||||
| struct kconf_id; | ||||
|  | ||||
| static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); | ||||
| /* maximum key range = 71, 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 const unsigned char asso_values[] = | ||||
|     { | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73,  5, 25, 25, | ||||
|        0,  0,  0,  5,  0,  0, 73, 73,  5,  0, | ||||
|       10,  5, 45, 73, 20, 20,  0, 15, 15, 73, | ||||
|       20,  5, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73, 73, 73, 73, 73, | ||||
|       73, 73, 73, 73, 73, 73 | ||||
|     }; | ||||
|   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 + asso_values[(unsigned char)str[len - 1]]; | ||||
| } | ||||
|  | ||||
| struct kconf_id_strings_t | ||||
|   { | ||||
|     char kconf_id_strings_str2[sizeof("if")]; | ||||
|     char kconf_id_strings_str3[sizeof("int")]; | ||||
|     char kconf_id_strings_str5[sizeof("endif")]; | ||||
|     char kconf_id_strings_str7[sizeof("default")]; | ||||
|     char kconf_id_strings_str8[sizeof("tristate")]; | ||||
|     char kconf_id_strings_str9[sizeof("endchoice")]; | ||||
|     char kconf_id_strings_str12[sizeof("def_tristate")]; | ||||
|     char kconf_id_strings_str13[sizeof("def_bool")]; | ||||
|     char kconf_id_strings_str14[sizeof("defconfig_list")]; | ||||
|     char kconf_id_strings_str17[sizeof("on")]; | ||||
|     char kconf_id_strings_str18[sizeof("optional")]; | ||||
|     char kconf_id_strings_str21[sizeof("option")]; | ||||
|     char kconf_id_strings_str22[sizeof("endmenu")]; | ||||
|     char kconf_id_strings_str23[sizeof("mainmenu")]; | ||||
|     char kconf_id_strings_str25[sizeof("menuconfig")]; | ||||
|     char kconf_id_strings_str27[sizeof("modules")]; | ||||
|     char kconf_id_strings_str28[sizeof("allnoconfig_y")]; | ||||
|     char kconf_id_strings_str29[sizeof("menu")]; | ||||
|     char kconf_id_strings_str31[sizeof("select")]; | ||||
|     char kconf_id_strings_str32[sizeof("comment")]; | ||||
|     char kconf_id_strings_str33[sizeof("env")]; | ||||
|     char kconf_id_strings_str35[sizeof("range")]; | ||||
|     char kconf_id_strings_str36[sizeof("choice")]; | ||||
|     char kconf_id_strings_str39[sizeof("bool")]; | ||||
|     char kconf_id_strings_str41[sizeof("source")]; | ||||
|     char kconf_id_strings_str42[sizeof("visible")]; | ||||
|     char kconf_id_strings_str43[sizeof("hex")]; | ||||
|     char kconf_id_strings_str46[sizeof("config")]; | ||||
|     char kconf_id_strings_str47[sizeof("boolean")]; | ||||
|     char kconf_id_strings_str51[sizeof("string")]; | ||||
|     char kconf_id_strings_str54[sizeof("help")]; | ||||
|     char kconf_id_strings_str56[sizeof("prompt")]; | ||||
|     char kconf_id_strings_str72[sizeof("depends")]; | ||||
|   }; | ||||
| static const struct kconf_id_strings_t kconf_id_strings_contents = | ||||
|   { | ||||
|     "if", | ||||
|     "int", | ||||
|     "endif", | ||||
|     "default", | ||||
|     "tristate", | ||||
|     "endchoice", | ||||
|     "def_tristate", | ||||
|     "def_bool", | ||||
|     "defconfig_list", | ||||
|     "on", | ||||
|     "optional", | ||||
|     "option", | ||||
|     "endmenu", | ||||
|     "mainmenu", | ||||
|     "menuconfig", | ||||
|     "modules", | ||||
|     "allnoconfig_y", | ||||
|     "menu", | ||||
|     "select", | ||||
|     "comment", | ||||
|     "env", | ||||
|     "range", | ||||
|     "choice", | ||||
|     "bool", | ||||
|     "source", | ||||
|     "visible", | ||||
|     "hex", | ||||
|     "config", | ||||
|     "boolean", | ||||
|     "string", | ||||
|     "help", | ||||
|     "prompt", | ||||
|     "depends" | ||||
|   }; | ||||
| #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 | ||||
| const struct kconf_id * | ||||
| kconf_id_lookup (register const char *str, register unsigned int len) | ||||
| { | ||||
|   enum | ||||
|     { | ||||
|       TOTAL_KEYWORDS = 33, | ||||
|       MIN_WORD_LENGTH = 2, | ||||
|       MAX_WORD_LENGTH = 14, | ||||
|       MIN_HASH_VALUE = 2, | ||||
|       MAX_HASH_VALUE = 72 | ||||
|     }; | ||||
|  | ||||
|   static const struct kconf_id wordlist[] = | ||||
|     { | ||||
|       {-1}, {-1}, | ||||
| #line 25 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2,		T_IF,		TF_COMMAND|TF_PARAM}, | ||||
| #line 36 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3,		T_TYPE,		TF_COMMAND, S_INT}, | ||||
|       {-1}, | ||||
| #line 26 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5,		T_ENDIF,	TF_COMMAND}, | ||||
|       {-1}, | ||||
| #line 29 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7,	T_DEFAULT,	TF_COMMAND, S_UNKNOWN}, | ||||
| #line 31 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8,	T_TYPE,		TF_COMMAND, S_TRISTATE}, | ||||
| #line 20 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9,	T_ENDCHOICE,	TF_COMMAND}, | ||||
|       {-1}, {-1}, | ||||
| #line 32 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12,	T_DEFAULT,	TF_COMMAND, S_TRISTATE}, | ||||
| #line 35 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13,	T_DEFAULT,	TF_COMMAND, S_BOOLEAN}, | ||||
| #line 45 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14,	T_OPT_DEFCONFIG_LIST,TF_OPTION}, | ||||
|       {-1}, {-1}, | ||||
| #line 43 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17,		T_ON,		TF_PARAM}, | ||||
| #line 28 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18,	T_OPTIONAL,	TF_COMMAND}, | ||||
|       {-1}, {-1}, | ||||
| #line 42 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21,		T_OPTION,	TF_COMMAND}, | ||||
| #line 17 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22,	T_ENDMENU,	TF_COMMAND}, | ||||
| #line 15 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23,	T_MAINMENU,	TF_COMMAND}, | ||||
|       {-1}, | ||||
| #line 23 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str25,	T_MENUCONFIG,	TF_COMMAND}, | ||||
|       {-1}, | ||||
| #line 44 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27,	T_OPT_MODULES,	TF_OPTION}, | ||||
| #line 47 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28,	T_OPT_ALLNOCONFIG_Y,TF_OPTION}, | ||||
| #line 16 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29,		T_MENU,		TF_COMMAND}, | ||||
|       {-1}, | ||||
| #line 39 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31,		T_SELECT,	TF_COMMAND}, | ||||
| #line 21 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32,	T_COMMENT,	TF_COMMAND}, | ||||
| #line 46 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33,		T_OPT_ENV,	TF_OPTION}, | ||||
|       {-1}, | ||||
| #line 40 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35,		T_RANGE,	TF_COMMAND}, | ||||
| #line 19 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36,		T_CHOICE,	TF_COMMAND}, | ||||
|       {-1}, {-1}, | ||||
| #line 33 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str39,		T_TYPE,		TF_COMMAND, S_BOOLEAN}, | ||||
|       {-1}, | ||||
| #line 18 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41,		T_SOURCE,	TF_COMMAND}, | ||||
| #line 41 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42,	T_VISIBLE,	TF_COMMAND}, | ||||
| #line 37 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43,		T_TYPE,		TF_COMMAND, S_HEX}, | ||||
|       {-1}, {-1}, | ||||
| #line 22 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46,		T_CONFIG,	TF_COMMAND}, | ||||
| #line 34 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47,	T_TYPE,		TF_COMMAND, S_BOOLEAN}, | ||||
|       {-1}, {-1}, {-1}, | ||||
| #line 38 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51,		T_TYPE,		TF_COMMAND, S_STRING}, | ||||
|       {-1}, {-1}, | ||||
| #line 24 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str54,		T_HELP,		TF_COMMAND}, | ||||
|       {-1}, | ||||
| #line 30 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str56,		T_PROMPT,	TF_COMMAND}, | ||||
|       {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, | ||||
|       {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, | ||||
| #line 27 "scripts/kconfig/zconf.gperf" | ||||
|       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str72,	T_DEPENDS,	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; | ||||
| } | ||||
| #line 48 "scripts/kconfig/zconf.gperf" | ||||
| @@ -1,391 +0,0 @@ | ||||
| %option nostdinit noyywrap never-interactive full ecs | ||||
| %option 8bit nodefault perf-report perf-report | ||||
| %option noinput | ||||
| %x COMMAND HELP STRING PARAM | ||||
| %{ | ||||
| /* | ||||
|  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> | ||||
|  * Released under the terms of the GNU GPL v2.0. | ||||
|  */ | ||||
|  | ||||
| #include <glob.h> | ||||
| #include <limits.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "lkc.h" | ||||
|  | ||||
| #define START_STRSIZE	16 | ||||
|  | ||||
| static struct { | ||||
| 	struct file *file; | ||||
| 	int lineno; | ||||
| } current_pos; | ||||
|  | ||||
| static char *text; | ||||
| static int text_size, text_asize; | ||||
|  | ||||
| struct buffer { | ||||
| 	struct buffer *parent; | ||||
| 	YY_BUFFER_STATE state; | ||||
| }; | ||||
|  | ||||
| struct buffer *current_buf; | ||||
|  | ||||
| static int last_ts, first_ts; | ||||
|  | ||||
| static void zconf_endhelp(void); | ||||
| static void zconf_endfile(void); | ||||
|  | ||||
| static void new_string(void) | ||||
| { | ||||
| 	text = xmalloc(START_STRSIZE); | ||||
| 	text_asize = START_STRSIZE; | ||||
| 	text_size = 0; | ||||
| 	*text = 0; | ||||
| } | ||||
|  | ||||
| static void append_string(const char *str, int size) | ||||
| { | ||||
| 	int new_size = text_size + size + 1; | ||||
| 	if (new_size > text_asize) { | ||||
| 		new_size += START_STRSIZE - 1; | ||||
| 		new_size &= -START_STRSIZE; | ||||
| 		text = realloc(text, new_size); | ||||
| 		text_asize = new_size; | ||||
| 	} | ||||
| 	memcpy(text + text_size, str, size); | ||||
| 	text_size += size; | ||||
| 	text[text_size] = 0; | ||||
| } | ||||
|  | ||||
| static void alloc_string(const char *str, int size) | ||||
| { | ||||
| 	text = xmalloc(size + 1); | ||||
| 	memcpy(text, str, size); | ||||
| 	text[size] = 0; | ||||
| } | ||||
| %} | ||||
|  | ||||
| n	[A-Za-z0-9_] | ||||
|  | ||||
| %% | ||||
| 	int str = 0; | ||||
| 	int ts, i; | ||||
|  | ||||
| [ \t]*#.*\n	| | ||||
| [ \t]*\n	{ | ||||
| 	current_file->lineno++; | ||||
| 	return T_EOL; | ||||
| } | ||||
| [ \t]*#.* | ||||
|  | ||||
|  | ||||
| [ \t]+	{ | ||||
| 	BEGIN(COMMAND); | ||||
| } | ||||
|  | ||||
| .	{ | ||||
| 	unput(yytext[0]); | ||||
| 	BEGIN(COMMAND); | ||||
| } | ||||
|  | ||||
|  | ||||
| <COMMAND>{ | ||||
| 	{n}+	{ | ||||
| 		const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); | ||||
| 		BEGIN(PARAM); | ||||
| 		current_pos.file = current_file; | ||||
| 		current_pos.lineno = current_file->lineno; | ||||
| 		if (id && id->flags & TF_COMMAND) { | ||||
| 			zconflval.id = id; | ||||
| 			return id->token; | ||||
| 		} | ||||
| 		alloc_string(yytext, yyleng); | ||||
| 		zconflval.string = text; | ||||
| 		return T_WORD; | ||||
| 	} | ||||
| 	. | ||||
| 	\n	{ | ||||
| 		BEGIN(INITIAL); | ||||
| 		current_file->lineno++; | ||||
| 		return T_EOL; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| <PARAM>{ | ||||
| 	"&&"	return T_AND; | ||||
| 	"||"	return T_OR; | ||||
| 	"("	return T_OPEN_PAREN; | ||||
| 	")"	return T_CLOSE_PAREN; | ||||
| 	"!"	return T_NOT; | ||||
| 	"="	return T_EQUAL; | ||||
| 	"!="	return T_UNEQUAL; | ||||
| 	\"|\'	{ | ||||
| 		str = yytext[0]; | ||||
| 		new_string(); | ||||
| 		BEGIN(STRING); | ||||
| 	} | ||||
| 	\n	BEGIN(INITIAL); current_file->lineno++; return T_EOL; | ||||
| 	---	/* ignore */ | ||||
| 	({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); | ||||
| 		zconflval.string = text; | ||||
| 		return T_WORD; | ||||
| 	} | ||||
| 	#.*	/* comment */ | ||||
| 	\\\n	current_file->lineno++; | ||||
| 	. | ||||
| 	<<EOF>> { | ||||
| 		BEGIN(INITIAL); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| <STRING>{ | ||||
| 	[^'"\\\n]+/\n	{ | ||||
| 		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); | ||||
| 	} | ||||
| 	\'|\"	{ | ||||
| 		if (str == yytext[0]) { | ||||
| 			BEGIN(PARAM); | ||||
| 			zconflval.string = text; | ||||
| 			return T_WORD_QUOTE; | ||||
| 		} else | ||||
| 			append_string(yytext, 1); | ||||
| 	} | ||||
| 	\n	{ | ||||
| 		printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); | ||||
| 		current_file->lineno++; | ||||
| 		BEGIN(INITIAL); | ||||
| 		return T_EOL; | ||||
| 	} | ||||
| 	<<EOF>>	{ | ||||
| 		BEGIN(INITIAL); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| <HELP>{ | ||||
| 	[ \t]+	{ | ||||
| 		ts = 0; | ||||
| 		for (i = 0; i < yyleng; i++) { | ||||
| 			if (yytext[i] == '\t') | ||||
| 				ts = (ts & ~7) + 8; | ||||
| 			else | ||||
| 				ts++; | ||||
| 		} | ||||
| 		last_ts = ts; | ||||
| 		if (first_ts) { | ||||
| 			if (ts < first_ts) { | ||||
| 				zconf_endhelp(); | ||||
| 				return T_HELPTEXT; | ||||
| 			} | ||||
| 			ts -= first_ts; | ||||
| 			while (ts > 8) { | ||||
| 				append_string("        ", 8); | ||||
| 				ts -= 8; | ||||
| 			} | ||||
| 			append_string("        ", ts); | ||||
| 		} | ||||
| 	} | ||||
| 	[ \t]*\n/[^ \t\n] { | ||||
| 		current_file->lineno++; | ||||
| 		zconf_endhelp(); | ||||
| 		return T_HELPTEXT; | ||||
| 	} | ||||
| 	[ \t]*\n	{ | ||||
| 		current_file->lineno++; | ||||
| 		append_string("\n", 1); | ||||
| 	} | ||||
| 	[^ \t\n].* { | ||||
| 		while (yyleng) { | ||||
| 			if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) | ||||
| 				break; | ||||
| 			yyleng--; | ||||
| 		} | ||||
| 		append_string(yytext, yyleng); | ||||
| 		if (!first_ts) | ||||
| 			first_ts = last_ts; | ||||
| 	} | ||||
| 	<<EOF>>	{ | ||||
| 		zconf_endhelp(); | ||||
| 		return T_HELPTEXT; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| <<EOF>>	{ | ||||
| 	if (current_file) { | ||||
| 		zconf_endfile(); | ||||
| 		return T_EOL; | ||||
| 	} | ||||
| 	fclose(yyin); | ||||
| 	yyterminate(); | ||||
| } | ||||
|  | ||||
| %% | ||||
| void zconf_starthelp(void) | ||||
| { | ||||
| 	new_string(); | ||||
| 	last_ts = first_ts = 0; | ||||
| 	BEGIN(HELP); | ||||
| } | ||||
|  | ||||
| static void zconf_endhelp(void) | ||||
| { | ||||
| 	zconflval.string = text; | ||||
| 	BEGIN(INITIAL); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Try to open specified file with following names: | ||||
|  * ./name | ||||
|  * $(srctree)/name | ||||
|  * The latter is used when srctree is separate from objtree | ||||
|  * when compiling the kernel. | ||||
|  * Return NULL if file is not found. | ||||
|  */ | ||||
| FILE *zconf_fopen(const char *name) | ||||
| { | ||||
| 	char *env, fullname[PATH_MAX+1]; | ||||
| 	FILE *f; | ||||
|  | ||||
| 	f = fopen(name, "r"); | ||||
| 	if (!f && name != NULL && name[0] != '/') { | ||||
| 		env = getenv(SRCTREE); | ||||
| 		if (env) { | ||||
| 			snprintf(fullname, sizeof(fullname), | ||||
| 					"%s/%s", env, name); | ||||
| 			f = fopen(fullname, "r"); | ||||
| 		} | ||||
| 	} | ||||
| 	return f; | ||||
| } | ||||
|  | ||||
| void zconf_initscan(const char *name) | ||||
| { | ||||
| 	yyin = zconf_fopen(name); | ||||
| 	if (!yyin) { | ||||
| 		printf("can't find file %s\n", name); | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| 	current_buf = xmalloc(sizeof(*current_buf)); | ||||
| 	memset(current_buf, 0, sizeof(*current_buf)); | ||||
|  | ||||
| 	current_file = file_lookup(name); | ||||
| 	current_file->lineno = 1; | ||||
| } | ||||
|  | ||||
| void zconf_nextfile(const char *name) | ||||
| { | ||||
| 	struct file *iter; | ||||
| 	struct file *file = file_lookup(name); | ||||
| 	struct buffer *buf = xmalloc(sizeof(*buf)); | ||||
| 	memset(buf, 0, sizeof(*buf)); | ||||
|  | ||||
| 	current_buf->state = YY_CURRENT_BUFFER; | ||||
| 	yyin = zconf_fopen(file->name); | ||||
| 	if (!yyin) { | ||||
| 		printf("%s:%d: can't open file \"%s\"\n", | ||||
| 		    zconf_curname(), zconf_lineno(), file->name); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); | ||||
| 	buf->parent = current_buf; | ||||
| 	current_buf = buf; | ||||
|  | ||||
| 	for (iter = current_file->parent; iter; iter = iter->parent ) { | ||||
| 		if (!strcmp(current_file->name,iter->name) ) { | ||||
| 			printf("%s:%d: recursive inclusion detected. " | ||||
| 			       "Inclusion path:\n  current file : '%s'\n", | ||||
| 			       zconf_curname(), zconf_lineno(), | ||||
| 			       zconf_curname()); | ||||
| 			iter = current_file->parent; | ||||
| 			while (iter && \ | ||||
| 			       strcmp(iter->name,current_file->name)) { | ||||
| 				printf("  included from: '%s:%d'\n", | ||||
| 				       iter->name, iter->lineno-1); | ||||
| 				iter = iter->parent; | ||||
| 			} | ||||
| 			if (iter) | ||||
| 				printf("  included from: '%s:%d'\n", | ||||
| 				       iter->name, iter->lineno+1); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 	} | ||||
| 	file->lineno = 1; | ||||
| 	file->parent = current_file; | ||||
| 	current_file = file; | ||||
| } | ||||
|  | ||||
| void zconf_nextfiles(const char *wildcard) | ||||
| { | ||||
| 	glob_t g = {0}; | ||||
| 	char **w; | ||||
| 	int i; | ||||
|  | ||||
| 	if (glob(wildcard, 0, NULL, &g) != 0) { | ||||
| 		return; | ||||
| 	} | ||||
| 	if (g.gl_pathv == NULL) { | ||||
| 		globfree(&g); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	/* working through files backwards, since | ||||
| 	 * we're first pushing them on a stack | ||||
| 	 * before actually handling them. | ||||
| 	 */ | ||||
| 	for (i = g.gl_pathc; i > 0; i--) { | ||||
| 		w = &g.gl_pathv[i - 1]; | ||||
| 		zconf_nextfile(*w); | ||||
| 	} | ||||
|  | ||||
| 	globfree(&g); | ||||
| } | ||||
|  | ||||
| static void zconf_endfile(void) | ||||
| { | ||||
| 	struct buffer *parent; | ||||
|  | ||||
| 	current_file = current_file->parent; | ||||
|  | ||||
| 	parent = current_buf->parent; | ||||
| 	if (parent) { | ||||
| 		fclose(yyin); | ||||
| 		yy_delete_buffer(YY_CURRENT_BUFFER); | ||||
| 		yy_switch_to_buffer(parent->state); | ||||
| 	} | ||||
| 	free(current_buf); | ||||
| 	current_buf = parent; | ||||
| } | ||||
|  | ||||
| int zconf_lineno(void) | ||||
| { | ||||
| 	return current_pos.lineno; | ||||
| } | ||||
|  | ||||
| const char *zconf_curname(void) | ||||
| { | ||||
| 	return current_pos.file ? current_pos.file->name : "<none>"; | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user