aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-06 14:31:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-06 14:31:45 -0400
commit0ad39cb3d70fb4324d127aeceee7f63e3f71605c (patch)
tree627d885a698b485d13be0140fe7e6881486fbd11
parent8715ee75fe6fa3aed367f28aa7a3655e6a8e4688 (diff)
parent2ae89c7a82ea9d81a19b4fc2df23bef4b112f24e (diff)
Merge tag 'kconfig-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild
Pull Kconfig updates from Masahiro Yamada: "Kconfig now supports new functionality to perform textual substitution. It has been a while since Linus suggested to move compiler option tests from makefiles to Kconfig. Finally, here it is. The implementation has been generalized into a Make-like macro language. Some built-in functions such as 'shell' are provided. Variables and user-defined functions are also supported so that 'cc-option', 'ld-option', etc. are implemented as macros. Summary: - refactor package checks for building {m,n,q,g}conf - remove unused/unmaintained localization support - remove Kbuild cache - drop CONFIG_CROSS_COMPILE support - replace 'option env=' with direct variable expansion - add built-in functions such as 'shell' - support variables and user-defined functions - add helper macros as as 'cc-option' - add unit tests and a document of the new macro language - add 'testconfig' to help - fix warnings from GCC 8.1" * tag 'kconfig-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild: (30 commits) kconfig: Avoid format overflow warning from GCC 8.1 kbuild: Move last word of nconfig help to the previous line kconfig: Add testconfig into make help output kconfig: add basic helper macros to scripts/Kconfig.include kconfig: show compiler version text in the top comment kconfig: test: add Kconfig macro language tests Documentation: kconfig: document a new Kconfig macro language kconfig: error out if a recursive variable references itself kconfig: add 'filename' and 'lineno' built-in variables kconfig: add 'info', 'warning-if', and 'error-if' built-in functions kconfig: expand lefthand side of assignment statement kconfig: support append assignment operator kconfig: support simply expanded variable kconfig: support user-defined function and recursively expanded variable kconfig: begin PARAM state only when seeing a command keyword kconfig: replace $(UNAME_RELEASE) with function call kconfig: add 'shell' built-in function kconfig: add built-in function support kconfig: make default prompt of mainmenu less specific kconfig: remove sym_expand_string_value() ...
-rw-r--r--Documentation/kbuild/kconfig-language.txt8
-rw-r--r--Documentation/kbuild/kconfig-macro-language.txt242
-rw-r--r--Kconfig10
-rw-r--r--MAINTAINERS3
-rw-r--r--Makefile10
-rw-r--r--arch/sh/Kconfig4
-rw-r--r--arch/sparc/Kconfig4
-rw-r--r--arch/um/Kconfig.common4
-rw-r--r--arch/x86/Kconfig4
-rw-r--r--arch/x86/um/Kconfig10
-rw-r--r--init/Kconfig25
-rw-r--r--scripts/Kbuild.include102
-rw-r--r--scripts/Kconfig.include27
-rw-r--r--scripts/kconfig/.gitignore4
-rw-r--r--scripts/kconfig/Makefile194
-rw-r--r--scripts/kconfig/POTFILES.in12
-rwxr-xr-xscripts/kconfig/check.sh14
-rw-r--r--scripts/kconfig/conf.c51
-rw-r--r--scripts/kconfig/confdata.c39
-rwxr-xr-xscripts/kconfig/gconf-cfg.sh23
-rw-r--r--scripts/kconfig/gconf.c46
-rw-r--r--scripts/kconfig/kconf_id.c1
-rw-r--r--scripts/kconfig/kxgettext.c235
-rw-r--r--scripts/kconfig/lkc.h19
-rw-r--r--scripts/kconfig/lkc_proto.h15
-rwxr-xr-xscripts/kconfig/lxdialog/check-lxdialog.sh93
-rw-r--r--scripts/kconfig/lxdialog/checklist.c4
-rw-r--r--scripts/kconfig/lxdialog/dialog.h8
-rw-r--r--scripts/kconfig/lxdialog/inputbox.c4
-rw-r--r--scripts/kconfig/lxdialog/menubox.c10
-rw-r--r--scripts/kconfig/lxdialog/textbox.c2
-rw-r--r--scripts/kconfig/lxdialog/yesno.c4
-rwxr-xr-xscripts/kconfig/mconf-cfg.sh44
-rw-r--r--scripts/kconfig/mconf.c141
-rw-r--r--scripts/kconfig/menu.c23
-rw-r--r--scripts/kconfig/nconf-cfg.sh44
-rw-r--r--scripts/kconfig/nconf.c148
-rw-r--r--scripts/kconfig/nconf.h1
-rw-r--r--scripts/kconfig/preprocess.c572
-rwxr-xr-xscripts/kconfig/qconf-cfg.sh25
-rw-r--r--scripts/kconfig/qconf.cc104
-rw-r--r--scripts/kconfig/symbol.c109
-rw-r--r--scripts/kconfig/tests/no_write_if_dep_unmet/expected_config2
-rw-r--r--scripts/kconfig/tests/preprocess/builtin_func/Kconfig27
-rw-r--r--scripts/kconfig/tests/preprocess/builtin_func/__init__.py9
-rw-r--r--scripts/kconfig/tests/preprocess/builtin_func/expected_stderr5
-rw-r--r--scripts/kconfig/tests/preprocess/builtin_func/expected_stdout1
-rw-r--r--scripts/kconfig/tests/preprocess/circular_expansion/Kconfig5
-rw-r--r--scripts/kconfig/tests/preprocess/circular_expansion/__init__.py11
-rw-r--r--scripts/kconfig/tests/preprocess/circular_expansion/expected_stderr1
-rw-r--r--scripts/kconfig/tests/preprocess/escape/Kconfig44
-rw-r--r--scripts/kconfig/tests/preprocess/escape/__init__.py8
-rw-r--r--scripts/kconfig/tests/preprocess/escape/expected_stderr10
-rw-r--r--scripts/kconfig/tests/preprocess/variable/Kconfig53
-rw-r--r--scripts/kconfig/tests/preprocess/variable/__init__.py8
-rw-r--r--scripts/kconfig/tests/preprocess/variable/expected_stderr9
-rw-r--r--scripts/kconfig/util.c33
-rw-r--r--scripts/kconfig/zconf.l95
-rw-r--r--scripts/kconfig/zconf.y46
59 files changed, 1666 insertions, 1143 deletions
diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt
index f5b9493f04ad..0e966e8f9ec7 100644
--- a/Documentation/kbuild/kconfig-language.txt
+++ b/Documentation/kbuild/kconfig-language.txt
@@ -198,14 +198,6 @@ applicable everywhere (see syntax).
198 enables the third modular state for all config symbols. 198 enables the third modular state for all config symbols.
199 At most one symbol may have the "modules" option set. 199 At most one symbol may have the "modules" option set.
200 200
201 - "env"=<value>
202 This imports the environment variable into Kconfig. It behaves like
203 a default, except that the value comes from the environment, this
204 also means that the behaviour when mixing it with normal defaults is
205 undefined at this point. The symbol is currently not exported back
206 to the build environment (if this is desired, it can be done via
207 another symbol).
208
209 - "allnoconfig_y" 201 - "allnoconfig_y"
210 This declares the symbol as one that should have the value y when 202 This declares the symbol as one that should have the value y when
211 using "allnoconfig". Used for symbols that hide other symbols. 203 using "allnoconfig". Used for symbols that hide other symbols.
diff --git a/Documentation/kbuild/kconfig-macro-language.txt b/Documentation/kbuild/kconfig-macro-language.txt
new file mode 100644
index 000000000000..07da2ea68dce
--- /dev/null
+++ b/Documentation/kbuild/kconfig-macro-language.txt
@@ -0,0 +1,242 @@
1Concept
2-------
3
4The basic idea was inspired by Make. When we look at Make, we notice sort of
5two languages in one. One language describes dependency graphs consisting of
6targets and prerequisites. The other is a macro language for performing textual
7substitution.
8
9There is clear distinction between the two language stages. For example, you
10can write a makefile like follows:
11
12 APP := foo
13 SRC := foo.c
14 CC := gcc
15
16 $(APP): $(SRC)
17 $(CC) -o $(APP) $(SRC)
18
19The macro language replaces the variable references with their expanded form,
20and handles as if the source file were input like follows:
21
22 foo: foo.c
23 gcc -o foo foo.c
24
25Then, Make analyzes the dependency graph and determines the targets to be
26updated.
27
28The idea is quite similar in Kconfig - it is possible to describe a Kconfig
29file like this:
30
31 CC := gcc
32
33 config CC_HAS_FOO
34 def_bool $(shell, $(srctree)/scripts/gcc-check-foo.sh $(CC))
35
36The macro language in Kconfig processes the source file into the following
37intermediate:
38
39 config CC_HAS_FOO
40 def_bool y
41
42Then, Kconfig moves onto the evaluation stage to resolve inter-symbol
43dependency as explained in kconfig-language.txt.
44
45
46Variables
47---------
48
49Like in Make, a variable in Kconfig works as a macro variable. A macro
50variable is expanded "in place" to yield a text string that may then be
51expanded further. To get the value of a variable, enclose the variable name in
52$( ). The parentheses are required even for single-letter variable names; $X is
53a syntax error. The curly brace form as in ${CC} is not supported either.
54
55There are two types of variables: simply expanded variables and recursively
56expanded variables.
57
58A simply expanded variable is defined using the := assignment operator. Its
59righthand side is expanded immediately upon reading the line from the Kconfig
60file.
61
62A recursively expanded variable is defined using the = assignment operator.
63Its righthand side is simply stored as the value of the variable without
64expanding it in any way. Instead, the expansion is performed when the variable
65is used.
66
67There is another type of assignment operator; += is used to append text to a
68variable. The righthand side of += is expanded immediately if the lefthand
69side was originally defined as a simple variable. Otherwise, its evaluation is
70deferred.
71
72The variable reference can take parameters, in the following form:
73
74 $(name,arg1,arg2,arg3)
75
76You can consider the parameterized reference as a function. (more precisely,
77"user-defined function" in contrast to "built-in function" listed below).
78
79Useful functions must be expanded when they are used since the same function is
80expanded differently if different parameters are passed. Hence, a user-defined
81function is defined using the = assignment operator. The parameters are
82referenced within the body definition with $(1), $(2), etc.
83
84In fact, recursively expanded variables and user-defined functions are the same
85internally. (In other words, "variable" is "function with zero argument".)
86When we say "variable" in a broad sense, it includes "user-defined function".
87
88
89Built-in functions
90------------------
91
92Like Make, Kconfig provides several built-in functions. Every function takes a
93particular number of arguments.
94
95In Make, every built-in function takes at least one argument. Kconfig allows
96zero argument for built-in functions, such as $(fileno), $(lineno). You could
97consider those as "built-in variable", but it is just a matter of how we call
98it after all. Let's say "built-in function" here to refer to natively supported
99functionality.
100
101Kconfig currently supports the following built-in functions.
102
103 - $(shell,command)
104
105 The "shell" function accepts a single argument that is expanded and passed
106 to a subshell for execution. The standard output of the command is then read
107 and returned as the value of the function. Every newline in the output is
108 replaced with a space. Any trailing newlines are deleted. The standard error
109 is not returned, nor is any program exit status.
110
111 - $(info,text)
112
113 The "info" function takes a single argument and prints it to stdout.
114 It evaluates to an empty string.
115
116 - $(warning-if,condition,text)
117
118 The "warning-if" function takes two arguments. If the condition part is "y",
119 the text part is sent to stderr. The text is prefixed with the name of the
120 current Kconfig file and the current line number.
121
122 - $(error-if,condition,text)
123
124 The "error-if" function is similar to "warning-if", but it terminates the
125 parsing immediately if the condition part is "y".
126
127 - $(filename)
128
129 The 'filename' takes no argument, and $(filename) is expanded to the file
130 name being parsed.
131
132 - $(lineno)
133
134 The 'lineno' takes no argument, and $(lineno) is expanded to the line number
135 being parsed.
136
137
138Make vs Kconfig
139---------------
140
141Kconfig adopts Make-like macro language, but the function call syntax is
142slightly different.
143
144A function call in Make looks like this:
145
146 $(func-name arg1,arg2,arg3)
147
148The function name and the first argument are separated by at least one
149whitespace. Then, leading whitespaces are trimmed from the first argument,
150while whitespaces in the other arguments are kept. You need to use a kind of
151trick to start the first parameter with spaces. For example, if you want
152to make "info" function print " hello", you can write like follows:
153
154 empty :=
155 space := $(empty) $(empty)
156 $(info $(space)$(space)hello)
157
158Kconfig uses only commas for delimiters, and keeps all whitespaces in the
159function call. Some people prefer putting a space after each comma delimiter:
160
161 $(func-name, arg1, arg2, arg3)
162
163In this case, "func-name" will receive " arg1", " arg2", " arg3". The presence
164of leading spaces may matter depending on the function. The same applies to
165Make - for example, $(subst .c, .o, $(sources)) is a typical mistake; it
166replaces ".c" with " .o".
167
168In Make, a user-defined function is referenced by using a built-in function,
169'call', like this:
170
171 $(call my-func,arg1,arg2,arg3)
172
173Kconfig invokes user-defined functions and built-in functions in the same way.
174The omission of 'call' makes the syntax shorter.
175
176In Make, some functions treat commas verbatim instead of argument separators.
177For example, $(shell echo hello, world) runs the command "echo hello, world".
178Likewise, $(info hello, world) prints "hello, world" to stdout. You could say
179this is _useful_ inconsistency.
180
181In Kconfig, for simpler implementation and grammatical consistency, commas that
182appear in the $( ) context are always delimiters. It means
183
184 $(shell, echo hello, world)
185
186is an error because it is passing two parameters where the 'shell' function
187accepts only one. To pass commas in arguments, you can use the following trick:
188
189 comma := ,
190 $(shell, echo hello$(comma) world)
191
192
193Caveats
194-------
195
196A variable (or function) cannot be expanded across tokens. So, you cannot use
197a variable as a shorthand for an expression that consists of multiple tokens.
198The following works:
199
200 RANGE_MIN := 1
201 RANGE_MAX := 3
202
203 config FOO
204 int "foo"
205 range $(RANGE_MIN) $(RANGE_MAX)
206
207But, the following does not work:
208
209 RANGES := 1 3
210
211 config FOO
212 int "foo"
213 range $(RANGES)
214
215A variable cannot be expanded to any keyword in Kconfig. The following does
216not work:
217
218 MY_TYPE := tristate
219
220 config FOO
221 $(MY_TYPE) "foo"
222 default y
223
224Obviously from the design, $(shell command) is expanded in the textual
225substitution phase. You cannot pass symbols to the 'shell' function.
226The following does not work as expected.
227
228 config ENDIAN_FLAG
229 string
230 default "-mbig-endian" if CPU_BIG_ENDIAN
231 default "-mlittle-endian" if CPU_LITTLE_ENDIAN
232
233 config CC_HAS_ENDIAN_FLAG
234 def_bool $(shell $(srctree)/scripts/gcc-check-flag ENDIAN_FLAG)
235
236Instead, you can do like follows so that any function call is statically
237expanded.
238
239 config CC_HAS_ENDIAN_FLAG
240 bool
241 default $(shell $(srctree)/scripts/gcc-check-flag -mbig-endian) if CPU_BIG_ENDIAN
242 default $(shell $(srctree)/scripts/gcc-check-flag -mlittle-endian) if CPU_LITTLE_ENDIAN
diff --git a/Kconfig b/Kconfig
index 8c4c1cb0f9cd..a90d9f9e268b 100644
--- a/Kconfig
+++ b/Kconfig
@@ -3,10 +3,10 @@
3# For a description of the syntax of this configuration file, 3# For a description of the syntax of this configuration file,
4# see Documentation/kbuild/kconfig-language.txt. 4# see Documentation/kbuild/kconfig-language.txt.
5# 5#
6mainmenu "Linux/$ARCH $KERNELVERSION Kernel Configuration" 6mainmenu "Linux/$(ARCH) $(KERNELVERSION) Kernel Configuration"
7 7
8config SRCARCH 8comment "Compiler: $(CC_VERSION_TEXT)"
9 string
10 option env="SRCARCH"
11 9
12source "arch/$SRCARCH/Kconfig" 10source "scripts/Kconfig.include"
11
12source "arch/$(SRCARCH)/Kconfig"
diff --git a/MAINTAINERS b/MAINTAINERS
index cfae882e63df..66cd131c517d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7684,8 +7684,9 @@ M: Masahiro Yamada <yamada.masahiro@socionext.com>
7684T: git git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git kconfig 7684T: git git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git kconfig
7685L: linux-kbuild@vger.kernel.org 7685L: linux-kbuild@vger.kernel.org
7686S: Maintained 7686S: Maintained
7687F: Documentation/kbuild/kconfig-language.txt 7687F: Documentation/kbuild/kconfig*
7688F: scripts/kconfig/ 7688F: scripts/kconfig/
7689F: scripts/Kconfig.include
7689 7690
7690KDUMP 7691KDUMP
7691M: Dave Young <dyoung@redhat.com> 7692M: Dave Young <dyoung@redhat.com>
diff --git a/Makefile b/Makefile
index 0d5cdaa72d5f..bbc979aeea29 100644
--- a/Makefile
+++ b/Makefile
@@ -316,12 +316,9 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
316# CROSS_COMPILE can be set on the command line 316# CROSS_COMPILE can be set on the command line
317# make CROSS_COMPILE=ia64-linux- 317# make CROSS_COMPILE=ia64-linux-
318# Alternatively CROSS_COMPILE can be set in the environment. 318# Alternatively CROSS_COMPILE can be set in the environment.
319# A third alternative is to store a setting in .config so that plain
320# "make" in the configured kernel build directory always uses that.
321# Default value for CROSS_COMPILE is not to prefix executables 319# Default value for CROSS_COMPILE is not to prefix executables
322# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile 320# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
323ARCH ?= $(SUBARCH) 321ARCH ?= $(SUBARCH)
324CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
325 322
326# Architecture as present in compile.h 323# Architecture as present in compile.h
327UTS_MACHINE := $(ARCH) 324UTS_MACHINE := $(ARCH)
@@ -445,6 +442,8 @@ export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
445export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL 442export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
446export KBUILD_ARFLAGS 443export KBUILD_ARFLAGS
447 444
445export CC_VERSION_TEXT := $(shell $(CC) --version | head -n 1)
446
448# When compiling out-of-tree modules, put MODVERDIR in the module 447# When compiling out-of-tree modules, put MODVERDIR in the module
449# tree rather than in the kernel tree. The kernel tree might 448# tree rather than in the kernel tree. The kernel tree might
450# even be read-only. 449# even be read-only.
@@ -504,7 +503,7 @@ KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
504KBUILD_AFLAGS += $(call cc-option,-fno-PIE) 503KBUILD_AFLAGS += $(call cc-option,-fno-PIE)
505 504
506# check for 'asm goto' 505# check for 'asm goto'
507ifeq ($(call shell-cached,$(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y) 506ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y)
508 CC_HAVE_ASM_GOTO := 1 507 CC_HAVE_ASM_GOTO := 1
509 KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO 508 KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
510 KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO 509 KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO
@@ -807,7 +806,7 @@ KBUILD_CFLAGS_KERNEL += $(call cc-option,-fdata-sections,)
807endif 806endif
808 807
809# arch Makefile may override CC so keep this after arch Makefile is included 808# arch Makefile may override CC so keep this after arch Makefile is included
810NOSTDINC_FLAGS += -nostdinc -isystem $(call shell-cached,$(CC) -print-file-name=include) 809NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
811 810
812# warn about C99 declaration after statement 811# warn about C99 declaration after statement
813KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) 812KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
@@ -1630,7 +1629,6 @@ clean: $(clean-dirs)
1630 -o -name '*.asn1.[ch]' \ 1629 -o -name '*.asn1.[ch]' \
1631 -o -name '*.symtypes' -o -name 'modules.order' \ 1630 -o -name '*.symtypes' -o -name 'modules.order' \
1632 -o -name modules.builtin -o -name '.tmp_*.o.*' \ 1631 -o -name modules.builtin -o -name '.tmp_*.o.*' \
1633 -o -name .cache.mk \
1634 -o -name '*.c.[012]*.*' \ 1632 -o -name '*.c.[012]*.*' \
1635 -o -name '*.ll' \ 1633 -o -name '*.ll' \
1636 -o -name '*.gcno' \) -type f -print | xargs rm -f 1634 -o -name '*.gcno' \) -type f -print | xargs rm -f
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index a97538b607a4..ae619d54018c 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -60,7 +60,7 @@ config SUPERH
60 <http://www.linux-sh.org/>. 60 <http://www.linux-sh.org/>.
61 61
62config SUPERH32 62config SUPERH32
63 def_bool ARCH = "sh" 63 def_bool "$(ARCH)" = "sh"
64 select HAVE_KPROBES 64 select HAVE_KPROBES
65 select HAVE_KRETPROBES 65 select HAVE_KRETPROBES
66 select HAVE_IOREMAP_PROT if MMU && !X2TLB 66 select HAVE_IOREMAP_PROT if MMU && !X2TLB
@@ -79,7 +79,7 @@ config SUPERH32
79 select HAVE_CC_STACKPROTECTOR 79 select HAVE_CC_STACKPROTECTOR
80 80
81config SUPERH64 81config SUPERH64
82 def_bool ARCH = "sh64" 82 def_bool "$(ARCH)" = "sh64"
83 select HAVE_EXIT_THREAD 83 select HAVE_EXIT_THREAD
84 select KALLSYMS 84 select KALLSYMS
85 85
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 435dbc033afe..b42ba888217d 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -1,6 +1,6 @@
1config 64BIT 1config 64BIT
2 bool "64-bit kernel" if ARCH = "sparc" 2 bool "64-bit kernel" if "$(ARCH)" = "sparc"
3 default ARCH = "sparc64" 3 default "$(ARCH)" = "sparc64"
4 help 4 help
5 SPARC is a family of RISC microprocessors designed and marketed by 5 SPARC is a family of RISC microprocessors designed and marketed by
6 Sun Microsystems, incorporated. They are very widely found in Sun 6 Sun Microsystems, incorporated. They are very widely found in Sun
diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common
index c68add8df3ae..07f84c842cc3 100644
--- a/arch/um/Kconfig.common
+++ b/arch/um/Kconfig.common
@@ -54,10 +54,6 @@ config HZ
54 int 54 int
55 default 100 55 default 100
56 56
57config SUBARCH
58 string
59 option env="SUBARCH"
60
61config NR_CPUS 57config NR_CPUS
62 int 58 int
63 range 1 1 59 range 1 1
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 1fe24b624d44..ed796c92701f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1,8 +1,8 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2# Select 32 or 64 bit 2# Select 32 or 64 bit
3config 64BIT 3config 64BIT
4 bool "64-bit kernel" if ARCH = "x86" 4 bool "64-bit kernel" if "$(ARCH)" = "x86"
5 default ARCH != "i386" 5 default "$(ARCH)" != "i386"
6 ---help--- 6 ---help---
7 Say yes to build a 64-bit kernel - formerly known as x86_64 7 Say yes to build a 64-bit kernel - formerly known as x86_64
8 Say no to build a 32-bit kernel - formerly known as i386 8 Say no to build a 32-bit kernel - formerly known as i386
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
index 13ed827c7c66..9d529f22fd9d 100644
--- a/arch/x86/um/Kconfig
+++ b/arch/x86/um/Kconfig
@@ -1,5 +1,9 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2mainmenu "User Mode Linux/$SUBARCH $KERNELVERSION Kernel Configuration" 2mainmenu "User Mode Linux/$(SUBARCH) $(KERNELVERSION) Kernel Configuration"
3
4comment "Compiler: $(CC_VERSION_TEXT)"
5
6source "scripts/Kconfig.include"
3 7
4source "arch/um/Kconfig.common" 8source "arch/um/Kconfig.common"
5 9
@@ -16,8 +20,8 @@ config UML_X86
16 select GENERIC_FIND_FIRST_BIT 20 select GENERIC_FIND_FIRST_BIT
17 21
18config 64BIT 22config 64BIT
19 bool "64-bit kernel" if SUBARCH = "x86" 23 bool "64-bit kernel" if "$(SUBARCH)" = "x86"
20 default SUBARCH != "i386" 24 default "$(SUBARCH)" != "i386"
21 25
22config X86_32 26config X86_32
23 def_bool !64BIT 27 def_bool !64BIT
diff --git a/init/Kconfig b/init/Kconfig
index 829a4c1117f2..0274d0d28df7 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1,20 +1,12 @@
1config ARCH
2 string
3 option env="ARCH"
4
5config KERNELVERSION
6 string
7 option env="KERNELVERSION"
8
9config DEFCONFIG_LIST 1config DEFCONFIG_LIST
10 string 2 string
11 depends on !UML 3 depends on !UML
12 option defconfig_list 4 option defconfig_list
13 default "/lib/modules/$UNAME_RELEASE/.config" 5 default "/lib/modules/$(shell,uname --release)/.config"
14 default "/etc/kernel-config" 6 default "/etc/kernel-config"
15 default "/boot/config-$UNAME_RELEASE" 7 default "/boot/config-$(shell,uname --release)"
16 default "$ARCH_DEFCONFIG" 8 default ARCH_DEFCONFIG
17 default "arch/$ARCH/defconfig" 9 default "arch/$(ARCH)/defconfig"
18 10
19config CONSTRUCTORS 11config CONSTRUCTORS
20 bool 12 bool
@@ -54,15 +46,6 @@ config INIT_ENV_ARG_LIMIT
54 Maximum of each of the number of arguments and environment 46 Maximum of each of the number of arguments and environment
55 variables passed to init from the kernel command line. 47 variables passed to init from the kernel command line.
56 48
57
58config CROSS_COMPILE
59 string "Cross-compiler tool prefix"
60 help
61 Same as running 'make CROSS_COMPILE=prefix-' but stored for
62 default make runs in this kernel build directory. You don't
63 need to set this unless you want the configured kernel build
64 directory to select the cross-compiler automatically.
65
66config COMPILE_TEST 49config COMPILE_TEST
67 bool "Compile also drivers which will not load" 50 bool "Compile also drivers which will not load"
68 depends on !UML 51 depends on !UML
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 50cee534fd64..c8156d61678c 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -8,8 +8,6 @@ squote := '
8empty := 8empty :=
9space := $(empty) $(empty) 9space := $(empty) $(empty)
10space_escape := _-_SPACE_-_ 10space_escape := _-_SPACE_-_
11right_paren := )
12left_paren := (
13pound := \# 11pound := \#
14 12
15### 13###
@@ -57,7 +55,6 @@ kecho := $($(quiet)kecho)
57# to specify a valid file as first prerequisite (often the kbuild file) 55# to specify a valid file as first prerequisite (often the kbuild file)
58define filechk 56define filechk
59 $(Q)set -e; \ 57 $(Q)set -e; \
60 $(kecho) ' CHK $@'; \
61 mkdir -p $(dir $@); \ 58 mkdir -p $(dir $@); \
62 $(filechk_$(1)) < $< > $@.tmp; \ 59 $(filechk_$(1)) < $< > $@.tmp; \
63 if [ -r $@ ] && cmp -s $@ $@.tmp; then \ 60 if [ -r $@ ] && cmp -s $@ $@.tmp; then \
@@ -83,71 +80,6 @@ cc-cross-prefix = \
83 echo $(c); \ 80 echo $(c); \
84 fi))) 81 fi)))
85 82
86# Tools for caching Makefile variables that are "expensive" to compute.
87#
88# Here we want to help deal with variables that take a long time to compute
89# by making it easy to store these variables in a cache.
90#
91# The canonical example here is testing for compiler flags. On a simple system
92# each call to the compiler takes 10 ms, but on a system with a compiler that's
93# called through various wrappers it can take upwards of 100 ms. If we have
94# 100 calls to the compiler this can take 1 second (on a simple system) or 10
95# seconds (on a complicated system).
96#
97# The "cache" will be in Makefile syntax and can be directly included.
98# Any time we try to reference a variable that's not in the cache we'll
99# calculate it and store it in the cache for next time.
100
101# Include values from last time
102make-cache := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/,$(if $(obj),$(obj)/)).cache.mk
103$(make-cache): ;
104-include $(make-cache)
105
106cached-data := $(filter __cached_%, $(.VARIABLES))
107
108# If cache exceeds 1000 lines, shrink it down to 500.
109ifneq ($(word 1000,$(cached-data)),)
110$(shell tail -n 500 $(make-cache) > $(make-cache).tmp; \
111 mv $(make-cache).tmp $(make-cache))
112endif
113
114create-cache-dir := $(if $(KBUILD_SRC),$(if $(cache-data),,1))
115
116# Usage: $(call __sanitize-opt,Hello=Hola$(comma)Goodbye Adios)
117#
118# Convert all '$', ')', '(', '\', '=', ' ', ',', ':' to '_'
119__sanitize-opt = $(subst $$,_,$(subst $(right_paren),_,$(subst $(left_paren),_,$(subst \,_,$(subst =,_,$(subst $(space),_,$(subst $(comma),_,$(subst :,_,$(1)))))))))
120
121# Usage: $(call shell-cached,shell_command)
122# Example: $(call shell-cached,md5sum /usr/bin/gcc)
123#
124# If we've already seen a call to this exact shell command (even in a
125# previous invocation of make!) we'll return the value. If not, we'll
126# compute it and store the result for future runs.
127#
128# This is a bit of voodoo, but basic explanation is that if the variable
129# was undefined then we'll evaluate the shell command and store the result
130# into the variable. We'll then store that value in the cache and finally
131# output the value.
132#
133# NOTE: The $$(2) here isn't actually a parameter to __run-and-store. We
134# happen to know that the caller will have their shell command in $(2) so the
135# result of "call"ing this will produce a reference to that $(2). The reason
136# for this strangeness is to avoid an extra level of eval (and escaping) of
137# $(2).
138define __run-and-store
139ifeq ($(origin $(1)),undefined)
140 $$(eval $(1) := $$(shell $$(2)))
141ifeq ($(create-cache-dir),1)
142 $$(shell mkdir -p $(dir $(make-cache)))
143 $$(eval create-cache-dir :=)
144endif
145 $$(shell echo '$(1) := $$($(1))' >> $(make-cache))
146endif
147endef
148__shell-cached = $(eval $(call __run-and-store,$(1)))$($(1))
149shell-cached = $(call __shell-cached,__cached_$(call __sanitize-opt,$(1)),$(1))
150
151# output directory for tests below 83# output directory for tests below
152TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/) 84TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
153 85
@@ -155,36 +87,30 @@ TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
155# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise) 87# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
156# Exit code chooses option. "$$TMP" serves as a temporary file and is 88# Exit code chooses option. "$$TMP" serves as a temporary file and is
157# automatically cleaned up. 89# automatically cleaned up.
158__try-run = set -e; \ 90try-run = $(shell set -e; \
159 TMP="$(TMPOUT).$$$$.tmp"; \ 91 TMP="$(TMPOUT).$$$$.tmp"; \
160 TMPO="$(TMPOUT).$$$$.o"; \ 92 TMPO="$(TMPOUT).$$$$.o"; \
161 if ($(1)) >/dev/null 2>&1; \ 93 if ($(1)) >/dev/null 2>&1; \
162 then echo "$(2)"; \ 94 then echo "$(2)"; \
163 else echo "$(3)"; \ 95 else echo "$(3)"; \
164 fi; \ 96 fi; \
165 rm -f "$$TMP" "$$TMPO" 97 rm -f "$$TMP" "$$TMPO")
166
167try-run = $(shell $(__try-run))
168
169# try-run-cached
170# This works like try-run, but the result is cached.
171try-run-cached = $(call shell-cached,$(__try-run))
172 98
173# as-option 99# as-option
174# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,) 100# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
175 101
176as-option = $(call try-run-cached,\ 102as-option = $(call try-run,\
177 $(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2)) 103 $(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2))
178 104
179# as-instr 105# as-instr
180# Usage: cflags-y += $(call as-instr,instr,option1,option2) 106# Usage: cflags-y += $(call as-instr,instr,option1,option2)
181 107
182as-instr = $(call try-run-cached,\ 108as-instr = $(call try-run,\
183 printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3)) 109 printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
184 110
185# __cc-option 111# __cc-option
186# Usage: MY_CFLAGS += $(call __cc-option,$(CC),$(MY_CFLAGS),-march=winchip-c6,-march=i586) 112# Usage: MY_CFLAGS += $(call __cc-option,$(CC),$(MY_CFLAGS),-march=winchip-c6,-march=i586)
187__cc-option = $(call try-run-cached,\ 113__cc-option = $(call try-run,\
188 $(1) -Werror $(2) $(3) -c -x c /dev/null -o "$$TMP",$(3),$(4)) 114 $(1) -Werror $(2) $(3) -c -x c /dev/null -o "$$TMP",$(3),$(4))
189 115
190# Do not attempt to build with gcc plugins during cc-option tests. 116# Do not attempt to build with gcc plugins during cc-option tests.
@@ -204,23 +130,23 @@ hostcc-option = $(call __cc-option, $(HOSTCC),\
204 130
205# cc-option-yn 131# cc-option-yn
206# Usage: flag := $(call cc-option-yn,-march=winchip-c6) 132# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
207cc-option-yn = $(call try-run-cached,\ 133cc-option-yn = $(call try-run,\
208 $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n) 134 $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
209 135
210# cc-disable-warning 136# cc-disable-warning
211# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable) 137# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
212cc-disable-warning = $(call try-run-cached,\ 138cc-disable-warning = $(call try-run,\
213 $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1))) 139 $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
214 140
215# cc-name 141# cc-name
216# Expands to either gcc or clang 142# Expands to either gcc or clang
217cc-name = $(call shell-cached,$(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc) 143cc-name = $(shell $(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc)
218 144
219# cc-version 145# cc-version
220cc-version = $(call shell-cached,$(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) 146cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
221 147
222# cc-fullversion 148# cc-fullversion
223cc-fullversion = $(call shell-cached,$(CONFIG_SHELL) \ 149cc-fullversion = $(shell $(CONFIG_SHELL) \
224 $(srctree)/scripts/gcc-version.sh -p $(CC)) 150 $(srctree)/scripts/gcc-version.sh -p $(CC))
225 151
226# cc-ifversion 152# cc-ifversion
@@ -233,21 +159,21 @@ cc-if-fullversion = $(shell [ $(cc-fullversion) $(1) $(2) ] && echo $(3) || echo
233 159
234# cc-ldoption 160# cc-ldoption
235# Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both) 161# Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both)
236cc-ldoption = $(call try-run-cached,\ 162cc-ldoption = $(call try-run,\
237 $(CC) $(1) $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2)) 163 $(CC) $(1) $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2))
238 164
239# ld-option 165# ld-option
240# Usage: LDFLAGS += $(call ld-option, -X) 166# Usage: LDFLAGS += $(call ld-option, -X)
241ld-option = $(call try-run-cached, $(LD) $(LDFLAGS) $(1) -v,$(1),$(2)) 167ld-option = $(call try-run, $(LD) $(LDFLAGS) $(1) -v,$(1),$(2))
242 168
243# ar-option 169# ar-option
244# Usage: KBUILD_ARFLAGS := $(call ar-option,D) 170# Usage: KBUILD_ARFLAGS := $(call ar-option,D)
245# Important: no spaces around options 171# Important: no spaces around options
246ar-option = $(call try-run-cached, $(AR) rc$(1) "$$TMP",$(1),$(2)) 172ar-option = $(call try-run, $(AR) rc$(1) "$$TMP",$(1),$(2))
247 173
248# ld-version 174# ld-version
249# Note this is mainly for HJ Lu's 3 number binutil versions 175# Note this is mainly for HJ Lu's 3 number binutil versions
250ld-version = $(call shell-cached,$(LD) --version | $(srctree)/scripts/ld-version.sh) 176ld-version = $(shell $(LD) --version | $(srctree)/scripts/ld-version.sh)
251 177
252# ld-ifversion 178# ld-ifversion
253# Usage: $(call ld-ifversion, -ge, 22252, y) 179# Usage: $(call ld-ifversion, -ge, 22252, y)
diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include
new file mode 100644
index 000000000000..bf7c0c9fa3a4
--- /dev/null
+++ b/scripts/Kconfig.include
@@ -0,0 +1,27 @@
1# Kconfig helper macros
2
3# Convenient variables
4comma := ,
5quote := "
6squote := '
7empty :=
8space := $(empty) $(empty)
9dollar := $
10right_paren := )
11left_paren := (
12
13# $(if-success,<command>,<then>,<else>)
14# Return <then> if <command> exits with 0, <else> otherwise.
15if-success = $(shell,{ $(1); } >/dev/null 2>&1 && echo "$(2)" || echo "$(3)")
16
17# $(success,<command>)
18# Return y if <command> exits with 0, n otherwise
19success = $(if-success,$(1),y,n)
20
21# $(cc-option,<flag>)
22# Return y if the compiler supports <flag>, n otherwise
23cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)
24
25# $(ld-option,<flag>)
26# Return y if the linker supports <flag>, n otherwise
27ld-option = $(success,$(LD) -v $(1))
diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore
index 2da579edcbaf..0aabc1d6a182 100644
--- a/scripts/kconfig/.gitignore
+++ b/scripts/kconfig/.gitignore
@@ -2,9 +2,6 @@
2# Generated files 2# Generated files
3# 3#
4*.moc 4*.moc
5gconf.glade.h
6*.pot
7*.mo
8 5
9# 6#
10# configuration programs 7# configuration programs
@@ -14,4 +11,3 @@ mconf
14nconf 11nconf
15qconf 12qconf
16gconf 13gconf
17kxgettext
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 5def8779d7d8..a3ac2c91331c 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -3,7 +3,7 @@
3# Kernel configuration targets 3# Kernel configuration targets
4# These targets are used from top-level makefile 4# These targets are used from top-level makefile
5 5
6PHONY += xconfig gconfig menuconfig config syncconfig update-po-config \ 6PHONY += xconfig gconfig menuconfig config syncconfig \
7 localmodconfig localyesconfig 7 localmodconfig localyesconfig
8 8
9ifdef KBUILD_KCONFIG 9ifdef KBUILD_KCONFIG
@@ -55,29 +55,6 @@ localyesconfig localmodconfig: $(obj)/conf
55 fi 55 fi
56 $(Q)rm -f .tmp.config 56 $(Q)rm -f .tmp.config
57 57
58# Create new linux.pot file
59# Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files
60update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h
61 $(Q)$(kecho) " GEN config.pot"
62 $(Q)xgettext --default-domain=linux \
63 --add-comments --keyword=_ --keyword=N_ \
64 --from-code=UTF-8 \
65 --files-from=$(srctree)/scripts/kconfig/POTFILES.in \
66 --directory=$(srctree) --directory=$(objtree) \
67 --output $(obj)/config.pot
68 $(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot
69 $(Q)(for i in `ls $(srctree)/arch/*/Kconfig \
70 $(srctree)/arch/*/um/Kconfig`; \
71 do \
72 $(kecho) " GEN $$i"; \
73 $(obj)/kxgettext $$i \
74 >> $(obj)/config.pot; \
75 done )
76 $(Q)$(kecho) " GEN linux.pot"
77 $(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \
78 --output $(obj)/linux.pot
79 $(Q)rm -f $(obj)/config.pot
80
81# These targets map 1:1 to the commandline options of 'conf' 58# These targets map 1:1 to the commandline options of 'conf'
82simple-targets := oldconfig allnoconfig allyesconfig allmodconfig \ 59simple-targets := oldconfig allnoconfig allyesconfig allmodconfig \
83 alldefconfig randconfig listnewconfig olddefconfig 60 alldefconfig randconfig listnewconfig olddefconfig
@@ -151,8 +128,7 @@ clean-dirs += tests/.cache
151# Help text used by make help 128# Help text used by make help
152help: 129help:
153 @echo ' config - Update current config utilising a line-oriented program' 130 @echo ' config - Update current config utilising a line-oriented program'
154 @echo ' nconfig - Update current config utilising a ncurses menu based' 131 @echo ' nconfig - Update current config utilising a ncurses menu based program'
155 @echo ' program'
156 @echo ' menuconfig - Update current config utilising a menu based program' 132 @echo ' menuconfig - Update current config utilising a menu based program'
157 @echo ' xconfig - Update current config utilising a Qt based front-end' 133 @echo ' xconfig - Update current config utilising a Qt based front-end'
158 @echo ' gconfig - Update current config utilising a GTK+ based front-end' 134 @echo ' gconfig - Update current config utilising a GTK+ based front-end'
@@ -172,141 +148,77 @@ help:
172 @echo ' kvmconfig - Enable additional options for kvm guest kernel support' 148 @echo ' kvmconfig - Enable additional options for kvm guest kernel support'
173 @echo ' xenconfig - Enable additional options for xen dom0 and guest kernel support' 149 @echo ' xenconfig - Enable additional options for xen dom0 and guest kernel support'
174 @echo ' tinyconfig - Configure the tiniest possible kernel' 150 @echo ' tinyconfig - Configure the tiniest possible kernel'
175 151 @echo ' testconfig - Run Kconfig unit tests (requires python3 and pytest)'
176# lxdialog stuff
177check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
178
179# Use recursively expanded variables so we do not call gcc unless
180# we really need to do so. (Do not call gcc as part of make mrproper)
181HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \
182 -DLOCALE
183 152
184# =========================================================================== 153# ===========================================================================
185# Shared Makefile for the various kconfig executables: 154# Shared Makefile for the various kconfig executables:
186# conf: Used for defconfig, oldconfig and related targets 155# conf: Used for defconfig, oldconfig and related targets
187# nconf: Used for the nconfig target.
188# Utilizes ncurses
189# mconf: Used for the menuconfig target
190# Utilizes the lxdialog package
191# qconf: Used for the xconfig target
192# Based on Qt which needs to be installed to compile it
193# gconf: Used for the gconfig target
194# Based on GTK+ which needs to be installed to compile it
195# object files used by all kconfig flavours 156# object files used by all kconfig flavours
196 157
197lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o
198lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o
199
200conf-objs := conf.o zconf.tab.o 158conf-objs := conf.o zconf.tab.o
201mconf-objs := mconf.o zconf.tab.o $(lxdialog)
202nconf-objs := nconf.o zconf.tab.o nconf.gui.o
203kxgettext-objs := kxgettext.o zconf.tab.o
204qconf-cxxobjs := qconf.o
205qconf-objs := zconf.tab.o
206gconf-objs := gconf.o zconf.tab.o
207 159
208hostprogs-y := conf nconf mconf kxgettext qconf gconf 160hostprogs-y := conf
209 161
210targets += zconf.lex.c 162targets += zconf.lex.c
211clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck
212clean-files += gconf.glade.h
213clean-files += config.pot linux.pot
214
215# Check that we have the required ncurses stuff installed for lxdialog (menuconfig)
216PHONY += $(obj)/dochecklxdialog
217$(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/dochecklxdialog
218$(obj)/dochecklxdialog:
219 $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTLOADLIBES_mconf)
220
221always := dochecklxdialog
222
223# Add environment specific flags
224HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS))
225HOST_EXTRACXXFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCXX) $(HOSTCXXFLAGS))
226 163
227# generated files seem to need this to find local include files 164# generated files seem to need this to find local include files
228HOSTCFLAGS_zconf.lex.o := -I$(src) 165HOSTCFLAGS_zconf.lex.o := -I$(src)
229HOSTCFLAGS_zconf.tab.o := -I$(src) 166HOSTCFLAGS_zconf.tab.o := -I$(src)
230 167
231HOSTLOADLIBES_qconf = $(KC_QT_LIBS) 168# nconf: Used for the nconfig target based on ncurses
232HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) 169hostprogs-y += nconf
233 170nconf-objs := nconf.o zconf.tab.o nconf.gui.o
234HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0`
235HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
236 -Wno-missing-prototypes
237
238HOSTLOADLIBES_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
239
240HOSTLOADLIBES_nconf = $(shell \
241 pkg-config --libs menuw panelw ncursesw 2>/dev/null \
242 || pkg-config --libs menu panel ncurses 2>/dev/null \
243 || echo "-lmenu -lpanel -lncurses" )
244$(obj)/qconf.o: $(obj)/.tmp_qtcheck
245
246ifeq ($(MAKECMDGOALS),xconfig)
247$(obj)/.tmp_qtcheck: $(src)/Makefile
248-include $(obj)/.tmp_qtcheck
249
250# Qt needs some extra effort...
251$(obj)/.tmp_qtcheck:
252 @set -e; $(kecho) " CHECK qt"; \
253 if pkg-config --exists Qt5Core; then \
254 cflags="-std=c++11 -fPIC `pkg-config --cflags Qt5Core Qt5Gui Qt5Widgets`"; \
255 libs=`pkg-config --libs Qt5Core Qt5Gui Qt5Widgets`; \
256 moc=`pkg-config --variable=host_bins Qt5Core`/moc; \
257 elif pkg-config --exists QtCore; then \
258 cflags=`pkg-config --cflags QtCore QtGui`; \
259 libs=`pkg-config --libs QtCore QtGui`; \
260 moc=`pkg-config --variable=moc_location QtCore`; \
261 else \
262 echo >&2 "*"; \
263 echo >&2 "* Could not find Qt via pkg-config."; \
264 echo >&2 "* Please install either Qt 4.8 or 5.x. and make sure it's in PKG_CONFIG_PATH"; \
265 echo >&2 "*"; \
266 exit 1; \
267 fi; \
268 echo "KC_QT_CFLAGS=$$cflags" > $@; \
269 echo "KC_QT_LIBS=$$libs" >> $@; \
270 echo "KC_QT_MOC=$$moc" >> $@
271endif
272 171
273$(obj)/gconf.o: $(obj)/.tmp_gtkcheck 172HOSTLOADLIBES_nconf = $(shell . $(obj)/.nconf-cfg && echo $$libs)
274 173HOSTCFLAGS_nconf.o = $(shell . $(obj)/.nconf-cfg && echo $$cflags)
275ifeq ($(MAKECMDGOALS),gconfig) 174HOSTCFLAGS_nconf.gui.o = $(shell . $(obj)/.nconf-cfg && echo $$cflags)
276-include $(obj)/.tmp_gtkcheck
277
278# GTK+ needs some extra effort, too...
279$(obj)/.tmp_gtkcheck:
280 @if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then \
281 if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \
282 touch $@; \
283 else \
284 echo >&2 "*"; \
285 echo >&2 "* GTK+ is present but version >= 2.0.0 is required."; \
286 echo >&2 "*"; \
287 false; \
288 fi \
289 else \
290 echo >&2 "*"; \
291 echo >&2 "* Unable to find the GTK+ installation. Please make sure that"; \
292 echo >&2 "* the GTK+ 2.0 development package is correctly installed..."; \
293 echo >&2 "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \
294 echo >&2 "*"; \
295 false; \
296 fi
297endif
298 175
299$(obj)/zconf.tab.o: $(obj)/zconf.lex.c 176$(obj)/nconf.o: $(obj)/.nconf-cfg
177
178# mconf: Used for the menuconfig target based on lxdialog
179hostprogs-y += mconf
180lxdialog := checklist.o inputbox.o menubox.o textbox.o util.o yesno.o
181mconf-objs := mconf.o zconf.tab.o $(addprefix lxdialog/, $(lxdialog))
300 182
301$(obj)/qconf.o: $(obj)/qconf.moc 183HOSTLOADLIBES_mconf = $(shell . $(obj)/.mconf-cfg && echo $$libs)
184$(foreach f, mconf.o $(lxdialog), \
185 $(eval HOSTCFLAGS_$f = $$(shell . $(obj)/.mconf-cfg && echo $$$$cflags)))
186
187$(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/.mconf-cfg
188
189# qconf: Used for the xconfig target based on Qt
190hostprogs-y += qconf
191qconf-cxxobjs := qconf.o
192qconf-objs := zconf.tab.o
193
194HOSTLOADLIBES_qconf = $(shell . $(obj)/.qconf-cfg && echo $$libs)
195HOSTCXXFLAGS_qconf.o = $(shell . $(obj)/.qconf-cfg && echo $$cflags)
196
197$(obj)/qconf.o: $(obj)/.qconf-cfg $(obj)/qconf.moc
302 198
303quiet_cmd_moc = MOC $@ 199quiet_cmd_moc = MOC $@
304 cmd_moc = $(KC_QT_MOC) -i $< -o $@ 200 cmd_moc = $(shell . $(obj)/.qconf-cfg && echo $$moc) -i $< -o $@
305 201
306$(obj)/%.moc: $(src)/%.h $(obj)/.tmp_qtcheck 202$(obj)/%.moc: $(src)/%.h $(obj)/.qconf-cfg
307 $(call cmd,moc) 203 $(call cmd,moc)
308 204
309# Extract gconf menu items for i18n support 205# gconf: Used for the gconfig target based on GTK+
310$(obj)/gconf.glade.h: $(obj)/gconf.glade 206hostprogs-y += gconf
311 $(Q)intltool-extract --type=gettext/glade --srcdir=$(srctree) \ 207gconf-objs := gconf.o zconf.tab.o
312 $(obj)/gconf.glade 208
209HOSTLOADLIBES_gconf = $(shell . $(obj)/.gconf-cfg && echo $$libs)
210HOSTCFLAGS_gconf.o = $(shell . $(obj)/.gconf-cfg && echo $$cflags)
211
212$(obj)/gconf.o: $(obj)/.gconf-cfg
213
214$(obj)/zconf.tab.o: $(obj)/zconf.lex.c
215
216# check if necessary packages are available, and configure build flags
217define filechk_conf_cfg
218 $(CONFIG_SHELL) $<
219endef
220
221$(obj)/.%conf-cfg: $(src)/%conf-cfg.sh FORCE
222 $(call filechk,conf_cfg)
223
224clean-files += .*conf-cfg
diff --git a/scripts/kconfig/POTFILES.in b/scripts/kconfig/POTFILES.in
deleted file mode 100644
index 967457396990..000000000000
--- a/scripts/kconfig/POTFILES.in
+++ /dev/null
@@ -1,12 +0,0 @@
1scripts/kconfig/lxdialog/checklist.c
2scripts/kconfig/lxdialog/inputbox.c
3scripts/kconfig/lxdialog/menubox.c
4scripts/kconfig/lxdialog/textbox.c
5scripts/kconfig/lxdialog/util.c
6scripts/kconfig/lxdialog/yesno.c
7scripts/kconfig/mconf.c
8scripts/kconfig/conf.c
9scripts/kconfig/confdata.c
10scripts/kconfig/gconf.c
11scripts/kconfig/gconf.glade.h
12scripts/kconfig/qconf.cc
diff --git a/scripts/kconfig/check.sh b/scripts/kconfig/check.sh
deleted file mode 100755
index 97f0fee7d173..000000000000
--- a/scripts/kconfig/check.sh
+++ /dev/null
@@ -1,14 +0,0 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3# Needed for systems without gettext
4$* -x c -o /dev/null - > /dev/null 2>&1 << EOF
5#include <libintl.h>
6int main()
7{
8 gettext("");
9 return 0;
10}
11EOF
12if [ ! "$?" -eq "0" ]; then
13 echo -DKBUILD_NO_NLS;
14fi
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 283eeedaa4fa..671ff5364497 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -3,7 +3,6 @@
3 * Released under the terms of the GNU GPL v2.0. 3 * Released under the terms of the GNU GPL v2.0.
4 */ 4 */
5 5
6#include <locale.h>
7#include <ctype.h> 6#include <ctype.h>
8#include <limits.h> 7#include <limits.h>
9#include <stdio.h> 8#include <stdio.h>
@@ -86,7 +85,7 @@ static int conf_askvalue(struct symbol *sym, const char *def)
86 enum symbol_type type = sym_get_type(sym); 85 enum symbol_type type = sym_get_type(sym);
87 86
88 if (!sym_has_value(sym)) 87 if (!sym_has_value(sym))
89 printf(_("(NEW) ")); 88 printf("(NEW) ");
90 89
91 line[0] = '\n'; 90 line[0] = '\n';
92 line[1] = 0; 91 line[1] = 0;
@@ -133,7 +132,7 @@ static int conf_string(struct menu *menu)
133 const char *def; 132 const char *def;
134 133
135 while (1) { 134 while (1) {
136 printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); 135 printf("%*s%s ", indent - 1, "", menu->prompt->text);
137 printf("(%s) ", sym->name); 136 printf("(%s) ", sym->name);
138 def = sym_get_string_value(sym); 137 def = sym_get_string_value(sym);
139 if (sym_get_string_value(sym)) 138 if (sym_get_string_value(sym))
@@ -166,7 +165,7 @@ static int conf_sym(struct menu *menu)
166 tristate oldval, newval; 165 tristate oldval, newval;
167 166
168 while (1) { 167 while (1) {
169 printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); 168 printf("%*s%s ", indent - 1, "", menu->prompt->text);
170 if (sym->name) 169 if (sym->name)
171 printf("(%s) ", sym->name); 170 printf("(%s) ", sym->name);
172 putchar('['); 171 putchar('[');
@@ -251,7 +250,7 @@ static int conf_choice(struct menu *menu)
251 case no: 250 case no:
252 return 1; 251 return 1;
253 case mod: 252 case mod:
254 printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); 253 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
255 return 0; 254 return 0;
256 case yes: 255 case yes:
257 break; 256 break;
@@ -261,7 +260,7 @@ static int conf_choice(struct menu *menu)
261 while (1) { 260 while (1) {
262 int cnt, def; 261 int cnt, def;
263 262
264 printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); 263 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
265 def_sym = sym_get_choice_value(sym); 264 def_sym = sym_get_choice_value(sym);
266 cnt = def = 0; 265 cnt = def = 0;
267 line[0] = 0; 266 line[0] = 0;
@@ -269,7 +268,7 @@ static int conf_choice(struct menu *menu)
269 if (!menu_is_visible(child)) 268 if (!menu_is_visible(child))
270 continue; 269 continue;
271 if (!child->sym) { 270 if (!child->sym) {
272 printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); 271 printf("%*c %s\n", indent, '*', menu_get_prompt(child));
273 continue; 272 continue;
274 } 273 }
275 cnt++; 274 cnt++;
@@ -278,14 +277,14 @@ static int conf_choice(struct menu *menu)
278 printf("%*c", indent, '>'); 277 printf("%*c", indent, '>');
279 } else 278 } else
280 printf("%*c", indent, ' '); 279 printf("%*c", indent, ' ');
281 printf(" %d. %s", cnt, _(menu_get_prompt(child))); 280 printf(" %d. %s", cnt, menu_get_prompt(child));
282 if (child->sym->name) 281 if (child->sym->name)
283 printf(" (%s)", child->sym->name); 282 printf(" (%s)", child->sym->name);
284 if (!sym_has_value(child->sym)) 283 if (!sym_has_value(child->sym))
285 printf(_(" (NEW)")); 284 printf(" (NEW)");
286 printf("\n"); 285 printf("\n");
287 } 286 }
288 printf(_("%*schoice"), indent - 1, ""); 287 printf("%*schoice", indent - 1, "");
289 if (cnt == 1) { 288 if (cnt == 1) {
290 printf("[1]: 1\n"); 289 printf("[1]: 1\n");
291 goto conf_childs; 290 goto conf_childs;
@@ -372,7 +371,7 @@ static void conf(struct menu *menu)
372 if (prompt) 371 if (prompt)
373 printf("%*c\n%*c %s\n%*c\n", 372 printf("%*c\n%*c %s\n%*c\n",
374 indent, '*', 373 indent, '*',
375 indent, '*', _(prompt), 374 indent, '*', prompt,
376 indent, '*'); 375 indent, '*');
377 default: 376 default:
378 ; 377 ;
@@ -437,7 +436,7 @@ static void check_conf(struct menu *menu)
437 } 436 }
438 } else { 437 } else {
439 if (!conf_cnt++) 438 if (!conf_cnt++)
440 printf(_("*\n* Restart config...\n*\n")); 439 printf("*\n* Restart config...\n*\n");
441 rootEntry = menu_get_parent_menu(menu); 440 rootEntry = menu_get_parent_menu(menu);
442 conf(rootEntry); 441 conf(rootEntry);
443 } 442 }
@@ -498,10 +497,6 @@ int main(int ac, char **av)
498 const char *name, *defconfig_file = NULL /* gcc uninit */; 497 const char *name, *defconfig_file = NULL /* gcc uninit */;
499 struct stat tmpstat; 498 struct stat tmpstat;
500 499
501 setlocale(LC_ALL, "");
502 bindtextdomain(PACKAGE, LOCALEDIR);
503 textdomain(PACKAGE);
504
505 tty_stdio = isatty(0) && isatty(1); 500 tty_stdio = isatty(0) && isatty(1);
506 501
507 while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) { 502 while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
@@ -559,7 +554,7 @@ int main(int ac, char **av)
559 } 554 }
560 } 555 }
561 if (ac == optind) { 556 if (ac == optind) {
562 fprintf(stderr, _("%s: Kconfig file missing\n"), av[0]); 557 fprintf(stderr, "%s: Kconfig file missing\n", av[0]);
563 conf_usage(progname); 558 conf_usage(progname);
564 exit(1); 559 exit(1);
565 } 560 }
@@ -569,12 +564,12 @@ int main(int ac, char **av)
569 if (sync_kconfig) { 564 if (sync_kconfig) {
570 name = conf_get_configname(); 565 name = conf_get_configname();
571 if (stat(name, &tmpstat)) { 566 if (stat(name, &tmpstat)) {
572 fprintf(stderr, _("***\n" 567 fprintf(stderr, "***\n"
573 "*** Configuration file \"%s\" not found!\n" 568 "*** Configuration file \"%s\" not found!\n"
574 "***\n" 569 "***\n"
575 "*** Please run some configurator (e.g. \"make oldconfig\" or\n" 570 "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
576 "*** \"make menuconfig\" or \"make xconfig\").\n" 571 "*** \"make menuconfig\" or \"make xconfig\").\n"
577 "***\n"), name); 572 "***\n", name);
578 exit(1); 573 exit(1);
579 } 574 }
580 } 575 }
@@ -585,9 +580,9 @@ int main(int ac, char **av)
585 defconfig_file = conf_get_default_confname(); 580 defconfig_file = conf_get_default_confname();
586 if (conf_read(defconfig_file)) { 581 if (conf_read(defconfig_file)) {
587 fprintf(stderr, 582 fprintf(stderr,
588 _("***\n" 583 "***\n"
589 "*** Can't find default configuration \"%s\"!\n" 584 "*** Can't find default configuration \"%s\"!\n"
590 "***\n"), 585 "***\n",
591 defconfig_file); 586 defconfig_file);
592 exit(1); 587 exit(1);
593 } 588 }
@@ -611,7 +606,7 @@ int main(int ac, char **av)
611 if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) { 606 if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
612 if (conf_read_simple(name, S_DEF_USER)) { 607 if (conf_read_simple(name, S_DEF_USER)) {
613 fprintf(stderr, 608 fprintf(stderr,
614 _("*** Can't read seed configuration \"%s\"!\n"), 609 "*** Can't read seed configuration \"%s\"!\n",
615 name); 610 name);
616 exit(1); 611 exit(1);
617 } 612 }
@@ -628,7 +623,7 @@ int main(int ac, char **av)
628 if (conf_read_simple(name, S_DEF_USER) && 623 if (conf_read_simple(name, S_DEF_USER) &&
629 conf_read_simple("all.config", S_DEF_USER)) { 624 conf_read_simple("all.config", S_DEF_USER)) {
630 fprintf(stderr, 625 fprintf(stderr,
631 _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"), 626 "*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n",
632 name); 627 name);
633 exit(1); 628 exit(1);
634 } 629 }
@@ -642,7 +637,7 @@ int main(int ac, char **av)
642 name = getenv("KCONFIG_NOSILENTUPDATE"); 637 name = getenv("KCONFIG_NOSILENTUPDATE");
643 if (name && *name) { 638 if (name && *name) {
644 fprintf(stderr, 639 fprintf(stderr,
645 _("\n*** The configuration requires explicit update.\n\n")); 640 "\n*** The configuration requires explicit update.\n\n");
646 return 1; 641 return 1;
647 } 642 }
648 } 643 }
@@ -694,22 +689,22 @@ int main(int ac, char **av)
694 * All other commands are only used to generate a config. 689 * All other commands are only used to generate a config.
695 */ 690 */
696 if (conf_get_changed() && conf_write(NULL)) { 691 if (conf_get_changed() && conf_write(NULL)) {
697 fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); 692 fprintf(stderr, "\n*** Error during writing of the configuration.\n\n");
698 exit(1); 693 exit(1);
699 } 694 }
700 if (conf_write_autoconf()) { 695 if (conf_write_autoconf()) {
701 fprintf(stderr, _("\n*** Error during update of the configuration.\n\n")); 696 fprintf(stderr, "\n*** Error during update of the configuration.\n\n");
702 return 1; 697 return 1;
703 } 698 }
704 } else if (input_mode == savedefconfig) { 699 } else if (input_mode == savedefconfig) {
705 if (conf_write_defconfig(defconfig_file)) { 700 if (conf_write_defconfig(defconfig_file)) {
706 fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"), 701 fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n",
707 defconfig_file); 702 defconfig_file);
708 return 1; 703 return 1;
709 } 704 }
710 } else if (input_mode != listnewconfig) { 705 } else if (input_mode != listnewconfig) {
711 if (conf_write(NULL)) { 706 if (conf_write(NULL)) {
712 fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); 707 fprintf(stderr, "\n*** Error during writing of the configuration.\n\n");
713 exit(1); 708 exit(1);
714 } 709 }
715 } 710 }
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index df26c7b0fe13..39e20974f4a3 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -30,7 +30,7 @@ static void conf_message(const char *fmt, ...)
30static const char *conf_filename; 30static const char *conf_filename;
31static int conf_lineno, conf_warnings; 31static int conf_lineno, conf_warnings;
32 32
33const char conf_defname[] = "arch/$ARCH/defconfig"; 33const char conf_defname[] = "arch/$(ARCH)/defconfig";
34 34
35static void conf_warning(const char *fmt, ...) 35static void conf_warning(const char *fmt, ...)
36{ 36{
@@ -81,39 +81,13 @@ const char *conf_get_autoconfig_name(void)
81 return name ? name : "include/config/auto.conf"; 81 return name ? name : "include/config/auto.conf";
82} 82}
83 83
84static char *conf_expand_value(const char *in)
85{
86 struct symbol *sym;
87 const char *src;
88 static char res_value[SYMBOL_MAXLENGTH];
89 char *dst, name[SYMBOL_MAXLENGTH];
90
91 res_value[0] = 0;
92 dst = name;
93 while ((src = strchr(in, '$'))) {
94 strncat(res_value, in, src - in);
95 src++;
96 dst = name;
97 while (isalnum(*src) || *src == '_')
98 *dst++ = *src++;
99 *dst = 0;
100 sym = sym_lookup(name, 0);
101 sym_calc_value(sym);
102 strcat(res_value, sym_get_string_value(sym));
103 in = src;
104 }
105 strcat(res_value, in);
106
107 return res_value;
108}
109
110char *conf_get_default_confname(void) 84char *conf_get_default_confname(void)
111{ 85{
112 struct stat buf; 86 struct stat buf;
113 static char fullname[PATH_MAX+1]; 87 static char fullname[PATH_MAX+1];
114 char *env, *name; 88 char *env, *name;
115 89
116 name = conf_expand_value(conf_defname); 90 name = expand_string(conf_defname);
117 env = getenv(SRCTREE); 91 env = getenv(SRCTREE);
118 if (env) { 92 if (env) {
119 sprintf(fullname, "%s/%s", env, name); 93 sprintf(fullname, "%s/%s", env, name);
@@ -274,10 +248,11 @@ int conf_read_simple(const char *name, int def)
274 if (expr_calc_value(prop->visible.expr) == no || 248 if (expr_calc_value(prop->visible.expr) == no ||
275 prop->expr->type != E_SYMBOL) 249 prop->expr->type != E_SYMBOL)
276 continue; 250 continue;
277 name = conf_expand_value(prop->expr->left.sym->name); 251 sym_calc_value(prop->expr->left.sym);
252 name = sym_get_string_value(prop->expr->left.sym);
278 in = zconf_fopen(name); 253 in = zconf_fopen(name);
279 if (in) { 254 if (in) {
280 conf_message(_("using defaults found in %s"), 255 conf_message("using defaults found in %s",
281 name); 256 name);
282 goto load; 257 goto load;
283 } 258 }
@@ -745,7 +720,7 @@ int conf_write(const char *name)
745 struct menu *menu; 720 struct menu *menu;
746 const char *basename; 721 const char *basename;
747 const char *str; 722 const char *str;
748 char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; 723 char dirname[PATH_MAX+1], tmpname[PATH_MAX+22], newname[PATH_MAX+8];
749 char *env; 724 char *env;
750 725
751 dirname[0] = 0; 726 dirname[0] = 0;
@@ -831,7 +806,7 @@ next:
831 return 1; 806 return 1;
832 } 807 }
833 808
834 conf_message(_("configuration written to %s"), newname); 809 conf_message("configuration written to %s", newname);
835 810
836 sym_set_change_count(0); 811 sym_set_change_count(0);
837 812
diff --git a/scripts/kconfig/gconf-cfg.sh b/scripts/kconfig/gconf-cfg.sh
new file mode 100755
index 000000000000..533b3d8f8f08
--- /dev/null
+++ b/scripts/kconfig/gconf-cfg.sh
@@ -0,0 +1,23 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3
4PKG="gtk+-2.0 gmodule-2.0 libglade-2.0"
5
6if ! pkg-config --exists $PKG; then
7 echo >&2 "*"
8 echo >&2 "* Unable to find the GTK+ installation. Please make sure that"
9 echo >&2 "* the GTK+ 2.0 development package is correctly installed."
10 echo >&2 "* You need $PKG"
11 echo >&2 "*"
12 exit 1
13fi
14
15if ! pkg-config --atleast-version=2.0.0 gtk+-2.0; then
16 echo >&2 "*"
17 echo >&2 "* GTK+ is present but version >= 2.0.0 is required."
18 echo >&2 "*"
19 exit 1
20fi
21
22echo cflags=\"$(pkg-config --cflags $PKG)\"
23echo libs=\"$(pkg-config --libs $PKG)\"
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index cfddddb9c9d7..610c4ab54d76 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -137,7 +137,7 @@ void init_main_window(const gchar * glade_file)
137 137
138 xml = glade_xml_new(glade_file, "window1", NULL); 138 xml = glade_xml_new(glade_file, "window1", NULL);
139 if (!xml) 139 if (!xml)
140 g_error(_("GUI loading failed !\n")); 140 g_error("GUI loading failed !\n");
141 glade_xml_signal_autoconnect(xml); 141 glade_xml_signal_autoconnect(xml);
142 142
143 main_wnd = glade_xml_get_widget(xml, "window1"); 143 main_wnd = glade_xml_get_widget(xml, "window1");
@@ -233,7 +233,7 @@ void init_left_tree(void)
233 233
234 column = gtk_tree_view_column_new(); 234 column = gtk_tree_view_column_new();
235 gtk_tree_view_append_column(view, column); 235 gtk_tree_view_append_column(view, column);
236 gtk_tree_view_column_set_title(column, _("Options")); 236 gtk_tree_view_column_set_title(column, "Options");
237 237
238 renderer = gtk_cell_renderer_toggle_new(); 238 renderer = gtk_cell_renderer_toggle_new();
239 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), 239 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
@@ -276,7 +276,7 @@ void init_right_tree(void)
276 276
277 column = gtk_tree_view_column_new(); 277 column = gtk_tree_view_column_new();
278 gtk_tree_view_append_column(view, column); 278 gtk_tree_view_append_column(view, column);
279 gtk_tree_view_column_set_title(column, _("Options")); 279 gtk_tree_view_column_set_title(column, "Options");
280 280
281 renderer = gtk_cell_renderer_pixbuf_new(); 281 renderer = gtk_cell_renderer_pixbuf_new();
282 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), 282 gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
@@ -305,7 +305,7 @@ void init_right_tree(void)
305 305
306 renderer = gtk_cell_renderer_text_new(); 306 renderer = gtk_cell_renderer_text_new();
307 gtk_tree_view_insert_column_with_attributes(view, -1, 307 gtk_tree_view_insert_column_with_attributes(view, -1,
308 _("Name"), renderer, 308 "Name", renderer,
309 "text", COL_NAME, 309 "text", COL_NAME,
310 "foreground-gdk", 310 "foreground-gdk",
311 COL_COLOR, NULL); 311 COL_COLOR, NULL);
@@ -329,7 +329,7 @@ void init_right_tree(void)
329 COL_COLOR, NULL); 329 COL_COLOR, NULL);
330 renderer = gtk_cell_renderer_text_new(); 330 renderer = gtk_cell_renderer_text_new();
331 gtk_tree_view_insert_column_with_attributes(view, -1, 331 gtk_tree_view_insert_column_with_attributes(view, -1,
332 _("Value"), renderer, 332 "Value", renderer,
333 "text", COL_VALUE, 333 "text", COL_VALUE,
334 "editable", 334 "editable",
335 COL_EDIT, 335 COL_EDIT,
@@ -368,7 +368,7 @@ static void text_insert_help(struct menu *menu)
368{ 368{
369 GtkTextBuffer *buffer; 369 GtkTextBuffer *buffer;
370 GtkTextIter start, end; 370 GtkTextIter start, end;
371 const char *prompt = _(menu_get_prompt(menu)); 371 const char *prompt = menu_get_prompt(menu);
372 struct gstr help = str_new(); 372 struct gstr help = str_new();
373 373
374 menu_get_ext_help(menu, &help); 374 menu_get_ext_help(menu, &help);
@@ -422,7 +422,7 @@ gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
422 if (!conf_get_changed()) 422 if (!conf_get_changed())
423 return FALSE; 423 return FALSE;
424 424
425 dialog = gtk_dialog_new_with_buttons(_("Warning !"), 425 dialog = gtk_dialog_new_with_buttons("Warning !",
426 GTK_WINDOW(main_wnd), 426 GTK_WINDOW(main_wnd),
427 (GtkDialogFlags) 427 (GtkDialogFlags)
428 (GTK_DIALOG_MODAL | 428 (GTK_DIALOG_MODAL |
@@ -436,7 +436,7 @@ gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
436 gtk_dialog_set_default_response(GTK_DIALOG(dialog), 436 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
437 GTK_RESPONSE_CANCEL); 437 GTK_RESPONSE_CANCEL);
438 438
439 label = gtk_label_new(_("\nSave configuration ?\n")); 439 label = gtk_label_new("\nSave configuration ?\n");
440 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); 440 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
441 gtk_widget_show(label); 441 gtk_widget_show(label);
442 442
@@ -496,7 +496,7 @@ load_filename(GtkFileSelection * file_selector, gpointer user_data)
496 (user_data)); 496 (user_data));
497 497
498 if (conf_read(fn)) 498 if (conf_read(fn))
499 text_insert_msg(_("Error"), _("Unable to load configuration !")); 499 text_insert_msg("Error", "Unable to load configuration !");
500 else 500 else
501 display_tree(&rootmenu); 501 display_tree(&rootmenu);
502} 502}
@@ -505,7 +505,7 @@ void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
505{ 505{
506 GtkWidget *fs; 506 GtkWidget *fs;
507 507
508 fs = gtk_file_selection_new(_("Load file...")); 508 fs = gtk_file_selection_new("Load file...");
509 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), 509 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
510 "clicked", 510 "clicked",
511 G_CALLBACK(load_filename), (gpointer) fs); 511 G_CALLBACK(load_filename), (gpointer) fs);
@@ -524,7 +524,7 @@ void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
524void on_save_activate(GtkMenuItem * menuitem, gpointer user_data) 524void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
525{ 525{
526 if (conf_write(NULL)) 526 if (conf_write(NULL))
527 text_insert_msg(_("Error"), _("Unable to save configuration !")); 527 text_insert_msg("Error", "Unable to save configuration !");
528} 528}
529 529
530 530
@@ -537,7 +537,7 @@ store_filename(GtkFileSelection * file_selector, gpointer user_data)
537 (user_data)); 537 (user_data));
538 538
539 if (conf_write(fn)) 539 if (conf_write(fn))
540 text_insert_msg(_("Error"), _("Unable to save configuration !")); 540 text_insert_msg("Error", "Unable to save configuration !");
541 541
542 gtk_widget_destroy(GTK_WIDGET(user_data)); 542 gtk_widget_destroy(GTK_WIDGET(user_data));
543} 543}
@@ -546,7 +546,7 @@ void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
546{ 546{
547 GtkWidget *fs; 547 GtkWidget *fs;
548 548
549 fs = gtk_file_selection_new(_("Save file as...")); 549 fs = gtk_file_selection_new("Save file as...");
550 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), 550 g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
551 "clicked", 551 "clicked",
552 G_CALLBACK(store_filename), (gpointer) fs); 552 G_CALLBACK(store_filename), (gpointer) fs);
@@ -639,7 +639,7 @@ on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
639void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) 639void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
640{ 640{
641 GtkWidget *dialog; 641 GtkWidget *dialog;
642 const gchar *intro_text = _( 642 const gchar *intro_text =
643 "Welcome to gkc, the GTK+ graphical configuration tool\n" 643 "Welcome to gkc, the GTK+ graphical configuration tool\n"
644 "For each option, a blank box indicates the feature is disabled, a\n" 644 "For each option, a blank box indicates the feature is disabled, a\n"
645 "check indicates it is enabled, and a dot indicates that it is to\n" 645 "check indicates it is enabled, and a dot indicates that it is to\n"
@@ -654,7 +654,7 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
654 "option.\n" 654 "option.\n"
655 "\n" 655 "\n"
656 "Toggling Show Debug Info under the Options menu will show \n" 656 "Toggling Show Debug Info under the Options menu will show \n"
657 "the dependencies, which you can then match by examining other options."); 657 "the dependencies, which you can then match by examining other options.";
658 658
659 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), 659 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
660 GTK_DIALOG_DESTROY_WITH_PARENT, 660 GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -671,8 +671,8 @@ void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
671{ 671{
672 GtkWidget *dialog; 672 GtkWidget *dialog;
673 const gchar *about_text = 673 const gchar *about_text =
674 _("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n" 674 "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
675 "Based on the source code from Roman Zippel.\n"); 675 "Based on the source code from Roman Zippel.\n";
676 676
677 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), 677 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
678 GTK_DIALOG_DESTROY_WITH_PARENT, 678 GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -689,9 +689,9 @@ void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
689{ 689{
690 GtkWidget *dialog; 690 GtkWidget *dialog;
691 const gchar *license_text = 691 const gchar *license_text =
692 _("gkc is released under the terms of the GNU GPL v2.\n" 692 "gkc is released under the terms of the GNU GPL v2.\n"
693 "For more information, please see the source code or\n" 693 "For more information, please see the source code or\n"
694 "visit http://www.fsf.org/licenses/licenses.html\n"); 694 "visit http://www.fsf.org/licenses/licenses.html\n";
695 695
696 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), 696 dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
697 GTK_DIALOG_DESTROY_WITH_PARENT, 697 GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -1049,7 +1049,7 @@ static gchar **fill_row(struct menu *menu)
1049 bzero(row, sizeof(row)); 1049 bzero(row, sizeof(row));
1050 1050
1051 row[COL_OPTION] = 1051 row[COL_OPTION] =
1052 g_strdup_printf("%s %s", _(menu_get_prompt(menu)), 1052 g_strdup_printf("%s %s", menu_get_prompt(menu),
1053 sym && !sym_has_value(sym) ? "(NEW)" : ""); 1053 sym && !sym_has_value(sym) ? "(NEW)" : "");
1054 1054
1055 if (opt_mode == OPT_ALL && !menu_is_visible(menu)) 1055 if (opt_mode == OPT_ALL && !menu_is_visible(menu))
@@ -1102,7 +1102,7 @@ static gchar **fill_row(struct menu *menu)
1102 1102
1103 if (def_menu) 1103 if (def_menu)
1104 row[COL_VALUE] = 1104 row[COL_VALUE] =
1105 g_strdup(_(menu_get_prompt(def_menu))); 1105 g_strdup(menu_get_prompt(def_menu));
1106 } 1106 }
1107 if (sym->flags & SYMBOL_CHOICEVAL) 1107 if (sym->flags & SYMBOL_CHOICEVAL)
1108 row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); 1108 row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
@@ -1447,10 +1447,6 @@ int main(int ac, char *av[])
1447 char *env; 1447 char *env;
1448 gchar *glade_file; 1448 gchar *glade_file;
1449 1449
1450 bindtextdomain(PACKAGE, LOCALEDIR);
1451 bind_textdomain_codeset(PACKAGE, "UTF-8");
1452 textdomain(PACKAGE);
1453
1454 /* GTK stuffs */ 1450 /* GTK stuffs */
1455 gtk_set_locale(); 1451 gtk_set_locale();
1456 gtk_init(&ac, &av); 1452 gtk_init(&ac, &av);
diff --git a/scripts/kconfig/kconf_id.c b/scripts/kconfig/kconf_id.c
index 3ea9c5f9f730..b3e0ea0ac732 100644
--- a/scripts/kconfig/kconf_id.c
+++ b/scripts/kconfig/kconf_id.c
@@ -32,7 +32,6 @@ static struct kconf_id kconf_id_array[] = {
32 { "on", T_ON, TF_PARAM }, 32 { "on", T_ON, TF_PARAM },
33 { "modules", T_OPT_MODULES, TF_OPTION }, 33 { "modules", T_OPT_MODULES, TF_OPTION },
34 { "defconfig_list", T_OPT_DEFCONFIG_LIST, TF_OPTION }, 34 { "defconfig_list", T_OPT_DEFCONFIG_LIST, TF_OPTION },
35 { "env", T_OPT_ENV, TF_OPTION },
36 { "allnoconfig_y", T_OPT_ALLNOCONFIG_Y, TF_OPTION }, 35 { "allnoconfig_y", T_OPT_ALLNOCONFIG_Y, TF_OPTION },
37}; 36};
38 37
diff --git a/scripts/kconfig/kxgettext.c b/scripts/kconfig/kxgettext.c
deleted file mode 100644
index 240880a89111..000000000000
--- a/scripts/kconfig/kxgettext.c
+++ /dev/null
@@ -1,235 +0,0 @@
1/*
2 * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005
3 *
4 * Released under the terms of the GNU GPL v2.0
5 */
6
7#include <stdlib.h>
8#include <string.h>
9
10#include "lkc.h"
11
12static char *escape(const char* text, char *bf, int len)
13{
14 char *bfp = bf;
15 int multiline = strchr(text, '\n') != NULL;
16 int eol = 0;
17 int textlen = strlen(text);
18
19 if ((textlen > 0) && (text[textlen-1] == '\n'))
20 eol = 1;
21
22 *bfp++ = '"';
23 --len;
24
25 if (multiline) {
26 *bfp++ = '"';
27 *bfp++ = '\n';
28 *bfp++ = '"';
29 len -= 3;
30 }
31
32 while (*text != '\0' && len > 1) {
33 if (*text == '"')
34 *bfp++ = '\\';
35 else if (*text == '\n') {
36 *bfp++ = '\\';
37 *bfp++ = 'n';
38 *bfp++ = '"';
39 *bfp++ = '\n';
40 *bfp++ = '"';
41 len -= 5;
42 ++text;
43 goto next;
44 }
45 else if (*text == '\\') {
46 *bfp++ = '\\';
47 len--;
48 }
49 *bfp++ = *text++;
50next:
51 --len;
52 }
53
54 if (multiline && eol)
55 bfp -= 3;
56
57 *bfp++ = '"';
58 *bfp = '\0';
59
60 return bf;
61}
62
63struct file_line {
64 struct file_line *next;
65 const char *file;
66 int lineno;
67};
68
69static struct file_line *file_line__new(const char *file, int lineno)
70{
71 struct file_line *self = malloc(sizeof(*self));
72
73 if (self == NULL)
74 goto out;
75
76 self->file = file;
77 self->lineno = lineno;
78 self->next = NULL;
79out:
80 return self;
81}
82
83struct message {
84 const char *msg;
85 const char *option;
86 struct message *next;
87 struct file_line *files;
88};
89
90static struct message *message__list;
91
92static struct message *message__new(const char *msg, char *option,
93 const char *file, int lineno)
94{
95 struct message *self = malloc(sizeof(*self));
96
97 if (self == NULL)
98 goto out;
99
100 self->files = file_line__new(file, lineno);
101 if (self->files == NULL)
102 goto out_fail;
103
104 self->msg = xstrdup(msg);
105 if (self->msg == NULL)
106 goto out_fail_msg;
107
108 self->option = option;
109 self->next = NULL;
110out:
111 return self;
112out_fail_msg:
113 free(self->files);
114out_fail:
115 free(self);
116 self = NULL;
117 goto out;
118}
119
120static struct message *mesage__find(const char *msg)
121{
122 struct message *m = message__list;
123
124 while (m != NULL) {
125 if (strcmp(m->msg, msg) == 0)
126 break;
127 m = m->next;
128 }
129
130 return m;
131}
132
133static int message__add_file_line(struct message *self, const char *file,
134 int lineno)
135{
136 int rc = -1;
137 struct file_line *fl = file_line__new(file, lineno);
138
139 if (fl == NULL)
140 goto out;
141
142 fl->next = self->files;
143 self->files = fl;
144 rc = 0;
145out:
146 return rc;
147}
148
149static int message__add(const char *msg, char *option, const char *file,
150 int lineno)
151{
152 int rc = 0;
153 char bf[16384];
154 char *escaped = escape(msg, bf, sizeof(bf));
155 struct message *m = mesage__find(escaped);
156
157 if (m != NULL)
158 rc = message__add_file_line(m, file, lineno);
159 else {
160 m = message__new(escaped, option, file, lineno);
161
162 if (m != NULL) {
163 m->next = message__list;
164 message__list = m;
165 } else
166 rc = -1;
167 }
168 return rc;
169}
170
171static void menu_build_message_list(struct menu *menu)
172{
173 struct menu *child;
174
175 message__add(menu_get_prompt(menu), NULL,
176 menu->file == NULL ? "Root Menu" : menu->file->name,
177 menu->lineno);
178
179 if (menu->sym != NULL && menu_has_help(menu))
180 message__add(menu_get_help(menu), menu->sym->name,
181 menu->file == NULL ? "Root Menu" : menu->file->name,
182 menu->lineno);
183
184 for (child = menu->list; child != NULL; child = child->next)
185 if (child->prompt != NULL)
186 menu_build_message_list(child);
187}
188
189static void message__print_file_lineno(struct message *self)
190{
191 struct file_line *fl = self->files;
192
193 putchar('\n');
194 if (self->option != NULL)
195 printf("# %s:00000\n", self->option);
196
197 printf("#: %s:%d", fl->file, fl->lineno);
198 fl = fl->next;
199
200 while (fl != NULL) {
201 printf(", %s:%d", fl->file, fl->lineno);
202 fl = fl->next;
203 }
204
205 putchar('\n');
206}
207
208static void message__print_gettext_msgid_msgstr(struct message *self)
209{
210 message__print_file_lineno(self);
211
212 printf("msgid %s\n"
213 "msgstr \"\"\n", self->msg);
214}
215
216static void menu__xgettext(void)
217{
218 struct message *m = message__list;
219
220 while (m != NULL) {
221 /* skip empty lines ("") */
222 if (strlen(m->msg) > sizeof("\"\""))
223 message__print_gettext_msgid_msgstr(m);
224 m = m->next;
225 }
226}
227
228int main(int ac, char **av)
229{
230 conf_parse(av[1]);
231
232 menu_build_message_list(menu_get_root_menu(NULL));
233 menu__xgettext();
234 return 0;
235}
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index f4394af6e4b8..ed3ff88e60ba 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -8,15 +8,6 @@
8 8
9#include "expr.h" 9#include "expr.h"
10 10
11#ifndef KBUILD_NO_NLS
12# include <libintl.h>
13#else
14static inline const char *gettext(const char *txt) { return txt; }
15static inline void textdomain(const char *domainname) {}
16static inline void bindtextdomain(const char *name, const char *dir) {}
17static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; }
18#endif
19
20#ifdef __cplusplus 11#ifdef __cplusplus
21extern "C" { 12extern "C" {
22#endif 13#endif
@@ -29,11 +20,6 @@ extern "C" {
29#define PACKAGE "linux" 20#define PACKAGE "linux"
30#endif 21#endif
31 22
32#define LOCALEDIR "/usr/share/locale"
33
34#define _(text) gettext(text)
35#define N_(text) (text)
36
37#ifndef CONFIG_ 23#ifndef CONFIG_
38#define CONFIG_ "CONFIG_" 24#define CONFIG_ "CONFIG_"
39#endif 25#endif
@@ -58,7 +44,6 @@ enum conf_def_mode {
58 44
59#define T_OPT_MODULES 1 45#define T_OPT_MODULES 1
60#define T_OPT_DEFCONFIG_LIST 2 46#define T_OPT_DEFCONFIG_LIST 2
61#define T_OPT_ENV 3
62#define T_OPT_ALLNOCONFIG_Y 4 47#define T_OPT_ALLNOCONFIG_Y 4
63 48
64struct kconf_id { 49struct kconf_id {
@@ -117,6 +102,7 @@ void *xmalloc(size_t size);
117void *xcalloc(size_t nmemb, size_t size); 102void *xcalloc(size_t nmemb, size_t size);
118void *xrealloc(void *p, size_t size); 103void *xrealloc(void *p, size_t size);
119char *xstrdup(const char *s); 104char *xstrdup(const char *s);
105char *xstrndup(const char *s, size_t n);
120 106
121struct gstr { 107struct gstr {
122 size_t len; 108 size_t len;
@@ -134,9 +120,6 @@ void str_printf(struct gstr *gs, const char *fmt, ...);
134const char *str_get(struct gstr *gs); 120const char *str_get(struct gstr *gs);
135 121
136/* symbol.c */ 122/* symbol.c */
137extern struct expr *sym_env_list;
138
139void sym_init(void);
140void sym_clear_all_valid(void); 123void sym_clear_all_valid(void);
141struct symbol *sym_choice_default(struct symbol *sym); 124struct symbol *sym_choice_default(struct symbol *sym);
142const char *sym_get_string_default(struct symbol *sym); 125const char *sym_get_string_default(struct symbol *sym);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 9dc8abfb1dc3..a8b7a330587e 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -31,7 +31,6 @@ extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
31 31
32struct symbol * sym_lookup(const char *name, int flags); 32struct symbol * sym_lookup(const char *name, int flags);
33struct symbol * sym_find(const char *name); 33struct symbol * sym_find(const char *name);
34char *sym_expand_string_value(const char *in);
35const char * sym_escape_string_value(const char *in); 34const char * sym_escape_string_value(const char *in);
36struct symbol ** sym_re_search(const char *pattern); 35struct symbol ** sym_re_search(const char *pattern);
37const char * sym_type_name(enum symbol_type type); 36const char * sym_type_name(enum symbol_type type);
@@ -49,5 +48,19 @@ const char * sym_get_string_value(struct symbol *sym);
49 48
50const char * prop_get_type_name(enum prop_type type); 49const char * prop_get_type_name(enum prop_type type);
51 50
51/* preprocess.c */
52enum variable_flavor {
53 VAR_SIMPLE,
54 VAR_RECURSIVE,
55 VAR_APPEND,
56};
57void env_write_dep(FILE *f, const char *auto_conf_name);
58void variable_add(const char *name, const char *value,
59 enum variable_flavor flavor);
60void variable_all_del(void);
61char *expand_string(const char *in);
62char *expand_dollar(const char **str);
63char *expand_one_token(const char **str);
64
52/* expr.c */ 65/* expr.c */
53void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken); 66void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
deleted file mode 100755
index 6c0bcd9c472d..000000000000
--- a/scripts/kconfig/lxdialog/check-lxdialog.sh
+++ /dev/null
@@ -1,93 +0,0 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3# Check ncurses compatibility
4
5# What library to link
6ldflags()
7{
8 pkg-config --libs ncursesw 2>/dev/null && exit
9 pkg-config --libs ncurses 2>/dev/null && exit
10 for ext in so a dll.a dylib ; do
11 for lib in ncursesw ncurses curses ; do
12 $cc -print-file-name=lib${lib}.${ext} | grep -q /
13 if [ $? -eq 0 ]; then
14 echo "-l${lib}"
15 exit
16 fi
17 done
18 done
19 exit 1
20}
21
22# Where is ncurses.h?
23ccflags()
24{
25 if pkg-config --cflags ncursesw 2>/dev/null; then
26 echo '-DCURSES_LOC="<ncurses.h>" -DNCURSES_WIDECHAR=1'
27 elif pkg-config --cflags ncurses 2>/dev/null; then
28 echo '-DCURSES_LOC="<ncurses.h>"'
29 elif [ -f /usr/include/ncursesw/curses.h ]; then
30 echo '-I/usr/include/ncursesw -DCURSES_LOC="<curses.h>"'
31 echo ' -DNCURSES_WIDECHAR=1'
32 elif [ -f /usr/include/ncurses/ncurses.h ]; then
33 echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
34 elif [ -f /usr/include/ncurses/curses.h ]; then
35 echo '-I/usr/include/ncurses -DCURSES_LOC="<curses.h>"'
36 elif [ -f /usr/include/ncurses.h ]; then
37 echo '-DCURSES_LOC="<ncurses.h>"'
38 else
39 echo '-DCURSES_LOC="<curses.h>"'
40 fi
41}
42
43# Temp file, try to clean up after us
44tmp=.lxdialog.tmp
45trap "rm -f $tmp" 0 1 2 3 15
46
47# Check if we can link to ncurses
48check() {
49 $cc -x c - -o $tmp 2>/dev/null <<'EOF'
50#include CURSES_LOC
51main() {}
52EOF
53 if [ $? != 0 ]; then
54 echo " *** Unable to find the ncurses libraries or the" 1>&2
55 echo " *** required header files." 1>&2
56 echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2
57 echo " *** " 1>&2
58 echo " *** Install ncurses (ncurses-devel or libncurses-dev " 1>&2
59 echo " *** depending on your distribution) and try again." 1>&2
60 echo " *** " 1>&2
61 exit 1
62 fi
63}
64
65usage() {
66 printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n"
67}
68
69if [ $# -eq 0 ]; then
70 usage
71 exit 1
72fi
73
74cc=""
75case "$1" in
76 "-check")
77 shift
78 cc="$@"
79 check
80 ;;
81 "-ccflags")
82 ccflags
83 ;;
84 "-ldflags")
85 shift
86 cc="$@"
87 ldflags
88 ;;
89 "*")
90 usage
91 exit 1
92 ;;
93esac
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
index 8d016faa28d7..2e96323ad11b 100644
--- a/scripts/kconfig/lxdialog/checklist.c
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -103,8 +103,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
103 int x = width / 2 - 11; 103 int x = width / 2 - 11;
104 int y = height - 2; 104 int y = height - 2;
105 105
106 print_button(dialog, gettext("Select"), y, x, selected == 0); 106 print_button(dialog, "Select", y, x, selected == 0);
107 print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); 107 print_button(dialog, " Help ", y, x + 14, selected == 1);
108 108
109 wmove(dialog, y, x + 1 + 14 * selected); 109 wmove(dialog, y, x + 1 + 14 * selected);
110 wrefresh(dialog); 110 wrefresh(dialog);
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
index fcffd5b41fb0..0b00be5abaa6 100644
--- a/scripts/kconfig/lxdialog/dialog.h
+++ b/scripts/kconfig/lxdialog/dialog.h
@@ -26,16 +26,10 @@
26#include <string.h> 26#include <string.h>
27#include <stdbool.h> 27#include <stdbool.h>
28 28
29#ifndef KBUILD_NO_NLS
30# include <libintl.h>
31#else
32# define gettext(Msgid) ((const char *) (Msgid))
33#endif
34
35#ifdef __sun__ 29#ifdef __sun__
36#define CURS_MACROS 30#define CURS_MACROS
37#endif 31#endif
38#include CURSES_LOC 32#include <ncurses.h>
39 33
40/* 34/*
41 * Colors in ncurses 1.9.9e do not work properly since foreground and 35 * Colors in ncurses 1.9.9e do not work properly since foreground and
diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c
index d58de1dc5360..fe82ff6d744e 100644
--- a/scripts/kconfig/lxdialog/inputbox.c
+++ b/scripts/kconfig/lxdialog/inputbox.c
@@ -31,8 +31,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
31 int x = width / 2 - 11; 31 int x = width / 2 - 11;
32 int y = height - 2; 32 int y = height - 2;
33 33
34 print_button(dialog, gettext(" Ok "), y, x, selected == 0); 34 print_button(dialog, " Ok ", y, x, selected == 0);
35 print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); 35 print_button(dialog, " Help ", y, x + 14, selected == 1);
36 36
37 wmove(dialog, y, x + 1 + 14 * selected); 37 wmove(dialog, y, x + 1 + 14 * selected);
38 wrefresh(dialog); 38 wrefresh(dialog);
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
index 11ae9ad7ac7b..d70cab36137e 100644
--- a/scripts/kconfig/lxdialog/menubox.c
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -157,11 +157,11 @@ static void print_buttons(WINDOW * win, int height, int width, int selected)
157 int x = width / 2 - 28; 157 int x = width / 2 - 28;
158 int y = height - 2; 158 int y = height - 2;
159 159
160 print_button(win, gettext("Select"), y, x, selected == 0); 160 print_button(win, "Select", y, x, selected == 0);
161 print_button(win, gettext(" Exit "), y, x + 12, selected == 1); 161 print_button(win, " Exit ", y, x + 12, selected == 1);
162 print_button(win, gettext(" Help "), y, x + 24, selected == 2); 162 print_button(win, " Help ", y, x + 24, selected == 2);
163 print_button(win, gettext(" Save "), y, x + 36, selected == 3); 163 print_button(win, " Save ", y, x + 36, selected == 3);
164 print_button(win, gettext(" Load "), y, x + 48, selected == 4); 164 print_button(win, " Load ", y, x + 48, selected == 4);
165 165
166 wmove(win, y, x + 1 + 12 * selected); 166 wmove(win, y, x + 1 + 12 * selected);
167 wrefresh(win); 167 wrefresh(win);
diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c
index 1773319b95e7..88d2818ed956 100644
--- a/scripts/kconfig/lxdialog/textbox.c
+++ b/scripts/kconfig/lxdialog/textbox.c
@@ -129,7 +129,7 @@ do_resize:
129 129
130 print_title(dialog, title, width); 130 print_title(dialog, title, width);
131 131
132 print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE); 132 print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
133 wnoutrefresh(dialog); 133 wnoutrefresh(dialog);
134 getyx(dialog, cur_y, cur_x); /* Save cursor position */ 134 getyx(dialog, cur_y, cur_x); /* Save cursor position */
135 135
diff --git a/scripts/kconfig/lxdialog/yesno.c b/scripts/kconfig/lxdialog/yesno.c
index 676fb2f824a3..cd1223c903d1 100644
--- a/scripts/kconfig/lxdialog/yesno.c
+++ b/scripts/kconfig/lxdialog/yesno.c
@@ -29,8 +29,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
29 int x = width / 2 - 10; 29 int x = width / 2 - 10;
30 int y = height - 2; 30 int y = height - 2;
31 31
32 print_button(dialog, gettext(" Yes "), y, x, selected == 0); 32 print_button(dialog, " Yes ", y, x, selected == 0);
33 print_button(dialog, gettext(" No "), y, x + 13, selected == 1); 33 print_button(dialog, " No ", y, x + 13, selected == 1);
34 34
35 wmove(dialog, y, x + 1 + 13 * selected); 35 wmove(dialog, y, x + 1 + 13 * selected);
36 wrefresh(dialog); 36 wrefresh(dialog);
diff --git a/scripts/kconfig/mconf-cfg.sh b/scripts/kconfig/mconf-cfg.sh
new file mode 100755
index 000000000000..e6f9facd0077
--- /dev/null
+++ b/scripts/kconfig/mconf-cfg.sh
@@ -0,0 +1,44 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3
4PKG="ncursesw"
5PKG2="ncurses"
6
7if pkg-config --exists $PKG; then
8 echo cflags=\"$(pkg-config --cflags $PKG)\"
9 echo libs=\"$(pkg-config --libs $PKG)\"
10 exit 0
11fi
12
13if pkg-config --exists $PKG2; then
14 echo cflags=\"$(pkg-config --cflags $PKG2)\"
15 echo libs=\"$(pkg-config --libs $PKG2)\"
16 exit 0
17fi
18
19# Unfortunately, some distributions (e.g. openSUSE) cannot find ncurses
20# by pkg-config.
21if [ -f /usr/include/ncursesw/ncurses.h ]; then
22 echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\"
23 echo libs=\"-lncursesw\"
24 exit 0
25fi
26
27if [ -f /usr/include/ncurses/ncurses.h ]; then
28 echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\"
29 echo libs=\"-lncurses\"
30 exit 0
31fi
32
33if [ -f /usr/include/ncurses.h ]; then
34 echo cflags=\"-D_GNU_SOURCE\"
35 echo libs=\"-lncurses\"
36 exit 0
37fi
38
39echo >&2 "*"
40echo >&2 "* Unable to find the ncurses package."
41echo >&2 "* Install ncurses (ncurses-devel or libncurses-dev"
42echo >&2 "* depending on your distribution)."
43echo >&2 "*"
44exit 1
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index c829be8bb19f..5294ed159b98 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -17,12 +17,11 @@
17#include <string.h> 17#include <string.h>
18#include <signal.h> 18#include <signal.h>
19#include <unistd.h> 19#include <unistd.h>
20#include <locale.h>
21 20
22#include "lkc.h" 21#include "lkc.h"
23#include "lxdialog/dialog.h" 22#include "lxdialog/dialog.h"
24 23
25static const char mconf_readme[] = N_( 24static const char mconf_readme[] =
26"Overview\n" 25"Overview\n"
27"--------\n" 26"--------\n"
28"This interface lets you select features and parameters for the build.\n" 27"This interface lets you select features and parameters for the build.\n"
@@ -171,37 +170,37 @@ static const char mconf_readme[] = N_(
171" blackbg => selects a color scheme with black background\n" 170" blackbg => selects a color scheme with black background\n"
172" classic => theme with blue background. The classic look\n" 171" classic => theme with blue background. The classic look\n"
173" bluetitle => an LCD friendly version of classic. (default)\n" 172" bluetitle => an LCD friendly version of classic. (default)\n"
174"\n"), 173"\n",
175menu_instructions[] = N_( 174menu_instructions[] =
176 "Arrow keys navigate the menu. " 175 "Arrow keys navigate the menu. "
177 "<Enter> selects submenus ---> (or empty submenus ----). " 176 "<Enter> selects submenus ---> (or empty submenus ----). "
178 "Highlighted letters are hotkeys. " 177 "Highlighted letters are hotkeys. "
179 "Pressing <Y> includes, <N> excludes, <M> modularizes features. " 178 "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
180 "Press <Esc><Esc> to exit, <?> for Help, </> for Search. " 179 "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
181 "Legend: [*] built-in [ ] excluded <M> module < > module capable"), 180 "Legend: [*] built-in [ ] excluded <M> module < > module capable",
182radiolist_instructions[] = N_( 181radiolist_instructions[] =
183 "Use the arrow keys to navigate this window or " 182 "Use the arrow keys to navigate this window or "
184 "press the hotkey of the item you wish to select " 183 "press the hotkey of the item you wish to select "
185 "followed by the <SPACE BAR>. " 184 "followed by the <SPACE BAR>. "
186 "Press <?> for additional information about this option."), 185 "Press <?> for additional information about this option.",
187inputbox_instructions_int[] = N_( 186inputbox_instructions_int[] =
188 "Please enter a decimal value. " 187 "Please enter a decimal value. "
189 "Fractions will not be accepted. " 188 "Fractions will not be accepted. "
190 "Use the <TAB> key to move from the input field to the buttons below it."), 189 "Use the <TAB> key to move from the input field to the buttons below it.",
191inputbox_instructions_hex[] = N_( 190inputbox_instructions_hex[] =
192 "Please enter a hexadecimal value. " 191 "Please enter a hexadecimal value. "
193 "Use the <TAB> key to move from the input field to the buttons below it."), 192 "Use the <TAB> key to move from the input field to the buttons below it.",
194inputbox_instructions_string[] = N_( 193inputbox_instructions_string[] =
195 "Please enter a string value. " 194 "Please enter a string value. "
196 "Use the <TAB> key to move from the input field to the buttons below it."), 195 "Use the <TAB> key to move from the input field to the buttons below it.",
197setmod_text[] = N_( 196setmod_text[] =
198 "This feature depends on another which has been configured as a module.\n" 197 "This feature depends on another which has been configured as a module.\n"
199 "As a result, this feature will be built as a module."), 198 "As a result, this feature will be built as a module.",
200load_config_text[] = N_( 199load_config_text[] =
201 "Enter the name of the configuration file you wish to load. " 200 "Enter the name of the configuration file you wish to load. "
202 "Accept the name shown to restore the configuration you " 201 "Accept the name shown to restore the configuration you "
203 "last retrieved. Leave blank to abort."), 202 "last retrieved. Leave blank to abort.",
204load_config_help[] = N_( 203load_config_help[] =
205 "\n" 204 "\n"
206 "For various reasons, one may wish to keep several different\n" 205 "For various reasons, one may wish to keep several different\n"
207 "configurations available on a single machine.\n" 206 "configurations available on a single machine.\n"
@@ -211,11 +210,11 @@ load_config_help[] = N_(
211 "configuration.\n" 210 "configuration.\n"
212 "\n" 211 "\n"
213 "If you are uncertain, then you have probably never used alternate\n" 212 "If you are uncertain, then you have probably never used alternate\n"
214 "configuration files. You should therefore leave this blank to abort.\n"), 213 "configuration files. You should therefore leave this blank to abort.\n",
215save_config_text[] = N_( 214save_config_text[] =
216 "Enter a filename to which this configuration should be saved " 215 "Enter a filename to which this configuration should be saved "
217 "as an alternate. Leave blank to abort."), 216 "as an alternate. Leave blank to abort.",
218save_config_help[] = N_( 217save_config_help[] =
219 "\n" 218 "\n"
220 "For various reasons, one may wish to keep different configurations\n" 219 "For various reasons, one may wish to keep different configurations\n"
221 "available on a single machine.\n" 220 "available on a single machine.\n"
@@ -225,8 +224,8 @@ save_config_help[] = N_(
225 "configuration options you have selected at that time.\n" 224 "configuration options you have selected at that time.\n"
226 "\n" 225 "\n"
227 "If you are uncertain what all this means then you should probably\n" 226 "If you are uncertain what all this means then you should probably\n"
228 "leave this blank.\n"), 227 "leave this blank.\n",
229search_help[] = N_( 228search_help[] =
230 "\n" 229 "\n"
231 "Search for symbols and display their relations.\n" 230 "Search for symbols and display their relations.\n"
232 "Regular expressions are allowed.\n" 231 "Regular expressions are allowed.\n"
@@ -271,7 +270,7 @@ search_help[] = N_(
271 "Examples: USB => find all symbols containing USB\n" 270 "Examples: USB => find all symbols containing USB\n"
272 " ^USB => find all symbols starting with USB\n" 271 " ^USB => find all symbols starting with USB\n"
273 " USB$ => find all symbols ending with USB\n" 272 " USB$ => find all symbols ending with USB\n"
274 "\n"); 273 "\n";
275 274
276static int indent; 275static int indent;
277static struct menu *current_menu; 276static struct menu *current_menu;
@@ -400,19 +399,19 @@ static void search_conf(void)
400 struct subtitle_part stpart; 399 struct subtitle_part stpart;
401 400
402 title = str_new(); 401 title = str_new();
403 str_printf( &title, _("Enter (sub)string or regexp to search for " 402 str_printf( &title, "Enter (sub)string or regexp to search for "
404 "(with or without \"%s\")"), CONFIG_); 403 "(with or without \"%s\")", CONFIG_);
405 404
406again: 405again:
407 dialog_clear(); 406 dialog_clear();
408 dres = dialog_inputbox(_("Search Configuration Parameter"), 407 dres = dialog_inputbox("Search Configuration Parameter",
409 str_get(&title), 408 str_get(&title),
410 10, 75, ""); 409 10, 75, "");
411 switch (dres) { 410 switch (dres) {
412 case 0: 411 case 0:
413 break; 412 break;
414 case 1: 413 case 1:
415 show_helptext(_("Search Configuration"), search_help); 414 show_helptext("Search Configuration", search_help);
416 goto again; 415 goto again;
417 default: 416 default:
418 str_free(&title); 417 str_free(&title);
@@ -443,7 +442,7 @@ again:
443 442
444 res = get_relations_str(sym_arr, &head); 443 res = get_relations_str(sym_arr, &head);
445 set_subtitle(); 444 set_subtitle();
446 dres = show_textbox_ext(_("Search Results"), (char *) 445 dres = show_textbox_ext("Search Results", (char *)
447 str_get(&res), 0, 0, keys, &vscroll, 446 str_get(&res), 0, 0, keys, &vscroll,
448 &hscroll, &update_text, (void *) 447 &hscroll, &update_text, (void *)
449 &data); 448 &data);
@@ -491,7 +490,7 @@ static void build_conf(struct menu *menu)
491 switch (prop->type) { 490 switch (prop->type) {
492 case P_MENU: 491 case P_MENU:
493 child_count++; 492 child_count++;
494 prompt = _(prompt); 493 prompt = prompt;
495 if (single_menu_mode) { 494 if (single_menu_mode) {
496 item_make("%s%*c%s", 495 item_make("%s%*c%s",
497 menu->data ? "-->" : "++>", 496 menu->data ? "-->" : "++>",
@@ -508,7 +507,7 @@ static void build_conf(struct menu *menu)
508 case P_COMMENT: 507 case P_COMMENT:
509 if (prompt) { 508 if (prompt) {
510 child_count++; 509 child_count++;
511 item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt)); 510 item_make(" %*c*** %s ***", indent + 1, ' ', prompt);
512 item_set_tag(':'); 511 item_set_tag(':');
513 item_set_data(menu); 512 item_set_data(menu);
514 } 513 }
@@ -516,7 +515,7 @@ static void build_conf(struct menu *menu)
516 default: 515 default:
517 if (prompt) { 516 if (prompt) {
518 child_count++; 517 child_count++;
519 item_make("---%*c%s", indent + 1, ' ', _(prompt)); 518 item_make("---%*c%s", indent + 1, ' ', prompt);
520 item_set_tag(':'); 519 item_set_tag(':');
521 item_set_data(menu); 520 item_set_data(menu);
522 } 521 }
@@ -560,10 +559,10 @@ static void build_conf(struct menu *menu)
560 item_set_data(menu); 559 item_set_data(menu);
561 } 560 }
562 561
563 item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); 562 item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
564 if (val == yes) { 563 if (val == yes) {
565 if (def_menu) { 564 if (def_menu) {
566 item_add_str(" (%s)", _(menu_get_prompt(def_menu))); 565 item_add_str(" (%s)", menu_get_prompt(def_menu));
567 item_add_str(" --->"); 566 item_add_str(" --->");
568 if (def_menu->list) { 567 if (def_menu->list) {
569 indent += 2; 568 indent += 2;
@@ -575,7 +574,7 @@ static void build_conf(struct menu *menu)
575 } 574 }
576 } else { 575 } else {
577 if (menu == current_menu) { 576 if (menu == current_menu) {
578 item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); 577 item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
579 item_set_tag(':'); 578 item_set_tag(':');
580 item_set_data(menu); 579 item_set_data(menu);
581 goto conf_childs; 580 goto conf_childs;
@@ -618,17 +617,17 @@ static void build_conf(struct menu *menu)
618 tmp = indent - tmp + 4; 617 tmp = indent - tmp + 4;
619 if (tmp < 0) 618 if (tmp < 0)
620 tmp = 0; 619 tmp = 0;
621 item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)), 620 item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
622 (sym_has_value(sym) || !sym_is_changable(sym)) ? 621 (sym_has_value(sym) || !sym_is_changable(sym)) ?
623 "" : _(" (NEW)")); 622 "" : " (NEW)");
624 item_set_tag('s'); 623 item_set_tag('s');
625 item_set_data(menu); 624 item_set_data(menu);
626 goto conf_childs; 625 goto conf_childs;
627 } 626 }
628 } 627 }
629 item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)), 628 item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
630 (sym_has_value(sym) || !sym_is_changable(sym)) ? 629 (sym_has_value(sym) || !sym_is_changable(sym)) ?
631 "" : _(" (NEW)")); 630 "" : " (NEW)");
632 if (menu->prompt->type == P_MENU) { 631 if (menu->prompt->type == P_MENU) {
633 item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); 632 item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
634 return; 633 return;
@@ -665,8 +664,8 @@ static void conf(struct menu *menu, struct menu *active_menu)
665 break; 664 break;
666 set_subtitle(); 665 set_subtitle();
667 dialog_clear(); 666 dialog_clear();
668 res = dialog_menu(prompt ? _(prompt) : _("Main Menu"), 667 res = dialog_menu(prompt ? prompt : "Main Menu",
669 _(menu_instructions), 668 menu_instructions,
670 active_menu, &s_scroll); 669 active_menu, &s_scroll);
671 if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) 670 if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
672 break; 671 break;
@@ -708,7 +707,7 @@ static void conf(struct menu *menu, struct menu *active_menu)
708 show_help(submenu); 707 show_help(submenu);
709 else { 708 else {
710 reset_subtitle(); 709 reset_subtitle();
711 show_helptext(_("README"), _(mconf_readme)); 710 show_helptext("README", mconf_readme);
712 } 711 }
713 break; 712 break;
714 case 3: 713 case 3:
@@ -793,13 +792,13 @@ static void show_help(struct menu *menu)
793 help.max_width = getmaxx(stdscr) - 10; 792 help.max_width = getmaxx(stdscr) - 10;
794 menu_get_ext_help(menu, &help); 793 menu_get_ext_help(menu, &help);
795 794
796 show_helptext(_(menu_get_prompt(menu)), str_get(&help)); 795 show_helptext(menu_get_prompt(menu), str_get(&help));
797 str_free(&help); 796 str_free(&help);
798} 797}
799 798
800static void conf_choice(struct menu *menu) 799static void conf_choice(struct menu *menu)
801{ 800{
802 const char *prompt = _(menu_get_prompt(menu)); 801 const char *prompt = menu_get_prompt(menu);
803 struct menu *child; 802 struct menu *child;
804 struct symbol *active; 803 struct symbol *active;
805 804
@@ -814,9 +813,9 @@ static void conf_choice(struct menu *menu)
814 if (!menu_is_visible(child)) 813 if (!menu_is_visible(child))
815 continue; 814 continue;
816 if (child->sym) 815 if (child->sym)
817 item_make("%s", _(menu_get_prompt(child))); 816 item_make("%s", menu_get_prompt(child));
818 else { 817 else {
819 item_make("*** %s ***", _(menu_get_prompt(child))); 818 item_make("*** %s ***", menu_get_prompt(child));
820 item_set_tag(':'); 819 item_set_tag(':');
821 } 820 }
822 item_set_data(child); 821 item_set_data(child);
@@ -826,8 +825,8 @@ static void conf_choice(struct menu *menu)
826 item_set_tag('X'); 825 item_set_tag('X');
827 } 826 }
828 dialog_clear(); 827 dialog_clear();
829 res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), 828 res = dialog_checklist(prompt ? prompt : "Main Menu",
830 _(radiolist_instructions), 829 radiolist_instructions,
831 MENUBOX_HEIGTH_MIN, 830 MENUBOX_HEIGTH_MIN,
832 MENUBOX_WIDTH_MIN, 831 MENUBOX_WIDTH_MIN,
833 CHECKLIST_HEIGTH_MIN); 832 CHECKLIST_HEIGTH_MIN);
@@ -868,26 +867,26 @@ static void conf_string(struct menu *menu)
868 867
869 switch (sym_get_type(menu->sym)) { 868 switch (sym_get_type(menu->sym)) {
870 case S_INT: 869 case S_INT:
871 heading = _(inputbox_instructions_int); 870 heading = inputbox_instructions_int;
872 break; 871 break;
873 case S_HEX: 872 case S_HEX:
874 heading = _(inputbox_instructions_hex); 873 heading = inputbox_instructions_hex;
875 break; 874 break;
876 case S_STRING: 875 case S_STRING:
877 heading = _(inputbox_instructions_string); 876 heading = inputbox_instructions_string;
878 break; 877 break;
879 default: 878 default:
880 heading = _("Internal mconf error!"); 879 heading = "Internal mconf error!";
881 } 880 }
882 dialog_clear(); 881 dialog_clear();
883 res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"), 882 res = dialog_inputbox(prompt ? prompt : "Main Menu",
884 heading, 10, 75, 883 heading, 10, 75,
885 sym_get_string_value(menu->sym)); 884 sym_get_string_value(menu->sym));
886 switch (res) { 885 switch (res) {
887 case 0: 886 case 0:
888 if (sym_set_string_value(menu->sym, dialog_input_result)) 887 if (sym_set_string_value(menu->sym, dialog_input_result))
889 return; 888 return;
890 show_textbox(NULL, _("You have made an invalid entry."), 5, 43); 889 show_textbox(NULL, "You have made an invalid entry.", 5, 43);
891 break; 890 break;
892 case 1: 891 case 1:
893 show_help(menu); 892 show_help(menu);
@@ -915,10 +914,10 @@ static void conf_load(void)
915 sym_set_change_count(1); 914 sym_set_change_count(1);
916 return; 915 return;
917 } 916 }
918 show_textbox(NULL, _("File does not exist!"), 5, 38); 917 show_textbox(NULL, "File does not exist!", 5, 38);
919 break; 918 break;
920 case 1: 919 case 1:
921 show_helptext(_("Load Alternate Configuration"), load_config_help); 920 show_helptext("Load Alternate Configuration", load_config_help);
922 break; 921 break;
923 case KEY_ESC: 922 case KEY_ESC:
924 return; 923 return;
@@ -941,10 +940,10 @@ static void conf_save(void)
941 set_config_filename(dialog_input_result); 940 set_config_filename(dialog_input_result);
942 return; 941 return;
943 } 942 }
944 show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60); 943 show_textbox(NULL, "Can't create file! Probably a nonexistent directory.", 5, 60);
945 break; 944 break;
946 case 1: 945 case 1:
947 show_helptext(_("Save Alternate Configuration"), save_config_help); 946 show_helptext("Save Alternate Configuration", save_config_help);
948 break; 947 break;
949 case KEY_ESC: 948 case KEY_ESC:
950 return; 949 return;
@@ -961,8 +960,8 @@ static int handle_exit(void)
961 dialog_clear(); 960 dialog_clear();
962 if (conf_get_changed()) 961 if (conf_get_changed())
963 res = dialog_yesno(NULL, 962 res = dialog_yesno(NULL,
964 _("Do you wish to save your new configuration?\n" 963 "Do you wish to save your new configuration?\n"
965 "(Press <ESC><ESC> to continue kernel configuration.)"), 964 "(Press <ESC><ESC> to continue kernel configuration.)",
966 6, 60); 965 6, 60);
967 else 966 else
968 res = -1; 967 res = -1;
@@ -972,26 +971,26 @@ static int handle_exit(void)
972 switch (res) { 971 switch (res) {
973 case 0: 972 case 0:
974 if (conf_write(filename)) { 973 if (conf_write(filename)) {
975 fprintf(stderr, _("\n\n" 974 fprintf(stderr, "\n\n"
976 "Error while writing of the configuration.\n" 975 "Error while writing of the configuration.\n"
977 "Your configuration changes were NOT saved." 976 "Your configuration changes were NOT saved."
978 "\n\n")); 977 "\n\n");
979 return 1; 978 return 1;
980 } 979 }
981 /* fall through */ 980 /* fall through */
982 case -1: 981 case -1:
983 if (!silent) 982 if (!silent)
984 printf(_("\n\n" 983 printf("\n\n"
985 "*** End of the configuration.\n" 984 "*** End of the configuration.\n"
986 "*** Execute 'make' to start the build or try 'make help'." 985 "*** Execute 'make' to start the build or try 'make help'."
987 "\n\n")); 986 "\n\n");
988 res = 0; 987 res = 0;
989 break; 988 break;
990 default: 989 default:
991 if (!silent) 990 if (!silent)
992 fprintf(stderr, _("\n\n" 991 fprintf(stderr, "\n\n"
993 "Your configuration changes were NOT saved." 992 "Your configuration changes were NOT saved."
994 "\n\n")); 993 "\n\n");
995 if (res != KEY_ESC) 994 if (res != KEY_ESC)
996 res = 0; 995 res = 0;
997 } 996 }
@@ -1009,10 +1008,6 @@ int main(int ac, char **av)
1009 char *mode; 1008 char *mode;
1010 int res; 1009 int res;
1011 1010
1012 setlocale(LC_ALL, "");
1013 bindtextdomain(PACKAGE, LOCALEDIR);
1014 textdomain(PACKAGE);
1015
1016 signal(SIGINT, sig_handler); 1011 signal(SIGINT, sig_handler);
1017 1012
1018 if (ac > 1 && strcmp(av[1], "-s") == 0) { 1013 if (ac > 1 && strcmp(av[1], "-s") == 0) {
@@ -1031,8 +1026,8 @@ int main(int ac, char **av)
1031 } 1026 }
1032 1027
1033 if (init_dialog(NULL)) { 1028 if (init_dialog(NULL)) {
1034 fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); 1029 fprintf(stderr, "Your display is too small to run Menuconfig!\n");
1035 fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); 1030 fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
1036 return 1; 1031 return 1;
1037 } 1032 }
1038 1033
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 5c5c1374b151..379a119dcd1e 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -214,9 +214,6 @@ void menu_add_option(int token, char *arg)
214 zconf_error("trying to redefine defconfig symbol"); 214 zconf_error("trying to redefine defconfig symbol");
215 sym_defconfig_list->flags |= SYMBOL_AUTO; 215 sym_defconfig_list->flags |= SYMBOL_AUTO;
216 break; 216 break;
217 case T_OPT_ENV:
218 prop_add_env(arg);
219 break;
220 case T_OPT_ALLNOCONFIG_Y: 217 case T_OPT_ALLNOCONFIG_Y:
221 current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y; 218 current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
222 break; 219 break;
@@ -711,7 +708,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
711 struct menu *submenu[8], *menu, *location = NULL; 708 struct menu *submenu[8], *menu, *location = NULL;
712 struct jump_key *jump = NULL; 709 struct jump_key *jump = NULL;
713 710
714 str_printf(r, _("Prompt: %s\n"), _(prop->text)); 711 str_printf(r, "Prompt: %s\n", prop->text);
715 menu = prop->menu->parent; 712 menu = prop->menu->parent;
716 for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) { 713 for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
717 bool accessible = menu_is_visible(menu); 714 bool accessible = menu_is_visible(menu);
@@ -744,16 +741,16 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
744 } 741 }
745 742
746 if (i > 0) { 743 if (i > 0) {
747 str_printf(r, _(" Location:\n")); 744 str_printf(r, " Location:\n");
748 for (j = 4; --i >= 0; j += 2) { 745 for (j = 4; --i >= 0; j += 2) {
749 menu = submenu[i]; 746 menu = submenu[i];
750 if (jump && menu == location) 747 if (jump && menu == location)
751 jump->offset = strlen(r->s); 748 jump->offset = strlen(r->s);
752 str_printf(r, "%*c-> %s", j, ' ', 749 str_printf(r, "%*c-> %s", j, ' ',
753 _(menu_get_prompt(menu))); 750 menu_get_prompt(menu));
754 if (menu->sym) { 751 if (menu->sym) {
755 str_printf(r, " (%s [=%s])", menu->sym->name ? 752 str_printf(r, " (%s [=%s])", menu->sym->name ?
756 menu->sym->name : _("<choice>"), 753 menu->sym->name : "<choice>",
757 sym_get_string_value(menu->sym)); 754 sym_get_string_value(menu->sym));
758 } 755 }
759 str_append(r, "\n"); 756 str_append(r, "\n");
@@ -817,23 +814,23 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
817 814
818 prop = get_symbol_prop(sym); 815 prop = get_symbol_prop(sym);
819 if (prop) { 816 if (prop) {
820 str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, 817 str_printf(r, " Defined at %s:%d\n", prop->menu->file->name,
821 prop->menu->lineno); 818 prop->menu->lineno);
822 if (!expr_is_yes(prop->visible.expr)) { 819 if (!expr_is_yes(prop->visible.expr)) {
823 str_append(r, _(" Depends on: ")); 820 str_append(r, " Depends on: ");
824 expr_gstr_print(prop->visible.expr, r); 821 expr_gstr_print(prop->visible.expr, r);
825 str_append(r, "\n"); 822 str_append(r, "\n");
826 } 823 }
827 } 824 }
828 825
829 get_symbol_props_str(r, sym, P_SELECT, _(" Selects: ")); 826 get_symbol_props_str(r, sym, P_SELECT, " Selects: ");
830 if (sym->rev_dep.expr) { 827 if (sym->rev_dep.expr) {
831 expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, " Selected by [y]:\n"); 828 expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, " Selected by [y]:\n");
832 expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, " Selected by [m]:\n"); 829 expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, " Selected by [m]:\n");
833 expr_gstr_print_revdep(sym->rev_dep.expr, r, no, " Selected by [n]:\n"); 830 expr_gstr_print_revdep(sym->rev_dep.expr, r, no, " Selected by [n]:\n");
834 } 831 }
835 832
836 get_symbol_props_str(r, sym, P_IMPLY, _(" Implies: ")); 833 get_symbol_props_str(r, sym, P_IMPLY, " Implies: ");
837 if (sym->implied.expr) { 834 if (sym->implied.expr) {
838 expr_gstr_print_revdep(sym->implied.expr, r, yes, " Implied by [y]:\n"); 835 expr_gstr_print_revdep(sym->implied.expr, r, yes, " Implied by [y]:\n");
839 expr_gstr_print_revdep(sym->implied.expr, r, mod, " Implied by [m]:\n"); 836 expr_gstr_print_revdep(sym->implied.expr, r, mod, " Implied by [m]:\n");
@@ -852,7 +849,7 @@ struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
852 for (i = 0; sym_arr && (sym = sym_arr[i]); i++) 849 for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
853 get_symbol_str(&res, sym, head); 850 get_symbol_str(&res, sym, head);
854 if (!i) 851 if (!i)
855 str_append(&res, _("No matches found.\n")); 852 str_append(&res, "No matches found.\n");
856 return res; 853 return res;
857} 854}
858 855
@@ -867,7 +864,7 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
867 str_printf(help, "%s%s:\n\n", CONFIG_, sym->name); 864 str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
868 help_text = menu_get_help(menu); 865 help_text = menu_get_help(menu);
869 } 866 }
870 str_printf(help, "%s\n", _(help_text)); 867 str_printf(help, "%s\n", help_text);
871 if (sym) 868 if (sym)
872 get_symbol_str(help, sym, NULL); 869 get_symbol_str(help, sym, NULL);
873} 870}
diff --git a/scripts/kconfig/nconf-cfg.sh b/scripts/kconfig/nconf-cfg.sh
new file mode 100644
index 000000000000..42f5ac73548e
--- /dev/null
+++ b/scripts/kconfig/nconf-cfg.sh
@@ -0,0 +1,44 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3
4PKG="ncursesw menuw panelw"
5PKG2="ncurses menu panel"
6
7if pkg-config --exists $PKG; then
8 echo cflags=\"$(pkg-config --cflags $PKG)\"
9 echo libs=\"$(pkg-config --libs $PKG)\"
10 exit 0
11fi
12
13if pkg-config --exists $PKG2; then
14 echo cflags=\"$(pkg-config --cflags $PKG2)\"
15 echo libs=\"$(pkg-config --libs $PKG2)\"
16 exit 0
17fi
18
19# Unfortunately, some distributions (e.g. openSUSE) cannot find ncurses
20# by pkg-config.
21if [ -f /usr/include/ncursesw/ncurses.h ]; then
22 echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\"
23 echo libs=\"-lncursesw -lmenuw -lpanelw\"
24 exit 0
25fi
26
27if [ -f /usr/include/ncurses/ncurses.h ]; then
28 echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\"
29 echo libs=\"-lncurses -lmenu -lpanel\"
30 exit 0
31fi
32
33if [ -f /usr/include/ncurses.h ]; then
34 echo cflags=\"-D_GNU_SOURCE\"
35 echo libs=\"-lncurses -lmenu -lpanel\"
36 exit 0
37fi
38
39echo >&2 "*"
40echo >&2 "* Unable to find the ncurses package."
41echo >&2 "* Install ncurses (ncurses-devel or libncurses-dev"
42echo >&2 "* depending on your distribution)."
43echo >&2 "*"
44exit 1
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index 003114779815..97b78445584b 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -15,7 +15,7 @@
15#include "nconf.h" 15#include "nconf.h"
16#include <ctype.h> 16#include <ctype.h>
17 17
18static const char nconf_global_help[] = N_( 18static const char nconf_global_help[] =
19"Help windows\n" 19"Help windows\n"
20"------------\n" 20"------------\n"
21"o Global help: Unless in a data entry window, pressing <F1> will give \n" 21"o Global help: Unless in a data entry window, pressing <F1> will give \n"
@@ -130,8 +130,8 @@ static const char nconf_global_help[] = N_(
130"\n" 130"\n"
131"Note that this mode can eventually be a little more CPU expensive than\n" 131"Note that this mode can eventually be a little more CPU expensive than\n"
132"the default mode, especially with a larger number of unfolded submenus.\n" 132"the default mode, especially with a larger number of unfolded submenus.\n"
133"\n"), 133"\n",
134menu_no_f_instructions[] = N_( 134menu_no_f_instructions[] =
135"Legend: [*] built-in [ ] excluded <M> module < > module capable.\n" 135"Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
136"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" 136"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n"
137"\n" 137"\n"
@@ -147,8 +147,8 @@ menu_no_f_instructions[] = N_(
147"You do not have function keys support.\n" 147"You do not have function keys support.\n"
148"Press <1> instead of <F1>, <2> instead of <F2>, etc.\n" 148"Press <1> instead of <F1>, <2> instead of <F2>, etc.\n"
149"For verbose global help use key <1>.\n" 149"For verbose global help use key <1>.\n"
150"For help related to the current menu entry press <?> or <h>.\n"), 150"For help related to the current menu entry press <?> or <h>.\n",
151menu_instructions[] = N_( 151menu_instructions[] =
152"Legend: [*] built-in [ ] excluded <M> module < > module capable.\n" 152"Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
153"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" 153"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n"
154"\n" 154"\n"
@@ -163,30 +163,30 @@ menu_instructions[] = N_(
163"\n" 163"\n"
164"Pressing <1> may be used instead of <F1>, <2> instead of <F2>, etc.\n" 164"Pressing <1> may be used instead of <F1>, <2> instead of <F2>, etc.\n"
165"For verbose global help press <F1>.\n" 165"For verbose global help press <F1>.\n"
166"For help related to the current menu entry press <?> or <h>.\n"), 166"For help related to the current menu entry press <?> or <h>.\n",
167radiolist_instructions[] = N_( 167radiolist_instructions[] =
168"Press <Up>, <Down>, <Home> or <End> to navigate a radiolist, select\n" 168"Press <Up>, <Down>, <Home> or <End> to navigate a radiolist, select\n"
169"with <Space>.\n" 169"with <Space>.\n"
170"For help related to the current entry press <?> or <h>.\n" 170"For help related to the current entry press <?> or <h>.\n"
171"For global help press <F1>.\n"), 171"For global help press <F1>.\n",
172inputbox_instructions_int[] = N_( 172inputbox_instructions_int[] =
173"Please enter a decimal value.\n" 173"Please enter a decimal value.\n"
174"Fractions will not be accepted.\n" 174"Fractions will not be accepted.\n"
175"Press <Enter> to apply, <Esc> to cancel."), 175"Press <Enter> to apply, <Esc> to cancel.",
176inputbox_instructions_hex[] = N_( 176inputbox_instructions_hex[] =
177"Please enter a hexadecimal value.\n" 177"Please enter a hexadecimal value.\n"
178"Press <Enter> to apply, <Esc> to cancel."), 178"Press <Enter> to apply, <Esc> to cancel.",
179inputbox_instructions_string[] = N_( 179inputbox_instructions_string[] =
180"Please enter a string value.\n" 180"Please enter a string value.\n"
181"Press <Enter> to apply, <Esc> to cancel."), 181"Press <Enter> to apply, <Esc> to cancel.",
182setmod_text[] = N_( 182setmod_text[] =
183"This feature depends on another feature which has been configured as a\n" 183"This feature depends on another feature which has been configured as a\n"
184"module. As a result, the current feature will be built as a module too."), 184"module. As a result, the current feature will be built as a module too.",
185load_config_text[] = N_( 185load_config_text[] =
186"Enter the name of the configuration file you wish to load.\n" 186"Enter the name of the configuration file you wish to load.\n"
187"Accept the name shown to restore the configuration you last\n" 187"Accept the name shown to restore the configuration you last\n"
188"retrieved. Leave empty to abort."), 188"retrieved. Leave empty to abort.",
189load_config_help[] = N_( 189load_config_help[] =
190"For various reasons, one may wish to keep several different\n" 190"For various reasons, one may wish to keep several different\n"
191"configurations available on a single machine.\n" 191"configurations available on a single machine.\n"
192"\n" 192"\n"
@@ -194,11 +194,11 @@ load_config_help[] = N_(
194"default one, entering its name here will allow you to load and modify\n" 194"default one, entering its name here will allow you to load and modify\n"
195"that configuration.\n" 195"that configuration.\n"
196"\n" 196"\n"
197"Leave empty to abort.\n"), 197"Leave empty to abort.\n",
198save_config_text[] = N_( 198save_config_text[] =
199"Enter a filename to which this configuration should be saved\n" 199"Enter a filename to which this configuration should be saved\n"
200"as an alternate. Leave empty to abort."), 200"as an alternate. Leave empty to abort.",
201save_config_help[] = N_( 201save_config_help[] =
202"For various reasons, one may wish to keep several different\n" 202"For various reasons, one may wish to keep several different\n"
203"configurations available on a single machine.\n" 203"configurations available on a single machine.\n"
204"\n" 204"\n"
@@ -206,8 +206,8 @@ save_config_help[] = N_(
206"and use the current configuration as an alternate to whatever\n" 206"and use the current configuration as an alternate to whatever\n"
207"configuration options you have selected at that time.\n" 207"configuration options you have selected at that time.\n"
208"\n" 208"\n"
209"Leave empty to abort.\n"), 209"Leave empty to abort.\n",
210search_help[] = N_( 210search_help[] =
211"Search for symbols (configuration variable names CONFIG_*) and display\n" 211"Search for symbols (configuration variable names CONFIG_*) and display\n"
212"their relations. Regular expressions are supported.\n" 212"their relations. Regular expressions are supported.\n"
213"Example: Search for \"^FOO\".\n" 213"Example: Search for \"^FOO\".\n"
@@ -244,7 +244,7 @@ search_help[] = N_(
244"USB => find all symbols containing USB\n" 244"USB => find all symbols containing USB\n"
245"^USB => find all symbols starting with USB\n" 245"^USB => find all symbols starting with USB\n"
246"USB$ => find all symbols ending with USB\n" 246"USB$ => find all symbols ending with USB\n"
247"\n"); 247"\n";
248 248
249struct mitem { 249struct mitem {
250 char str[256]; 250 char str[256];
@@ -388,7 +388,7 @@ static void print_function_line(void)
388static void handle_f1(int *key, struct menu *current_item) 388static void handle_f1(int *key, struct menu *current_item)
389{ 389{
390 show_scroll_win(main_window, 390 show_scroll_win(main_window,
391 _("Global help"), _(nconf_global_help)); 391 "Global help", nconf_global_help);
392 return; 392 return;
393} 393}
394 394
@@ -403,8 +403,8 @@ static void handle_f2(int *key, struct menu *current_item)
403static void handle_f3(int *key, struct menu *current_item) 403static void handle_f3(int *key, struct menu *current_item)
404{ 404{
405 show_scroll_win(main_window, 405 show_scroll_win(main_window,
406 _("Short help"), 406 "Short help",
407 _(current_instructions)); 407 current_instructions);
408 return; 408 return;
409} 409}
410 410
@@ -412,7 +412,7 @@ static void handle_f3(int *key, struct menu *current_item)
412static void handle_f4(int *key, struct menu *current_item) 412static void handle_f4(int *key, struct menu *current_item)
413{ 413{
414 int res = btn_dialog(main_window, 414 int res = btn_dialog(main_window,
415 _("Show all symbols?"), 415 "Show all symbols?",
416 2, 416 2,
417 " <Show All> ", 417 " <Show All> ",
418 "<Don't show all>"); 418 "<Don't show all>");
@@ -653,8 +653,8 @@ static int do_exit(void)
653 return 0; 653 return 0;
654 } 654 }
655 res = btn_dialog(main_window, 655 res = btn_dialog(main_window,
656 _("Do you wish to save your new configuration?\n" 656 "Do you wish to save your new configuration?\n"
657 "<ESC> to cancel and resume nconfig."), 657 "<ESC> to cancel and resume nconfig.",
658 2, 658 2,
659 " <save> ", 659 " <save> ",
660 "<don't save>"); 660 "<don't save>");
@@ -670,15 +670,15 @@ static int do_exit(void)
670 if (res) 670 if (res)
671 btn_dialog( 671 btn_dialog(
672 main_window, 672 main_window,
673 _("Error during writing of configuration.\n" 673 "Error during writing of configuration.\n"
674 "Your configuration changes were NOT saved."), 674 "Your configuration changes were NOT saved.",
675 1, 675 1,
676 "<OK>"); 676 "<OK>");
677 break; 677 break;
678 default: 678 default:
679 btn_dialog( 679 btn_dialog(
680 main_window, 680 main_window,
681 _("Your configuration changes were NOT saved."), 681 "Your configuration changes were NOT saved.",
682 1, 682 1,
683 "<OK>"); 683 "<OK>");
684 break; 684 break;
@@ -697,12 +697,12 @@ static void search_conf(void)
697 int dres; 697 int dres;
698 698
699 title = str_new(); 699 title = str_new();
700 str_printf( &title, _("Enter (sub)string or regexp to search for " 700 str_printf( &title, "Enter (sub)string or regexp to search for "
701 "(with or without \"%s\")"), CONFIG_); 701 "(with or without \"%s\")", CONFIG_);
702 702
703again: 703again:
704 dres = dialog_inputbox(main_window, 704 dres = dialog_inputbox(main_window,
705 _("Search Configuration Parameter"), 705 "Search Configuration Parameter",
706 str_get(&title), 706 str_get(&title),
707 "", &dialog_input_result, &dialog_input_result_len); 707 "", &dialog_input_result, &dialog_input_result_len);
708 switch (dres) { 708 switch (dres) {
@@ -710,7 +710,7 @@ again:
710 break; 710 break;
711 case 1: 711 case 1:
712 show_scroll_win(main_window, 712 show_scroll_win(main_window,
713 _("Search Configuration"), search_help); 713 "Search Configuration", search_help);
714 goto again; 714 goto again;
715 default: 715 default:
716 str_free(&title); 716 str_free(&title);
@@ -726,7 +726,7 @@ again:
726 res = get_relations_str(sym_arr, NULL); 726 res = get_relations_str(sym_arr, NULL);
727 free(sym_arr); 727 free(sym_arr);
728 show_scroll_win(main_window, 728 show_scroll_win(main_window,
729 _("Search Results"), str_get(&res)); 729 "Search Results", str_get(&res));
730 str_free(&res); 730 str_free(&res);
731 str_free(&title); 731 str_free(&title);
732} 732}
@@ -754,7 +754,7 @@ static void build_conf(struct menu *menu)
754 switch (ptype) { 754 switch (ptype) {
755 case P_MENU: 755 case P_MENU:
756 child_count++; 756 child_count++;
757 prompt = _(prompt); 757 prompt = prompt;
758 if (single_menu_mode) { 758 if (single_menu_mode) {
759 item_make(menu, 'm', 759 item_make(menu, 'm',
760 "%s%*c%s", 760 "%s%*c%s",
@@ -775,7 +775,7 @@ static void build_conf(struct menu *menu)
775 item_make(menu, ':', 775 item_make(menu, ':',
776 " %*c*** %s ***", 776 " %*c*** %s ***",
777 indent + 1, ' ', 777 indent + 1, ' ',
778 _(prompt)); 778 prompt);
779 } 779 }
780 break; 780 break;
781 default: 781 default:
@@ -783,7 +783,7 @@ static void build_conf(struct menu *menu)
783 child_count++; 783 child_count++;
784 item_make(menu, ':', "---%*c%s", 784 item_make(menu, ':', "---%*c%s",
785 indent + 1, ' ', 785 indent + 1, ' ',
786 _(prompt)); 786 prompt);
787 } 787 }
788 } 788 }
789 } else 789 } else
@@ -829,11 +829,11 @@ static void build_conf(struct menu *menu)
829 } 829 }
830 830
831 item_add_str("%*c%s", indent + 1, 831 item_add_str("%*c%s", indent + 1,
832 ' ', _(menu_get_prompt(menu))); 832 ' ', menu_get_prompt(menu));
833 if (val == yes) { 833 if (val == yes) {
834 if (def_menu) { 834 if (def_menu) {
835 item_add_str(" (%s)", 835 item_add_str(" (%s)",
836 _(menu_get_prompt(def_menu))); 836 menu_get_prompt(def_menu));
837 item_add_str(" --->"); 837 item_add_str(" --->");
838 if (def_menu->list) { 838 if (def_menu->list) {
839 indent += 2; 839 indent += 2;
@@ -847,7 +847,7 @@ static void build_conf(struct menu *menu)
847 if (menu == current_menu) { 847 if (menu == current_menu) {
848 item_make(menu, ':', 848 item_make(menu, ':',
849 "---%*c%s", indent + 1, 849 "---%*c%s", indent + 1,
850 ' ', _(menu_get_prompt(menu))); 850 ' ', menu_get_prompt(menu));
851 goto conf_childs; 851 goto conf_childs;
852 } 852 }
853 child_count++; 853 child_count++;
@@ -894,17 +894,17 @@ static void build_conf(struct menu *menu)
894 if (tmp < 0) 894 if (tmp < 0)
895 tmp = 0; 895 tmp = 0;
896 item_add_str("%*c%s%s", tmp, ' ', 896 item_add_str("%*c%s%s", tmp, ' ',
897 _(menu_get_prompt(menu)), 897 menu_get_prompt(menu),
898 (sym_has_value(sym) || 898 (sym_has_value(sym) ||
899 !sym_is_changable(sym)) ? "" : 899 !sym_is_changable(sym)) ? "" :
900 _(" (NEW)")); 900 " (NEW)");
901 goto conf_childs; 901 goto conf_childs;
902 } 902 }
903 } 903 }
904 item_add_str("%*c%s%s", indent + 1, ' ', 904 item_add_str("%*c%s%s", indent + 1, ' ',
905 _(menu_get_prompt(menu)), 905 menu_get_prompt(menu),
906 (sym_has_value(sym) || !sym_is_changable(sym)) ? 906 (sym_has_value(sym) || !sym_is_changable(sym)) ?
907 "" : _(" (NEW)")); 907 "" : " (NEW)");
908 if (menu->prompt && menu->prompt->type == P_MENU) { 908 if (menu->prompt && menu->prompt->type == P_MENU) {
909 item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); 909 item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
910 return; 910 return;
@@ -1086,8 +1086,8 @@ static void conf(struct menu *menu)
1086 if (!child_count) 1086 if (!child_count)
1087 break; 1087 break;
1088 1088
1089 show_menu(prompt ? _(prompt) : _("Main Menu"), 1089 show_menu(prompt ? prompt : "Main Menu",
1090 _(menu_instructions), 1090 menu_instructions,
1091 current_index, &last_top_row); 1091 current_index, &last_top_row);
1092 keypad((menu_win(curses_menu)), TRUE); 1092 keypad((menu_win(curses_menu)), TRUE);
1093 while (!global_exit) { 1093 while (!global_exit) {
@@ -1227,13 +1227,13 @@ static void show_help(struct menu *menu)
1227 1227
1228 help = str_new(); 1228 help = str_new();
1229 menu_get_ext_help(menu, &help); 1229 menu_get_ext_help(menu, &help);
1230 show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help)); 1230 show_scroll_win(main_window, menu_get_prompt(menu), str_get(&help));
1231 str_free(&help); 1231 str_free(&help);
1232} 1232}
1233 1233
1234static void conf_choice(struct menu *menu) 1234static void conf_choice(struct menu *menu)
1235{ 1235{
1236 const char *prompt = _(menu_get_prompt(menu)); 1236 const char *prompt = menu_get_prompt(menu);
1237 struct menu *child = NULL; 1237 struct menu *child = NULL;
1238 struct symbol *active; 1238 struct symbol *active;
1239 int selected_index = 0; 1239 int selected_index = 0;
@@ -1256,13 +1256,13 @@ static void conf_choice(struct menu *menu)
1256 1256
1257 if (child->sym == sym_get_choice_value(menu->sym)) 1257 if (child->sym == sym_get_choice_value(menu->sym))
1258 item_make(child, ':', "<X> %s", 1258 item_make(child, ':', "<X> %s",
1259 _(menu_get_prompt(child))); 1259 menu_get_prompt(child));
1260 else if (child->sym) 1260 else if (child->sym)
1261 item_make(child, ':', " %s", 1261 item_make(child, ':', " %s",
1262 _(menu_get_prompt(child))); 1262 menu_get_prompt(child));
1263 else 1263 else
1264 item_make(child, ':', "*** %s ***", 1264 item_make(child, ':', "*** %s ***",
1265 _(menu_get_prompt(child))); 1265 menu_get_prompt(child));
1266 1266
1267 if (child->sym == active){ 1267 if (child->sym == active){
1268 last_top_row = top_row(curses_menu); 1268 last_top_row = top_row(curses_menu);
@@ -1270,8 +1270,8 @@ static void conf_choice(struct menu *menu)
1270 } 1270 }
1271 i++; 1271 i++;
1272 } 1272 }
1273 show_menu(prompt ? _(prompt) : _("Choice Menu"), 1273 show_menu(prompt ? prompt : "Choice Menu",
1274 _(radiolist_instructions), 1274 radiolist_instructions,
1275 selected_index, 1275 selected_index,
1276 &last_top_row); 1276 &last_top_row);
1277 while (!global_exit) { 1277 while (!global_exit) {
@@ -1358,19 +1358,19 @@ static void conf_string(struct menu *menu)
1358 1358
1359 switch (sym_get_type(menu->sym)) { 1359 switch (sym_get_type(menu->sym)) {
1360 case S_INT: 1360 case S_INT:
1361 heading = _(inputbox_instructions_int); 1361 heading = inputbox_instructions_int;
1362 break; 1362 break;
1363 case S_HEX: 1363 case S_HEX:
1364 heading = _(inputbox_instructions_hex); 1364 heading = inputbox_instructions_hex;
1365 break; 1365 break;
1366 case S_STRING: 1366 case S_STRING:
1367 heading = _(inputbox_instructions_string); 1367 heading = inputbox_instructions_string;
1368 break; 1368 break;
1369 default: 1369 default:
1370 heading = _("Internal nconf error!"); 1370 heading = "Internal nconf error!";
1371 } 1371 }
1372 res = dialog_inputbox(main_window, 1372 res = dialog_inputbox(main_window,
1373 prompt ? _(prompt) : _("Main Menu"), 1373 prompt ? prompt : "Main Menu",
1374 heading, 1374 heading,
1375 sym_get_string_value(menu->sym), 1375 sym_get_string_value(menu->sym),
1376 &dialog_input_result, 1376 &dialog_input_result,
@@ -1381,7 +1381,7 @@ static void conf_string(struct menu *menu)
1381 dialog_input_result)) 1381 dialog_input_result))
1382 return; 1382 return;
1383 btn_dialog(main_window, 1383 btn_dialog(main_window,
1384 _("You have made an invalid entry."), 0); 1384 "You have made an invalid entry.", 0);
1385 break; 1385 break;
1386 case 1: 1386 case 1:
1387 show_help(menu); 1387 show_help(menu);
@@ -1410,11 +1410,11 @@ static void conf_load(void)
1410 sym_set_change_count(1); 1410 sym_set_change_count(1);
1411 return; 1411 return;
1412 } 1412 }
1413 btn_dialog(main_window, _("File does not exist!"), 0); 1413 btn_dialog(main_window, "File does not exist!", 0);
1414 break; 1414 break;
1415 case 1: 1415 case 1:
1416 show_scroll_win(main_window, 1416 show_scroll_win(main_window,
1417 _("Load Alternate Configuration"), 1417 "Load Alternate Configuration",
1418 load_config_help); 1418 load_config_help);
1419 break; 1419 break;
1420 case KEY_EXIT: 1420 case KEY_EXIT:
@@ -1441,13 +1441,13 @@ static void conf_save(void)
1441 set_config_filename(dialog_input_result); 1441 set_config_filename(dialog_input_result);
1442 return; 1442 return;
1443 } 1443 }
1444 btn_dialog(main_window, _("Can't create file! " 1444 btn_dialog(main_window, "Can't create file! "
1445 "Probably a nonexistent directory."), 1445 "Probably a nonexistent directory.",
1446 1, "<OK>"); 1446 1, "<OK>");
1447 break; 1447 break;
1448 case 1: 1448 case 1:
1449 show_scroll_win(main_window, 1449 show_scroll_win(main_window,
1450 _("Save Alternate Configuration"), 1450 "Save Alternate Configuration",
1451 save_config_help); 1451 save_config_help);
1452 break; 1452 break;
1453 case KEY_EXIT: 1453 case KEY_EXIT:
@@ -1480,10 +1480,6 @@ int main(int ac, char **av)
1480 int lines, columns; 1480 int lines, columns;
1481 char *mode; 1481 char *mode;
1482 1482
1483 setlocale(LC_ALL, "");
1484 bindtextdomain(PACKAGE, LOCALEDIR);
1485 textdomain(PACKAGE);
1486
1487 if (ac > 1 && strcmp(av[1], "-s") == 0) { 1483 if (ac > 1 && strcmp(av[1], "-s") == 0) {
1488 /* Silence conf_read() until the real callback is set up */ 1484 /* Silence conf_read() until the real callback is set up */
1489 conf_set_message_callback(NULL); 1485 conf_set_message_callback(NULL);
@@ -1541,8 +1537,8 @@ int main(int ac, char **av)
1541 /* check for KEY_FUNC(1) */ 1537 /* check for KEY_FUNC(1) */
1542 if (has_key(KEY_F(1)) == FALSE) { 1538 if (has_key(KEY_F(1)) == FALSE) {
1543 show_scroll_win(main_window, 1539 show_scroll_win(main_window,
1544 _("Instructions"), 1540 "Instructions",
1545 _(menu_no_f_instructions)); 1541 menu_no_f_instructions);
1546 } 1542 }
1547 1543
1548 conf_set_message_callback(conf_message_callback); 1544 conf_set_message_callback(conf_message_callback);
diff --git a/scripts/kconfig/nconf.h b/scripts/kconfig/nconf.h
index 9f6f21d3b0d4..2b9e19f603c4 100644
--- a/scripts/kconfig/nconf.h
+++ b/scripts/kconfig/nconf.h
@@ -14,7 +14,6 @@
14#include <stdlib.h> 14#include <stdlib.h>
15#include <string.h> 15#include <string.h>
16#include <unistd.h> 16#include <unistd.h>
17#include <locale.h>
18#include <ncurses.h> 17#include <ncurses.h>
19#include <menu.h> 18#include <menu.h>
20#include <panel.h> 19#include <panel.h>
diff --git a/scripts/kconfig/preprocess.c b/scripts/kconfig/preprocess.c
new file mode 100644
index 000000000000..65da87fce907
--- /dev/null
+++ b/scripts/kconfig/preprocess.c
@@ -0,0 +1,572 @@
1// SPDX-License-Identifier: GPL-2.0
2//
3// Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com>
4
5#include <stdarg.h>
6#include <stdbool.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include "list.h"
12
13#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
14
15static char *expand_string_with_args(const char *in, int argc, char *argv[]);
16
17static void __attribute__((noreturn)) pperror(const char *format, ...)
18{
19 va_list ap;
20
21 fprintf(stderr, "%s:%d: ", current_file->name, yylineno);
22 va_start(ap, format);
23 vfprintf(stderr, format, ap);
24 va_end(ap);
25 fprintf(stderr, "\n");
26
27 exit(1);
28}
29
30/*
31 * Environment variables
32 */
33static LIST_HEAD(env_list);
34
35struct env {
36 char *name;
37 char *value;
38 struct list_head node;
39};
40
41static void env_add(const char *name, const char *value)
42{
43 struct env *e;
44
45 e = xmalloc(sizeof(*e));
46 e->name = xstrdup(name);
47 e->value = xstrdup(value);
48
49 list_add_tail(&e->node, &env_list);
50}
51
52static void env_del(struct env *e)
53{
54 list_del(&e->node);
55 free(e->name);
56 free(e->value);
57 free(e);
58}
59
60/* The returned pointer must be freed when done */
61static char *env_expand(const char *name)
62{
63 struct env *e;
64 const char *value;
65
66 if (!*name)
67 return NULL;
68
69 list_for_each_entry(e, &env_list, node) {
70 if (!strcmp(name, e->name))
71 return xstrdup(e->value);
72 }
73
74 value = getenv(name);
75 if (!value)
76 return NULL;
77
78 /*
79 * We need to remember all referenced environment variables.
80 * They will be written out to include/config/auto.conf.cmd
81 */
82 env_add(name, value);
83
84 return xstrdup(value);
85}
86
87void env_write_dep(FILE *f, const char *autoconfig_name)
88{
89 struct env *e, *tmp;
90
91 list_for_each_entry_safe(e, tmp, &env_list, node) {
92 fprintf(f, "ifneq \"$(%s)\" \"%s\"\n", e->name, e->value);
93 fprintf(f, "%s: FORCE\n", autoconfig_name);
94 fprintf(f, "endif\n");
95 env_del(e);
96 }
97}
98
99/*
100 * Built-in functions
101 */
102struct function {
103 const char *name;
104 unsigned int min_args;
105 unsigned int max_args;
106 char *(*func)(int argc, char *argv[]);
107};
108
109static char *do_error_if(int argc, char *argv[])
110{
111 if (!strcmp(argv[0], "y"))
112 pperror("%s", argv[1]);
113
114 return NULL;
115}
116
117static char *do_filename(int argc, char *argv[])
118{
119 return xstrdup(current_file->name);
120}
121
122static char *do_info(int argc, char *argv[])
123{
124 printf("%s\n", argv[0]);
125
126 return xstrdup("");
127}
128
129static char *do_lineno(int argc, char *argv[])
130{
131 char buf[16];
132
133 sprintf(buf, "%d", yylineno);
134
135 return xstrdup(buf);
136}
137
138static char *do_shell(int argc, char *argv[])
139{
140 FILE *p;
141 char buf[256];
142 char *cmd;
143 size_t nread;
144 int i;
145
146 cmd = argv[0];
147
148 p = popen(cmd, "r");
149 if (!p) {
150 perror(cmd);
151 exit(1);
152 }
153
154 nread = fread(buf, 1, sizeof(buf), p);
155 if (nread == sizeof(buf))
156 nread--;
157
158 /* remove trailing new lines */
159 while (buf[nread - 1] == '\n')
160 nread--;
161
162 buf[nread] = 0;
163
164 /* replace a new line with a space */
165 for (i = 0; i < nread; i++) {
166 if (buf[i] == '\n')
167 buf[i] = ' ';
168 }
169
170 if (pclose(p) == -1) {
171 perror(cmd);
172 exit(1);
173 }
174
175 return xstrdup(buf);
176}
177
178static char *do_warning_if(int argc, char *argv[])
179{
180 if (!strcmp(argv[0], "y"))
181 fprintf(stderr, "%s:%d: %s\n",
182 current_file->name, yylineno, argv[1]);
183
184 return xstrdup("");
185}
186
187static const struct function function_table[] = {
188 /* Name MIN MAX Function */
189 { "error-if", 2, 2, do_error_if },
190 { "filename", 0, 0, do_filename },
191 { "info", 1, 1, do_info },
192 { "lineno", 0, 0, do_lineno },
193 { "shell", 1, 1, do_shell },
194 { "warning-if", 2, 2, do_warning_if },
195};
196
197#define FUNCTION_MAX_ARGS 16
198
199static char *function_expand(const char *name, int argc, char *argv[])
200{
201 const struct function *f;
202 int i;
203
204 for (i = 0; i < ARRAY_SIZE(function_table); i++) {
205 f = &function_table[i];
206 if (strcmp(f->name, name))
207 continue;
208
209 if (argc < f->min_args)
210 pperror("too few function arguments passed to '%s'",
211 name);
212
213 if (argc > f->max_args)
214 pperror("too many function arguments passed to '%s'",
215 name);
216
217 return f->func(argc, argv);
218 }
219
220 return NULL;
221}
222
223/*
224 * Variables (and user-defined functions)
225 */
226static LIST_HEAD(variable_list);
227
228struct variable {
229 char *name;
230 char *value;
231 enum variable_flavor flavor;
232 int exp_count;
233 struct list_head node;
234};
235
236static struct variable *variable_lookup(const char *name)
237{
238 struct variable *v;
239
240 list_for_each_entry(v, &variable_list, node) {
241 if (!strcmp(name, v->name))
242 return v;
243 }
244
245 return NULL;
246}
247
248static char *variable_expand(const char *name, int argc, char *argv[])
249{
250 struct variable *v;
251 char *res;
252
253 v = variable_lookup(name);
254 if (!v)
255 return NULL;
256
257 if (argc == 0 && v->exp_count)
258 pperror("Recursive variable '%s' references itself (eventually)",
259 name);
260
261 if (v->exp_count > 1000)
262 pperror("Too deep recursive expansion");
263
264 v->exp_count++;
265
266 if (v->flavor == VAR_RECURSIVE)
267 res = expand_string_with_args(v->value, argc, argv);
268 else
269 res = xstrdup(v->value);
270
271 v->exp_count--;
272
273 return res;
274}
275
276void variable_add(const char *name, const char *value,
277 enum variable_flavor flavor)
278{
279 struct variable *v;
280 char *new_value;
281 bool append = false;
282
283 v = variable_lookup(name);
284 if (v) {
285 /* For defined variables, += inherits the existing flavor */
286 if (flavor == VAR_APPEND) {
287 flavor = v->flavor;
288 append = true;
289 } else {
290 free(v->value);
291 }
292 } else {
293 /* For undefined variables, += assumes the recursive flavor */
294 if (flavor == VAR_APPEND)
295 flavor = VAR_RECURSIVE;
296
297 v = xmalloc(sizeof(*v));
298 v->name = xstrdup(name);
299 v->exp_count = 0;
300 list_add_tail(&v->node, &variable_list);
301 }
302
303 v->flavor = flavor;
304
305 if (flavor == VAR_SIMPLE)
306 new_value = expand_string(value);
307 else
308 new_value = xstrdup(value);
309
310 if (append) {
311 v->value = xrealloc(v->value,
312 strlen(v->value) + strlen(new_value) + 2);
313 strcat(v->value, " ");
314 strcat(v->value, new_value);
315 free(new_value);
316 } else {
317 v->value = new_value;
318 }
319}
320
321static void variable_del(struct variable *v)
322{
323 list_del(&v->node);
324 free(v->name);
325 free(v->value);
326 free(v);
327}
328
329void variable_all_del(void)
330{
331 struct variable *v, *tmp;
332
333 list_for_each_entry_safe(v, tmp, &variable_list, node)
334 variable_del(v);
335}
336
337/*
338 * Evaluate a clause with arguments. argc/argv are arguments from the upper
339 * function call.
340 *
341 * Returned string must be freed when done
342 */
343static char *eval_clause(const char *str, size_t len, int argc, char *argv[])
344{
345 char *tmp, *name, *res, *endptr, *prev, *p;
346 int new_argc = 0;
347 char *new_argv[FUNCTION_MAX_ARGS];
348 int nest = 0;
349 int i;
350 unsigned long n;
351
352 tmp = xstrndup(str, len);
353
354 /*
355 * If variable name is '1', '2', etc. It is generally an argument
356 * from a user-function call (i.e. local-scope variable). If not
357 * available, then look-up global-scope variables.
358 */
359 n = strtoul(tmp, &endptr, 10);
360 if (!*endptr && n > 0 && n <= argc) {
361 res = xstrdup(argv[n - 1]);
362 goto free_tmp;
363 }
364
365 prev = p = tmp;
366
367 /*
368 * Split into tokens
369 * The function name and arguments are separated by a comma.
370 * For example, if the function call is like this:
371 * $(foo,$(x),$(y))
372 *
373 * The input string for this helper should be:
374 * foo,$(x),$(y)
375 *
376 * and split into:
377 * new_argv[0] = 'foo'
378 * new_argv[1] = '$(x)'
379 * new_argv[2] = '$(y)'
380 */
381 while (*p) {
382 if (nest == 0 && *p == ',') {
383 *p = 0;
384 if (new_argc >= FUNCTION_MAX_ARGS)
385 pperror("too many function arguments");
386 new_argv[new_argc++] = prev;
387 prev = p + 1;
388 } else if (*p == '(') {
389 nest++;
390 } else if (*p == ')') {
391 nest--;
392 }
393
394 p++;
395 }
396 new_argv[new_argc++] = prev;
397
398 /*
399 * Shift arguments
400 * new_argv[0] represents a function name or a variable name. Put it
401 * into 'name', then shift the rest of the arguments. This simplifies
402 * 'const' handling.
403 */
404 name = expand_string_with_args(new_argv[0], argc, argv);
405 new_argc--;
406 for (i = 0; i < new_argc; i++)
407 new_argv[i] = expand_string_with_args(new_argv[i + 1],
408 argc, argv);
409
410 /* Search for variables */
411 res = variable_expand(name, new_argc, new_argv);
412 if (res)
413 goto free;
414
415 /* Look for built-in functions */
416 res = function_expand(name, new_argc, new_argv);
417 if (res)
418 goto free;
419
420 /* Last, try environment variable */
421 if (new_argc == 0) {
422 res = env_expand(name);
423 if (res)
424 goto free;
425 }
426
427 res = xstrdup("");
428free:
429 for (i = 0; i < new_argc; i++)
430 free(new_argv[i]);
431 free(name);
432free_tmp:
433 free(tmp);
434
435 return res;
436}
437
438/*
439 * Expand a string that follows '$'
440 *
441 * For example, if the input string is
442 * ($(FOO)$($(BAR)))$(BAZ)
443 * this helper evaluates
444 * $($(FOO)$($(BAR)))
445 * and returns a new string containing the expansion (note that the string is
446 * recursively expanded), also advancing 'str' to point to the next character
447 * after the corresponding closing parenthesis, in this case, *str will be
448 * $(BAR)
449 */
450static char *expand_dollar_with_args(const char **str, int argc, char *argv[])
451{
452 const char *p = *str;
453 const char *q;
454 int nest = 0;
455
456 /*
457 * In Kconfig, variable/function references always start with "$(".
458 * Neither single-letter variables as in $A nor curly braces as in ${CC}
459 * are supported. '$' not followed by '(' loses its special meaning.
460 */
461 if (*p != '(') {
462 *str = p;
463 return xstrdup("$");
464 }
465
466 p++;
467 q = p;
468 while (*q) {
469 if (*q == '(') {
470 nest++;
471 } else if (*q == ')') {
472 if (nest-- == 0)
473 break;
474 }
475 q++;
476 }
477
478 if (!*q)
479 pperror("unterminated reference to '%s': missing ')'", p);
480
481 /* Advance 'str' to after the expanded initial portion of the string */
482 *str = q + 1;
483
484 return eval_clause(p, q - p, argc, argv);
485}
486
487char *expand_dollar(const char **str)
488{
489 return expand_dollar_with_args(str, 0, NULL);
490}
491
492static char *__expand_string(const char **str, bool (*is_end)(char c),
493 int argc, char *argv[])
494{
495 const char *in, *p;
496 char *expansion, *out;
497 size_t in_len, out_len;
498
499 out = xmalloc(1);
500 *out = 0;
501 out_len = 1;
502
503 p = in = *str;
504
505 while (1) {
506 if (*p == '$') {
507 in_len = p - in;
508 p++;
509 expansion = expand_dollar_with_args(&p, argc, argv);
510 out_len += in_len + strlen(expansion);
511 out = xrealloc(out, out_len);
512 strncat(out, in, in_len);
513 strcat(out, expansion);
514 free(expansion);
515 in = p;
516 continue;
517 }
518
519 if (is_end(*p))
520 break;
521
522 p++;
523 }
524
525 in_len = p - in;
526 out_len += in_len;
527 out = xrealloc(out, out_len);
528 strncat(out, in, in_len);
529
530 /* Advance 'str' to the end character */
531 *str = p;
532
533 return out;
534}
535
536static bool is_end_of_str(char c)
537{
538 return !c;
539}
540
541/*
542 * Expand variables and functions in the given string. Undefined variables
543 * expand to an empty string.
544 * The returned string must be freed when done.
545 */
546static char *expand_string_with_args(const char *in, int argc, char *argv[])
547{
548 return __expand_string(&in, is_end_of_str, argc, argv);
549}
550
551char *expand_string(const char *in)
552{
553 return expand_string_with_args(in, 0, NULL);
554}
555
556static bool is_end_of_token(char c)
557{
558 /* Why are '.' and '/' valid characters for symbols? */
559 return !(isalnum(c) || c == '_' || c == '-' || c == '.' || c == '/');
560}
561
562/*
563 * Expand variables in a token. The parsing stops when a token separater
564 * (in most cases, it is a whitespace) is encountered. 'str' is updated to
565 * point to the next character.
566 *
567 * The returned string must be freed when done.
568 */
569char *expand_one_token(const char **str)
570{
571 return __expand_string(str, is_end_of_token, 0, NULL);
572}
diff --git a/scripts/kconfig/qconf-cfg.sh b/scripts/kconfig/qconf-cfg.sh
new file mode 100755
index 000000000000..0862e1562536
--- /dev/null
+++ b/scripts/kconfig/qconf-cfg.sh
@@ -0,0 +1,25 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3
4PKG="Qt5Core Qt5Gui Qt5Widgets"
5PKG2="QtCore QtGui"
6
7if pkg-config --exists $PKG; then
8 echo cflags=\"-std=c++11 -fPIC $(pkg-config --cflags Qt5Core Qt5Gui Qt5Widgets)\"
9 echo libs=\"$(pkg-config --libs $PKG)\"
10 echo moc=\"$(pkg-config --variable=host_bins Qt5Core)/moc\"
11 exit 0
12fi
13
14if pkg-config --exists $PKG2; then
15 echo cflags=\"$(pkg-config --cflags $PKG2)\"
16 echo libs=\"$(pkg-config --libs $PKG2)\"
17 echo moc=\"$(pkg-config --variable=moc_location QtCore)\"
18 exit 0
19fi
20
21echo >&2 "*"
22echo >&2 "* Could not find Qt via pkg-config."
23echo >&2 "* Please install either Qt 4.8 or 5.x. and make sure it's in PKG_CONFIG_PATH"
24echo >&2 "*"
25exit 1
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index ae6c72546411..ad9c22dd04f5 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -34,10 +34,6 @@
34#include "qconf.moc" 34#include "qconf.moc"
35#include "images.c" 35#include "images.c"
36 36
37#ifdef _
38# undef _
39# define _ qgettext
40#endif
41 37
42static QApplication *configApp; 38static QApplication *configApp;
43static ConfigSettings *configSettings; 39static ConfigSettings *configSettings;
@@ -46,12 +42,7 @@ QAction *ConfigMainWindow::saveAction;
46 42
47static inline QString qgettext(const char* str) 43static inline QString qgettext(const char* str)
48{ 44{
49 return QString::fromLocal8Bit(gettext(str)); 45 return QString::fromLocal8Bit(str);
50}
51
52static inline QString qgettext(const QString& str)
53{
54 return QString::fromLocal8Bit(gettext(str.toLatin1()));
55} 46}
56 47
57ConfigSettings::ConfigSettings() 48ConfigSettings::ConfigSettings()
@@ -127,7 +118,7 @@ void ConfigItem::updateMenu(void)
127 118
128 sym = menu->sym; 119 sym = menu->sym;
129 prop = menu->prompt; 120 prop = menu->prompt;
130 prompt = _(menu_get_prompt(menu)); 121 prompt = qgettext(menu_get_prompt(menu));
131 122
132 if (prop) switch (prop->type) { 123 if (prop) switch (prop->type) {
133 case P_MENU: 124 case P_MENU:
@@ -216,7 +207,7 @@ void ConfigItem::updateMenu(void)
216 break; 207 break;
217 } 208 }
218 if (!sym_has_value(sym) && visible) 209 if (!sym_has_value(sym) && visible)
219 prompt += _(" (NEW)"); 210 prompt += " (NEW)";
220set_prompt: 211set_prompt:
221 setText(promptColIdx, prompt); 212 setText(promptColIdx, prompt);
222} 213}
@@ -327,7 +318,7 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
327 setVerticalScrollMode(ScrollPerPixel); 318 setVerticalScrollMode(ScrollPerPixel);
328 setHorizontalScrollMode(ScrollPerPixel); 319 setHorizontalScrollMode(ScrollPerPixel);
329 320
330 setHeaderLabels(QStringList() << _("Option") << _("Name") << "N" << "M" << "Y" << _("Value")); 321 setHeaderLabels(QStringList() << "Option" << "Name" << "N" << "M" << "Y" << "Value");
331 322
332 connect(this, SIGNAL(itemSelectionChanged(void)), 323 connect(this, SIGNAL(itemSelectionChanged(void)),
333 SLOT(updateSelection(void))); 324 SLOT(updateSelection(void)));
@@ -883,7 +874,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
883 QAction *action; 874 QAction *action;
884 875
885 headerPopup = new QMenu(this); 876 headerPopup = new QMenu(this);
886 action = new QAction(_("Show Name"), this); 877 action = new QAction("Show Name", this);
887 action->setCheckable(true); 878 action->setCheckable(true);
888 connect(action, SIGNAL(toggled(bool)), 879 connect(action, SIGNAL(toggled(bool)),
889 parent(), SLOT(setShowName(bool))); 880 parent(), SLOT(setShowName(bool)));
@@ -891,7 +882,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
891 action, SLOT(setOn(bool))); 882 action, SLOT(setOn(bool)));
892 action->setChecked(showName); 883 action->setChecked(showName);
893 headerPopup->addAction(action); 884 headerPopup->addAction(action);
894 action = new QAction(_("Show Range"), this); 885 action = new QAction("Show Range", this);
895 action->setCheckable(true); 886 action->setCheckable(true);
896 connect(action, SIGNAL(toggled(bool)), 887 connect(action, SIGNAL(toggled(bool)),
897 parent(), SLOT(setShowRange(bool))); 888 parent(), SLOT(setShowRange(bool)));
@@ -899,7 +890,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
899 action, SLOT(setOn(bool))); 890 action, SLOT(setOn(bool)));
900 action->setChecked(showRange); 891 action->setChecked(showRange);
901 headerPopup->addAction(action); 892 headerPopup->addAction(action);
902 action = new QAction(_("Show Data"), this); 893 action = new QAction("Show Data", this);
903 action->setCheckable(true); 894 action->setCheckable(true);
904 connect(action, SIGNAL(toggled(bool)), 895 connect(action, SIGNAL(toggled(bool)),
905 parent(), SLOT(setShowData(bool))); 896 parent(), SLOT(setShowData(bool)));
@@ -1086,7 +1077,7 @@ void ConfigInfoView::menuInfo(void)
1086 if (sym) { 1077 if (sym) {
1087 if (_menu->prompt) { 1078 if (_menu->prompt) {
1088 head += "<big><b>"; 1079 head += "<big><b>";
1089 head += print_filter(_(_menu->prompt->text)); 1080 head += print_filter(_menu->prompt->text);
1090 head += "</b></big>"; 1081 head += "</b></big>";
1091 if (sym->name) { 1082 if (sym->name) {
1092 head += " ("; 1083 head += " (";
@@ -1117,7 +1108,7 @@ void ConfigInfoView::menuInfo(void)
1117 str_free(&help_gstr); 1108 str_free(&help_gstr);
1118 } else if (_menu->prompt) { 1109 } else if (_menu->prompt) {
1119 head += "<big><b>"; 1110 head += "<big><b>";
1120 head += print_filter(_(_menu->prompt->text)); 1111 head += print_filter(_menu->prompt->text);
1121 head += "</b></big><br><br>"; 1112 head += "</b></big><br><br>";
1122 if (showDebug()) { 1113 if (showDebug()) {
1123 if (_menu->prompt->visible.expr) { 1114 if (_menu->prompt->visible.expr) {
@@ -1152,7 +1143,7 @@ QString ConfigInfoView::debug_info(struct symbol *sym)
1152 case P_PROMPT: 1143 case P_PROMPT:
1153 case P_MENU: 1144 case P_MENU:
1154 debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu); 1145 debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
1155 debug += print_filter(_(prop->text)); 1146 debug += print_filter(prop->text);
1156 debug += "</a><br>"; 1147 debug += "</a><br>";
1157 break; 1148 break;
1158 case P_DEFAULT: 1149 case P_DEFAULT:
@@ -1234,7 +1225,7 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
1234QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos) 1225QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos)
1235{ 1226{
1236 QMenu* popup = Parent::createStandardContextMenu(pos); 1227 QMenu* popup = Parent::createStandardContextMenu(pos);
1237 QAction* action = new QAction(_("Show Debug Info"), popup); 1228 QAction* action = new QAction("Show Debug Info", popup);
1238 action->setCheckable(true); 1229 action->setCheckable(true);
1239 connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); 1230 connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
1240 connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool))); 1231 connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
@@ -1261,11 +1252,11 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *nam
1261 QHBoxLayout* layout2 = new QHBoxLayout(0); 1252 QHBoxLayout* layout2 = new QHBoxLayout(0);
1262 layout2->setContentsMargins(0, 0, 0, 0); 1253 layout2->setContentsMargins(0, 0, 0, 0);
1263 layout2->setSpacing(6); 1254 layout2->setSpacing(6);
1264 layout2->addWidget(new QLabel(_("Find:"), this)); 1255 layout2->addWidget(new QLabel("Find:", this));
1265 editField = new QLineEdit(this); 1256 editField = new QLineEdit(this);
1266 connect(editField, SIGNAL(returnPressed()), SLOT(search())); 1257 connect(editField, SIGNAL(returnPressed()), SLOT(search()));
1267 layout2->addWidget(editField); 1258 layout2->addWidget(editField);
1268 searchButton = new QPushButton(_("Search"), this); 1259 searchButton = new QPushButton("Search", this);
1269 searchButton->setAutoDefault(false); 1260 searchButton->setAutoDefault(false);
1270 connect(searchButton, SIGNAL(clicked()), SLOT(search())); 1261 connect(searchButton, SIGNAL(clicked()), SLOT(search()));
1271 layout2->addWidget(searchButton); 1262 layout2->addWidget(searchButton);
@@ -1387,44 +1378,44 @@ ConfigMainWindow::ConfigMainWindow(void)
1387 toolBar = new QToolBar("Tools", this); 1378 toolBar = new QToolBar("Tools", this);
1388 addToolBar(toolBar); 1379 addToolBar(toolBar);
1389 1380
1390 backAction = new QAction(QPixmap(xpm_back), _("Back"), this); 1381 backAction = new QAction(QPixmap(xpm_back), "Back", this);
1391 connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack())); 1382 connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack()));
1392 backAction->setEnabled(false); 1383 backAction->setEnabled(false);
1393 QAction *quitAction = new QAction(_("&Quit"), this); 1384 QAction *quitAction = new QAction("&Quit", this);
1394 quitAction->setShortcut(Qt::CTRL + Qt::Key_Q); 1385 quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
1395 connect(quitAction, SIGNAL(triggered(bool)), SLOT(close())); 1386 connect(quitAction, SIGNAL(triggered(bool)), SLOT(close()));
1396 QAction *loadAction = new QAction(QPixmap(xpm_load), _("&Load"), this); 1387 QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
1397 loadAction->setShortcut(Qt::CTRL + Qt::Key_L); 1388 loadAction->setShortcut(Qt::CTRL + Qt::Key_L);
1398 connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig())); 1389 connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig()));
1399 saveAction = new QAction(QPixmap(xpm_save), _("&Save"), this); 1390 saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
1400 saveAction->setShortcut(Qt::CTRL + Qt::Key_S); 1391 saveAction->setShortcut(Qt::CTRL + Qt::Key_S);
1401 connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig())); 1392 connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig()));
1402 conf_set_changed_callback(conf_changed); 1393 conf_set_changed_callback(conf_changed);
1403 // Set saveAction's initial state 1394 // Set saveAction's initial state
1404 conf_changed(); 1395 conf_changed();
1405 QAction *saveAsAction = new QAction(_("Save &As..."), this); 1396 QAction *saveAsAction = new QAction("Save &As...", this);
1406 connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs())); 1397 connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs()));
1407 QAction *searchAction = new QAction(_("&Find"), this); 1398 QAction *searchAction = new QAction("&Find", this);
1408 searchAction->setShortcut(Qt::CTRL + Qt::Key_F); 1399 searchAction->setShortcut(Qt::CTRL + Qt::Key_F);
1409 connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig())); 1400 connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig()));
1410 singleViewAction = new QAction(QPixmap(xpm_single_view), _("Single View"), this); 1401 singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
1411 singleViewAction->setCheckable(true); 1402 singleViewAction->setCheckable(true);
1412 connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView())); 1403 connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView()));
1413 splitViewAction = new QAction(QPixmap(xpm_split_view), _("Split View"), this); 1404 splitViewAction = new QAction(QPixmap(xpm_split_view), "Split View", this);
1414 splitViewAction->setCheckable(true); 1405 splitViewAction->setCheckable(true);
1415 connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView())); 1406 connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView()));
1416 fullViewAction = new QAction(QPixmap(xpm_tree_view), _("Full View"), this); 1407 fullViewAction = new QAction(QPixmap(xpm_tree_view), "Full View", this);
1417 fullViewAction->setCheckable(true); 1408 fullViewAction->setCheckable(true);
1418 connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView())); 1409 connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView()));
1419 1410
1420 QAction *showNameAction = new QAction(_("Show Name"), this); 1411 QAction *showNameAction = new QAction("Show Name", this);
1421 showNameAction->setCheckable(true); 1412 showNameAction->setCheckable(true);
1422 connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); 1413 connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
1423 showNameAction->setChecked(configView->showName()); 1414 showNameAction->setChecked(configView->showName());
1424 QAction *showRangeAction = new QAction(_("Show Range"), this); 1415 QAction *showRangeAction = new QAction("Show Range", this);
1425 showRangeAction->setCheckable(true); 1416 showRangeAction->setCheckable(true);
1426 connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); 1417 connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
1427 QAction *showDataAction = new QAction(_("Show Data"), this); 1418 QAction *showDataAction = new QAction("Show Data", this);
1428 showDataAction->setCheckable(true); 1419 showDataAction->setCheckable(true);
1429 connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); 1420 connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
1430 1421
@@ -1435,21 +1426,21 @@ ConfigMainWindow::ConfigMainWindow(void)
1435 connect(optGroup, SIGNAL(triggered(QAction *)), menuView, 1426 connect(optGroup, SIGNAL(triggered(QAction *)), menuView,
1436 SLOT(setOptionMode(QAction *))); 1427 SLOT(setOptionMode(QAction *)));
1437 1428
1438 configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup); 1429 configView->showNormalAction = new QAction("Show Normal Options", optGroup);
1439 configView->showAllAction = new QAction(_("Show All Options"), optGroup); 1430 configView->showAllAction = new QAction("Show All Options", optGroup);
1440 configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup); 1431 configView->showPromptAction = new QAction("Show Prompt Options", optGroup);
1441 configView->showNormalAction->setCheckable(true); 1432 configView->showNormalAction->setCheckable(true);
1442 configView->showAllAction->setCheckable(true); 1433 configView->showAllAction->setCheckable(true);
1443 configView->showPromptAction->setCheckable(true); 1434 configView->showPromptAction->setCheckable(true);
1444 1435
1445 QAction *showDebugAction = new QAction( _("Show Debug Info"), this); 1436 QAction *showDebugAction = new QAction("Show Debug Info", this);
1446 showDebugAction->setCheckable(true); 1437 showDebugAction->setCheckable(true);
1447 connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); 1438 connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
1448 showDebugAction->setChecked(helpText->showDebug()); 1439 showDebugAction->setChecked(helpText->showDebug());
1449 1440
1450 QAction *showIntroAction = new QAction( _("Introduction"), this); 1441 QAction *showIntroAction = new QAction("Introduction", this);
1451 connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro())); 1442 connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro()));
1452 QAction *showAboutAction = new QAction( _("About"), this); 1443 QAction *showAboutAction = new QAction("About", this);
1453 connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout())); 1444 connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout()));
1454 1445
1455 // init tool bar 1446 // init tool bar
@@ -1463,7 +1454,7 @@ ConfigMainWindow::ConfigMainWindow(void)
1463 toolBar->addAction(fullViewAction); 1454 toolBar->addAction(fullViewAction);
1464 1455
1465 // create config menu 1456 // create config menu
1466 QMenu* config = menu->addMenu(_("&File")); 1457 QMenu* config = menu->addMenu("&File");
1467 config->addAction(loadAction); 1458 config->addAction(loadAction);
1468 config->addAction(saveAction); 1459 config->addAction(saveAction);
1469 config->addAction(saveAsAction); 1460 config->addAction(saveAsAction);
@@ -1471,11 +1462,11 @@ ConfigMainWindow::ConfigMainWindow(void)
1471 config->addAction(quitAction); 1462 config->addAction(quitAction);
1472 1463
1473 // create edit menu 1464 // create edit menu
1474 QMenu* editMenu = menu->addMenu(_("&Edit")); 1465 QMenu* editMenu = menu->addMenu("&Edit");
1475 editMenu->addAction(searchAction); 1466 editMenu->addAction(searchAction);
1476 1467
1477 // create options menu 1468 // create options menu
1478 QMenu* optionMenu = menu->addMenu(_("&Option")); 1469 QMenu* optionMenu = menu->addMenu("&Option");
1479 optionMenu->addAction(showNameAction); 1470 optionMenu->addAction(showNameAction);
1480 optionMenu->addAction(showRangeAction); 1471 optionMenu->addAction(showRangeAction);
1481 optionMenu->addAction(showDataAction); 1472 optionMenu->addAction(showDataAction);
@@ -1486,7 +1477,7 @@ ConfigMainWindow::ConfigMainWindow(void)
1486 1477
1487 // create help menu 1478 // create help menu
1488 menu->addSeparator(); 1479 menu->addSeparator();
1489 QMenu* helpMenu = menu->addMenu(_("&Help")); 1480 QMenu* helpMenu = menu->addMenu("&Help");
1490 helpMenu->addAction(showIntroAction); 1481 helpMenu->addAction(showIntroAction);
1491 helpMenu->addAction(showAboutAction); 1482 helpMenu->addAction(showAboutAction);
1492 1483
@@ -1534,14 +1525,14 @@ void ConfigMainWindow::loadConfig(void)
1534 if (s.isNull()) 1525 if (s.isNull())
1535 return; 1526 return;
1536 if (conf_read(QFile::encodeName(s))) 1527 if (conf_read(QFile::encodeName(s)))
1537 QMessageBox::information(this, "qconf", _("Unable to load configuration!")); 1528 QMessageBox::information(this, "qconf", "Unable to load configuration!");
1538 ConfigView::updateListAll(); 1529 ConfigView::updateListAll();
1539} 1530}
1540 1531
1541bool ConfigMainWindow::saveConfig(void) 1532bool ConfigMainWindow::saveConfig(void)
1542{ 1533{
1543 if (conf_write(NULL)) { 1534 if (conf_write(NULL)) {
1544 QMessageBox::information(this, "qconf", _("Unable to save configuration!")); 1535 QMessageBox::information(this, "qconf", "Unable to save configuration!");
1545 return false; 1536 return false;
1546 } 1537 }
1547 return true; 1538 return true;
@@ -1723,11 +1714,11 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e)
1723 e->accept(); 1714 e->accept();
1724 return; 1715 return;
1725 } 1716 }
1726 QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning, 1717 QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
1727 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); 1718 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
1728 mb.setButtonText(QMessageBox::Yes, _("&Save Changes")); 1719 mb.setButtonText(QMessageBox::Yes, "&Save Changes");
1729 mb.setButtonText(QMessageBox::No, _("&Discard Changes")); 1720 mb.setButtonText(QMessageBox::No, "&Discard Changes");
1730 mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit")); 1721 mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
1731 switch (mb.exec()) { 1722 switch (mb.exec()) {
1732 case QMessageBox::Yes: 1723 case QMessageBox::Yes:
1733 if (saveConfig()) 1724 if (saveConfig())
@@ -1746,7 +1737,7 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e)
1746 1737
1747void ConfigMainWindow::showIntro(void) 1738void ConfigMainWindow::showIntro(void)
1748{ 1739{
1749 static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n" 1740 static const QString str = "Welcome to the qconf graphical configuration tool.\n\n"
1750 "For each option, a blank box indicates the feature is disabled, a check\n" 1741 "For each option, a blank box indicates the feature is disabled, a check\n"
1751 "indicates it is enabled, and a dot indicates that it is to be compiled\n" 1742 "indicates it is enabled, and a dot indicates that it is to be compiled\n"
1752 "as a module. Clicking on the box will cycle through the three states.\n\n" 1743 "as a module. Clicking on the box will cycle through the three states.\n\n"
@@ -1756,16 +1747,16 @@ void ConfigMainWindow::showIntro(void)
1756 "options must be enabled to support the option you are interested in, you can\n" 1747 "options must be enabled to support the option you are interested in, you can\n"
1757 "still view the help of a grayed-out option.\n\n" 1748 "still view the help of a grayed-out option.\n\n"
1758 "Toggling Show Debug Info under the Options menu will show the dependencies,\n" 1749 "Toggling Show Debug Info under the Options menu will show the dependencies,\n"
1759 "which you can then match by examining other options.\n\n"); 1750 "which you can then match by examining other options.\n\n";
1760 1751
1761 QMessageBox::information(this, "qconf", str); 1752 QMessageBox::information(this, "qconf", str);
1762} 1753}
1763 1754
1764void ConfigMainWindow::showAbout(void) 1755void ConfigMainWindow::showAbout(void)
1765{ 1756{
1766 static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n" 1757 static const QString str = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n"
1767 "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n" 1758 "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n"
1768 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"); 1759 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n";
1769 1760
1770 QMessageBox::information(this, "qconf", str); 1761 QMessageBox::information(this, "qconf", str);
1771} 1762}
@@ -1826,7 +1817,7 @@ static const char *progname;
1826 1817
1827static void usage(void) 1818static void usage(void)
1828{ 1819{
1829 printf(_("%s [-s] <config>\n").toLatin1().constData(), progname); 1820 printf("%s [-s] <config>\n", progname);
1830 exit(0); 1821 exit(0);
1831} 1822}
1832 1823
@@ -1835,9 +1826,6 @@ int main(int ac, char** av)
1835 ConfigMainWindow* v; 1826 ConfigMainWindow* v;
1836 const char *name; 1827 const char *name;
1837 1828
1838 bindtextdomain(PACKAGE, LOCALEDIR);
1839 textdomain(PACKAGE);
1840
1841 progname = av[0]; 1829 progname = av[0];
1842 configApp = new QApplication(ac, av); 1830 configApp = new QApplication(ac, av);
1843 if (ac > 1 && av[1][0] == '-') { 1831 if (ac > 1 && av[1][0] == '-') {
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index f0b2e3b3102d..7c9a88e91cfa 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -33,33 +33,6 @@ struct symbol *sym_defconfig_list;
33struct symbol *modules_sym; 33struct symbol *modules_sym;
34tristate modules_val; 34tristate modules_val;
35 35
36struct expr *sym_env_list;
37
38static void sym_add_default(struct symbol *sym, const char *def)
39{
40 struct property *prop = prop_alloc(P_DEFAULT, sym);
41
42 prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
43}
44
45void sym_init(void)
46{
47 struct symbol *sym;
48 struct utsname uts;
49 static bool inited = false;
50
51 if (inited)
52 return;
53 inited = true;
54
55 uname(&uts);
56
57 sym = sym_lookup("UNAME_RELEASE", 0);
58 sym->type = S_STRING;
59 sym->flags |= SYMBOL_AUTO;
60 sym_add_default(sym, uts.release);
61}
62
63enum symbol_type sym_get_type(struct symbol *sym) 36enum symbol_type sym_get_type(struct symbol *sym)
64{ 37{
65 enum symbol_type type = sym->type; 38 enum symbol_type type = sym->type;
@@ -906,59 +879,6 @@ struct symbol *sym_find(const char *name)
906 return symbol; 879 return symbol;
907} 880}
908 881
909/*
910 * Expand symbol's names embedded in the string given in argument. Symbols'
911 * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
912 * the empty string.
913 */
914char *sym_expand_string_value(const char *in)
915{
916 const char *src;
917 char *res;
918 size_t reslen;
919
920 /*
921 * Note: 'in' might come from a token that's about to be
922 * freed, so make sure to always allocate a new string
923 */
924 reslen = strlen(in) + 1;
925 res = xmalloc(reslen);
926 res[0] = '\0';
927
928 while ((src = strchr(in, '$'))) {
929 char *p, name[SYMBOL_MAXLENGTH];
930 const char *symval = "";
931 struct symbol *sym;
932 size_t newlen;
933
934 strncat(res, in, src - in);
935 src++;
936
937 p = name;
938 while (isalnum(*src) || *src == '_')
939 *p++ = *src++;
940 *p = '\0';
941
942 sym = sym_find(name);
943 if (sym != NULL) {
944 sym_calc_value(sym);
945 symval = sym_get_string_value(sym);
946 }
947
948 newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
949 if (newlen > reslen) {
950 reslen = newlen;
951 res = xrealloc(res, reslen);
952 }
953
954 strcat(res, symval);
955 in = src;
956 }
957 strcat(res, in);
958
959 return res;
960}
961
962const char *sym_escape_string_value(const char *in) 882const char *sym_escape_string_value(const char *in)
963{ 883{
964 const char *p; 884 const char *p;
@@ -1401,32 +1321,3 @@ const char *prop_get_type_name(enum prop_type type)
1401 } 1321 }
1402 return "unknown"; 1322 return "unknown";
1403} 1323}
1404
1405static void prop_add_env(const char *env)
1406{
1407 struct symbol *sym, *sym2;
1408 struct property *prop;
1409 char *p;
1410
1411 sym = current_entry->sym;
1412 sym->flags |= SYMBOL_AUTO;
1413 for_all_properties(sym, prop, P_ENV) {
1414 sym2 = prop_get_symbol(prop);
1415 if (strcmp(sym2->name, env))
1416 menu_warn(current_entry, "redefining environment symbol from %s",
1417 sym2->name);
1418 return;
1419 }
1420
1421 prop = prop_alloc(P_ENV, sym);
1422 prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
1423
1424 sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
1425 sym_env_list->right.sym = sym;
1426
1427 p = getenv(env);
1428 if (p)
1429 sym_add_default(sym, p);
1430 else
1431 menu_warn(current_entry, "environment variable %s undefined", env);
1432}
diff --git a/scripts/kconfig/tests/no_write_if_dep_unmet/expected_config b/scripts/kconfig/tests/no_write_if_dep_unmet/expected_config
index 0d15e41da475..473228810c35 100644
--- a/scripts/kconfig/tests/no_write_if_dep_unmet/expected_config
+++ b/scripts/kconfig/tests/no_write_if_dep_unmet/expected_config
@@ -1,5 +1,5 @@
1# 1#
2# Automatically generated file; DO NOT EDIT. 2# Automatically generated file; DO NOT EDIT.
3# Linux Kernel Configuration 3# Main menu
4# 4#
5# CONFIG_A is not set 5# CONFIG_A is not set
diff --git a/scripts/kconfig/tests/preprocess/builtin_func/Kconfig b/scripts/kconfig/tests/preprocess/builtin_func/Kconfig
new file mode 100644
index 000000000000..baa328827911
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/builtin_func/Kconfig
@@ -0,0 +1,27 @@
1# SPDX-License-Identifier: GPL-2.0
2
3# 'info' prints the argument to stdout.
4$(info,hello world 0)
5
6# 'warning-if', if the first argument is y, sends the second argument to stderr,
7# and the message is prefixed with the current file name and line number.
8$(warning-if,y,hello world 1)
9
10# 'error-if' is similar, but it terminates the parsing immediately.
11# The following is just no-op since the first argument is not y.
12$(error-if,n,this should not be printed)
13
14# Shorthand
15warning = $(warning-if,y,$(1))
16
17# 'shell' executes a command, and returns its stdout.
18$(warning,$(shell,echo hello world 3))
19
20# Every newline in the output is replaced with a space,
21# but any trailing newlines are deleted.
22$(warning,$(shell,printf 'hello\nworld\n\n4\n\n\n'))
23
24# 'filename' is expanded to the currently parsed file name,
25# 'lineno' to the line number.
26$(warning,filename=$(filename))
27$(warning,lineno=$(lineno))
diff --git a/scripts/kconfig/tests/preprocess/builtin_func/__init__.py b/scripts/kconfig/tests/preprocess/builtin_func/__init__.py
new file mode 100644
index 000000000000..2e53ba08fca1
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/builtin_func/__init__.py
@@ -0,0 +1,9 @@
1# SPDX-License-Identifier: GPL-2.0
2"""
3Built-in function tests.
4"""
5
6def test(conf):
7 assert conf.oldaskconfig() == 0
8 assert conf.stdout_contains('expected_stdout')
9 assert conf.stderr_matches('expected_stderr')
diff --git a/scripts/kconfig/tests/preprocess/builtin_func/expected_stderr b/scripts/kconfig/tests/preprocess/builtin_func/expected_stderr
new file mode 100644
index 000000000000..33ea9ca38400
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/builtin_func/expected_stderr
@@ -0,0 +1,5 @@
1Kconfig:8: hello world 1
2Kconfig:18: hello world 3
3Kconfig:22: hello world 4
4Kconfig:26: filename=Kconfig
5Kconfig:27: lineno=27
diff --git a/scripts/kconfig/tests/preprocess/builtin_func/expected_stdout b/scripts/kconfig/tests/preprocess/builtin_func/expected_stdout
new file mode 100644
index 000000000000..82de3a7e97de
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/builtin_func/expected_stdout
@@ -0,0 +1 @@
hello world 0
diff --git a/scripts/kconfig/tests/preprocess/circular_expansion/Kconfig b/scripts/kconfig/tests/preprocess/circular_expansion/Kconfig
new file mode 100644
index 000000000000..6838997c23ba
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/circular_expansion/Kconfig
@@ -0,0 +1,5 @@
1# SPDX-License-Identifier: GPL-2.0
2
3X = $(Y)
4Y = $(X)
5$(info $(X))
diff --git a/scripts/kconfig/tests/preprocess/circular_expansion/__init__.py b/scripts/kconfig/tests/preprocess/circular_expansion/__init__.py
new file mode 100644
index 000000000000..419bda3e075c
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/circular_expansion/__init__.py
@@ -0,0 +1,11 @@
1# SPDX-License-Identifier: GPL-2.0
2"""
3Detect circular variable expansion.
4
5If a recursively expanded variable references itself (eventually),
6it should fail with an error message.
7"""
8
9def test(conf):
10 assert conf.oldaskconfig() != 0
11 assert conf.stderr_matches('expected_stderr')
diff --git a/scripts/kconfig/tests/preprocess/circular_expansion/expected_stderr b/scripts/kconfig/tests/preprocess/circular_expansion/expected_stderr
new file mode 100644
index 000000000000..cde68fa989d0
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/circular_expansion/expected_stderr
@@ -0,0 +1 @@
Kconfig:5: Recursive variable 'X' references itself (eventually)
diff --git a/scripts/kconfig/tests/preprocess/escape/Kconfig b/scripts/kconfig/tests/preprocess/escape/Kconfig
new file mode 100644
index 000000000000..4e3f44445544
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/escape/Kconfig
@@ -0,0 +1,44 @@
1# SPDX-License-Identifier: GPL-2.0
2
3# Shorthand
4warning = $(warning-if,y,$(1))
5
6# You can not pass commas directly to a function since they are treated as
7# delimiters. You can use the following trick to do so.
8comma := ,
9$(warning,hello$(comma) world)
10
11# Like Make, single quotes, double quotes, spaces are treated verbatim.
12# The following prints the text as-is.
13$(warning, ' " '" ' ''' "'")
14
15# Unlike Make, '$' has special meaning only when it is followed by '('.
16# No need to escape '$' itself.
17$(warning,$)
18$(warning,$$)
19$ := 1
20$(warning,$($))
21
22# You need a trick to escape '$' followed by '('
23# The following should print "$(X)". It should not be expanded further.
24dollar := $
25$(warning,$(dollar)(X))
26
27# You need a trick to treat unbalanced parentheses.
28# The following should print "(".
29left_paren := (
30$(warning,$(left_paren))
31
32# A simple expanded should not be expanded multiple times.
33# The following should print "$(X)". It should not be expanded further.
34Y := $(dollar)(X)
35$(warning,$(Y))
36
37# The following should print "$(X)" as well.
38Y = $(dollar)(X)
39$(warning,$(Y))
40
41# The following should print "$(".
42# It should not be emit "unterminated reference" error.
43unterminated := $(dollar)(
44$(warning,$(unterminated))
diff --git a/scripts/kconfig/tests/preprocess/escape/__init__.py b/scripts/kconfig/tests/preprocess/escape/__init__.py
new file mode 100644
index 000000000000..7ee8e747f546
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/escape/__init__.py
@@ -0,0 +1,8 @@
1# SPDX-License-Identifier: GPL-2.0
2"""
3Escape sequence tests.
4"""
5
6def test(conf):
7 assert conf.oldaskconfig() == 0
8 assert conf.stderr_matches('expected_stderr')
diff --git a/scripts/kconfig/tests/preprocess/escape/expected_stderr b/scripts/kconfig/tests/preprocess/escape/expected_stderr
new file mode 100644
index 000000000000..1c00957ddaa9
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/escape/expected_stderr
@@ -0,0 +1,10 @@
1Kconfig:9: hello, world
2Kconfig:13: ' " '" ' ''' "'"
3Kconfig:17: $
4Kconfig:18: $$
5Kconfig:20: 1
6Kconfig:25: $(X)
7Kconfig:30: (
8Kconfig:35: $(X)
9Kconfig:39: $(X)
10Kconfig:44: $(
diff --git a/scripts/kconfig/tests/preprocess/variable/Kconfig b/scripts/kconfig/tests/preprocess/variable/Kconfig
new file mode 100644
index 000000000000..9ce2f95cbd24
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/variable/Kconfig
@@ -0,0 +1,53 @@
1# SPDX-License-Identifier: GPL-2.0
2
3# Shorthand
4warning = $(warning-if,y,$(1))
5
6# Simply expanded variable.
7X := 1
8SIMPLE := $(X)
9X := 2
10$(warning,SIMPLE = $(SIMPLE))
11
12# Recursively expanded variable.
13X := 1
14RECURSIVE = $(X)
15X := 2
16$(warning,RECURSIVE = $(RECURSIVE))
17
18# Append something to a simply expanded variable.
19Y := 3
20SIMPLE += $(Y)
21Y := 4
22$(warning,SIMPLE = $(SIMPLE))
23
24# Append something to a recursively expanded variable.
25Y := 3
26RECURSIVE += $(Y)
27Y := 4
28$(warning,RECURSIVE = $(RECURSIVE))
29
30# Use += operator to an undefined variable.
31# This works as a recursively expanded variable.
32Y := 3
33UNDEFINED_VARIABLE += $(Y)
34Y := 4
35$(warning,UNDEFINED_VARIABLE = $(UNDEFINED_VARIABLE))
36
37# You can use variable references for the lefthand side of assignment statement.
38X := A
39Y := B
40$(X)$(Y) := 5
41$(warning,AB = $(AB))
42
43# User-defined function.
44greeting = $(1), my name is $(2).
45$(warning,$(greeting,Hello,John))
46
47# The number of arguments is not checked for user-defined functions.
48# If some arguments are optional, it is useful to pass fewer parameters.
49# $(2) will be blank in this case.
50$(warning,$(greeting,Hello))
51
52# Unreferenced parameters are just ignored.
53$(warning,$(greeting,Hello,John,ignored,ignored))
diff --git a/scripts/kconfig/tests/preprocess/variable/__init__.py b/scripts/kconfig/tests/preprocess/variable/__init__.py
new file mode 100644
index 000000000000..e88b1708d6d4
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/variable/__init__.py
@@ -0,0 +1,8 @@
1# SPDX-License-Identifier: GPL-2.0
2"""
3Variable and user-defined function tests.
4"""
5
6def test(conf):
7 assert conf.oldaskconfig() == 0
8 assert conf.stderr_matches('expected_stderr')
diff --git a/scripts/kconfig/tests/preprocess/variable/expected_stderr b/scripts/kconfig/tests/preprocess/variable/expected_stderr
new file mode 100644
index 000000000000..a4841c3fdff5
--- /dev/null
+++ b/scripts/kconfig/tests/preprocess/variable/expected_stderr
@@ -0,0 +1,9 @@
1Kconfig:10: SIMPLE = 1
2Kconfig:16: RECURSIVE = 2
3Kconfig:22: SIMPLE = 1 3
4Kconfig:28: RECURSIVE = 2 4
5Kconfig:35: UNDEFINED_VARIABLE = 4
6Kconfig:41: AB = 5
7Kconfig:45: Hello, my name is John.
8Kconfig:50: Hello, my name is .
9Kconfig:53: Hello, my name is John.
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index c6f6e21b809f..a365594770d9 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -14,18 +14,16 @@
14struct file *file_lookup(const char *name) 14struct file *file_lookup(const char *name)
15{ 15{
16 struct file *file; 16 struct file *file;
17 char *file_name = sym_expand_string_value(name);
18 17
19 for (file = file_list; file; file = file->next) { 18 for (file = file_list; file; file = file->next) {
20 if (!strcmp(name, file->name)) { 19 if (!strcmp(name, file->name)) {
21 free(file_name);
22 return file; 20 return file;
23 } 21 }
24 } 22 }
25 23
26 file = xmalloc(sizeof(*file)); 24 file = xmalloc(sizeof(*file));
27 memset(file, 0, sizeof(*file)); 25 memset(file, 0, sizeof(*file));
28 file->name = file_name; 26 file->name = xstrdup(name);
29 file->next = file_list; 27 file->next = file_list;
30 file_list = file; 28 file_list = file;
31 return file; 29 return file;
@@ -34,8 +32,6 @@ struct file *file_lookup(const char *name)
34/* write a dependency file as used by kbuild to track dependencies */ 32/* write a dependency file as used by kbuild to track dependencies */
35int file_write_dep(const char *name) 33int file_write_dep(const char *name)
36{ 34{
37 struct symbol *sym, *env_sym;
38 struct expr *e;
39 struct file *file; 35 struct file *file;
40 FILE *out; 36 FILE *out;
41 37
@@ -54,21 +50,7 @@ int file_write_dep(const char *name)
54 fprintf(out, "\n%s: \\\n" 50 fprintf(out, "\n%s: \\\n"
55 "\t$(deps_config)\n\n", conf_get_autoconfig_name()); 51 "\t$(deps_config)\n\n", conf_get_autoconfig_name());
56 52
57 expr_list_for_each_sym(sym_env_list, e, sym) { 53 env_write_dep(out, conf_get_autoconfig_name());
58 struct property *prop;
59 const char *value;
60
61 prop = sym_get_env_prop(sym);
62 env_sym = prop_get_symbol(prop);
63 if (!env_sym)
64 continue;
65 value = getenv(env_sym->name);
66 if (!value)
67 value = "";
68 fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value);
69 fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name());
70 fprintf(out, "endif\n");
71 }
72 54
73 fprintf(out, "\n$(deps_config): ;\n"); 55 fprintf(out, "\n$(deps_config): ;\n");
74 fclose(out); 56 fclose(out);
@@ -165,3 +147,14 @@ char *xstrdup(const char *s)
165 fprintf(stderr, "Out of memory.\n"); 147 fprintf(stderr, "Out of memory.\n");
166 exit(1); 148 exit(1);
167} 149}
150
151char *xstrndup(const char *s, size_t n)
152{
153 char *p;
154
155 p = strndup(s, n);
156 if (p)
157 return p;
158 fprintf(stderr, "Out of memory.\n");
159 exit(1);
160}
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
index 045093d827e1..25bd2b89fe3f 100644
--- a/scripts/kconfig/zconf.l
+++ b/scripts/kconfig/zconf.l
@@ -1,13 +1,13 @@
1%option nostdinit noyywrap never-interactive full ecs 1%option nostdinit noyywrap never-interactive full ecs
2%option 8bit nodefault yylineno 2%option 8bit nodefault yylineno
3%option noinput 3%x COMMAND HELP STRING PARAM ASSIGN_VAL
4%x COMMAND HELP STRING PARAM
5%{ 4%{
6/* 5/*
7 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 6 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
8 * Released under the terms of the GNU GPL v2.0. 7 * Released under the terms of the GNU GPL v2.0.
9 */ 8 */
10 9
10#include <assert.h>
11#include <limits.h> 11#include <limits.h>
12#include <stdio.h> 12#include <stdio.h>
13#include <stdlib.h> 13#include <stdlib.h>
@@ -35,6 +35,8 @@ struct buffer *current_buf;
35 35
36static int last_ts, first_ts; 36static int last_ts, first_ts;
37 37
38static char *expand_token(const char *in, size_t n);
39static void append_expanded_string(const char *in);
38static void zconf_endhelp(void); 40static void zconf_endhelp(void);
39static void zconf_endfile(void); 41static void zconf_endfile(void);
40 42
@@ -101,17 +103,28 @@ n [A-Za-z0-9_-]
101<COMMAND>{ 103<COMMAND>{
102 {n}+ { 104 {n}+ {
103 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); 105 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
104 BEGIN(PARAM);
105 current_pos.file = current_file; 106 current_pos.file = current_file;
106 current_pos.lineno = yylineno; 107 current_pos.lineno = yylineno;
107 if (id && id->flags & TF_COMMAND) { 108 if (id && id->flags & TF_COMMAND) {
109 BEGIN(PARAM);
108 yylval.id = id; 110 yylval.id = id;
109 return id->token; 111 return id->token;
110 } 112 }
111 alloc_string(yytext, yyleng); 113 alloc_string(yytext, yyleng);
112 yylval.string = text; 114 yylval.string = text;
113 return T_WORD; 115 return T_VARIABLE;
114 } 116 }
117 ({n}|$)+ {
118 /* this token includes at least one '$' */
119 yylval.string = expand_token(yytext, yyleng);
120 if (strlen(yylval.string))
121 return T_VARIABLE;
122 free(yylval.string);
123 }
124 "=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_RECURSIVE; return T_ASSIGN; }
125 ":=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_SIMPLE; return T_ASSIGN; }
126 "+=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_APPEND; return T_ASSIGN; }
127 [[:blank:]]+
115 . warn_ignored_character(*yytext); 128 . warn_ignored_character(*yytext);
116 \n { 129 \n {
117 BEGIN(INITIAL); 130 BEGIN(INITIAL);
@@ -119,6 +132,16 @@ n [A-Za-z0-9_-]
119 } 132 }
120} 133}
121 134
135<ASSIGN_VAL>{
136 [^[:blank:]\n]+.* {
137 alloc_string(yytext, yyleng);
138 yylval.string = text;
139 return T_ASSIGN_VAL;
140 }
141 \n { BEGIN(INITIAL); return T_EOL; }
142 .
143}
144
122<PARAM>{ 145<PARAM>{
123 "&&" return T_AND; 146 "&&" return T_AND;
124 "||" return T_OR; 147 "||" return T_OR;
@@ -147,6 +170,13 @@ n [A-Za-z0-9_-]
147 yylval.string = text; 170 yylval.string = text;
148 return T_WORD; 171 return T_WORD;
149 } 172 }
173 ({n}|[/.$])+ {
174 /* this token includes at least one '$' */
175 yylval.string = expand_token(yytext, yyleng);
176 if (strlen(yylval.string))
177 return T_WORD;
178 free(yylval.string);
179 }
150 #.* /* comment */ 180 #.* /* comment */
151 \\\n ; 181 \\\n ;
152 [[:blank:]]+ 182 [[:blank:]]+
@@ -157,12 +187,13 @@ n [A-Za-z0-9_-]
157} 187}
158 188
159<STRING>{ 189<STRING>{
160 [^'"\\\n]+/\n { 190 "$".* append_expanded_string(yytext);
191 [^$'"\\\n]+/\n {
161 append_string(yytext, yyleng); 192 append_string(yytext, yyleng);
162 yylval.string = text; 193 yylval.string = text;
163 return T_WORD_QUOTE; 194 return T_WORD_QUOTE;
164 } 195 }
165 [^'"\\\n]+ { 196 [^$'"\\\n]+ {
166 append_string(yytext, yyleng); 197 append_string(yytext, yyleng);
167 } 198 }
168 \\.?/\n { 199 \\.?/\n {
@@ -249,6 +280,58 @@ n [A-Za-z0-9_-]
249} 280}
250 281
251%% 282%%
283static char *expand_token(const char *in, size_t n)
284{
285 char *out;
286 int c;
287 char c2;
288 const char *rest, *end;
289
290 new_string();
291 append_string(in, n);
292
293 /* get the whole line because we do not know the end of token. */
294 while ((c = input()) != EOF) {
295 if (c == '\n') {
296 unput(c);
297 break;
298 }
299 c2 = c;
300 append_string(&c2, 1);
301 }
302
303 rest = text;
304 out = expand_one_token(&rest);
305
306 /* push back unused characters to the input stream */
307 end = rest + strlen(rest);
308 while (end > rest)
309 unput(*--end);
310
311 free(text);
312
313 return out;
314}
315
316static void append_expanded_string(const char *str)
317{
318 const char *end;
319 char *res;
320
321 str++;
322
323 res = expand_dollar(&str);
324
325 /* push back unused characters to the input stream */
326 end = str + strlen(str);
327 while (end > str)
328 unput(*--end);
329
330 append_string(res, strlen(res));
331
332 free(res);
333}
334
252void zconf_starthelp(void) 335void zconf_starthelp(void)
253{ 336{
254 new_string(); 337 new_string();
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index ad6305b0f40c..6f9b0aa32a82 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -41,6 +41,7 @@ static struct menu *current_menu, *current_entry;
41 struct expr *expr; 41 struct expr *expr;
42 struct menu *menu; 42 struct menu *menu;
43 const struct kconf_id *id; 43 const struct kconf_id *id;
44 enum variable_flavor flavor;
44} 45}
45 46
46%token <id>T_MAINMENU 47%token <id>T_MAINMENU
@@ -77,6 +78,9 @@ static struct menu *current_menu, *current_entry;
77%token T_CLOSE_PAREN 78%token T_CLOSE_PAREN
78%token T_OPEN_PAREN 79%token T_OPEN_PAREN
79%token T_EOL 80%token T_EOL
81%token <string> T_VARIABLE
82%token <flavor> T_ASSIGN
83%token <string> T_ASSIGN_VAL
80 84
81%left T_OR 85%left T_OR
82%left T_AND 86%left T_AND
@@ -92,7 +96,7 @@ static struct menu *current_menu, *current_entry;
92%type <id> end 96%type <id> end
93%type <id> option_name 97%type <id> option_name
94%type <menu> if_entry menu_entry choice_entry 98%type <menu> if_entry menu_entry choice_entry
95%type <string> symbol_option_arg word_opt 99%type <string> symbol_option_arg word_opt assign_val
96 100
97%destructor { 101%destructor {
98 fprintf(stderr, "%s:%d: missing end statement for this entry\n", 102 fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -109,7 +113,7 @@ static struct menu *current_menu, *current_entry;
109%% 113%%
110input: nl start | start; 114input: nl start | start;
111 115
112start: mainmenu_stmt stmt_list | no_mainmenu_stmt stmt_list; 116start: mainmenu_stmt stmt_list | stmt_list;
113 117
114/* mainmenu entry */ 118/* mainmenu entry */
115 119
@@ -118,19 +122,6 @@ mainmenu_stmt: T_MAINMENU prompt nl
118 menu_add_prompt(P_MENU, $2, NULL); 122 menu_add_prompt(P_MENU, $2, NULL);
119}; 123};
120 124
121/* Default main menu, if there's no mainmenu entry */
122
123no_mainmenu_stmt: /* empty */
124{
125 /*
126 * Hack: Keep the main menu title on the heap so we can safely free it
127 * later regardless of whether it comes from the 'prompt' in
128 * mainmenu_stmt or here
129 */
130 menu_add_prompt(P_MENU, xstrdup("Linux Kernel Configuration"), NULL);
131};
132
133
134stmt_list: 125stmt_list:
135 /* empty */ 126 /* empty */
136 | stmt_list common_stmt 127 | stmt_list common_stmt
@@ -156,6 +147,7 @@ common_stmt:
156 | config_stmt 147 | config_stmt
157 | menuconfig_stmt 148 | menuconfig_stmt
158 | source_stmt 149 | source_stmt
150 | assignment_stmt
159; 151;
160 152
161option_error: 153option_error:
@@ -524,31 +516,42 @@ symbol: nonconst_symbol
524word_opt: /* empty */ { $$ = NULL; } 516word_opt: /* empty */ { $$ = NULL; }
525 | T_WORD 517 | T_WORD
526 518
519/* assignment statement */
520
521assignment_stmt: T_VARIABLE T_ASSIGN assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); }
522
523assign_val:
524 /* empty */ { $$ = xstrdup(""); };
525 | T_ASSIGN_VAL
526;
527
527%% 528%%
528 529
529void conf_parse(const char *name) 530void conf_parse(const char *name)
530{ 531{
531 const char *tmp;
532 struct symbol *sym; 532 struct symbol *sym;
533 int i; 533 int i;
534 534
535 zconf_initscan(name); 535 zconf_initscan(name);
536 536
537 sym_init();
538 _menu_init(); 537 _menu_init();
539 538
540 if (getenv("ZCONF_DEBUG")) 539 if (getenv("ZCONF_DEBUG"))
541 yydebug = 1; 540 yydebug = 1;
542 yyparse(); 541 yyparse();
542
543 /* Variables are expanded in the parse phase. We can free them here. */
544 variable_all_del();
545
543 if (yynerrs) 546 if (yynerrs)
544 exit(1); 547 exit(1);
545 if (!modules_sym) 548 if (!modules_sym)
546 modules_sym = sym_find( "n" ); 549 modules_sym = sym_find( "n" );
547 550
548 tmp = rootmenu.prompt->text; 551 if (!menu_has_prompt(&rootmenu)) {
549 rootmenu.prompt->text = _(rootmenu.prompt->text); 552 current_entry = &rootmenu;
550 rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); 553 menu_add_prompt(P_MENU, "Main menu", NULL);
551 free((char*)tmp); 554 }
552 555
553 menu_finalize(&rootmenu); 556 menu_finalize(&rootmenu);
554 for_all_symbols(i, sym) { 557 for_all_symbols(i, sym) {
@@ -780,3 +783,4 @@ void zconfdump(FILE *out)
780#include "expr.c" 783#include "expr.c"
781#include "symbol.c" 784#include "symbol.c"
782#include "menu.c" 785#include "menu.c"
786#include "preprocess.c"