Commit 0ad39cb3 authored by Linus Torvalds's avatar Linus Torvalds

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()
  ...
parents 8715ee75 2ae89c7a
......@@ -198,14 +198,6 @@ applicable everywhere (see syntax).
enables the third modular state for all config symbols.
At most one symbol may have the "modules" option set.
- "env"=<value>
This imports the environment variable into Kconfig. It behaves like
a default, except that the value comes from the environment, this
also means that the behaviour when mixing it with normal defaults is
undefined at this point. The symbol is currently not exported back
to the build environment (if this is desired, it can be done via
another symbol).
- "allnoconfig_y"
This declares the symbol as one that should have the value y when
using "allnoconfig". Used for symbols that hide other symbols.
......
Concept
-------
The basic idea was inspired by Make. When we look at Make, we notice sort of
two languages in one. One language describes dependency graphs consisting of
targets and prerequisites. The other is a macro language for performing textual
substitution.
There is clear distinction between the two language stages. For example, you
can write a makefile like follows:
APP := foo
SRC := foo.c
CC := gcc
$(APP): $(SRC)
$(CC) -o $(APP) $(SRC)
The macro language replaces the variable references with their expanded form,
and handles as if the source file were input like follows:
foo: foo.c
gcc -o foo foo.c
Then, Make analyzes the dependency graph and determines the targets to be
updated.
The idea is quite similar in Kconfig - it is possible to describe a Kconfig
file like this:
CC := gcc
config CC_HAS_FOO
def_bool $(shell, $(srctree)/scripts/gcc-check-foo.sh $(CC))
The macro language in Kconfig processes the source file into the following
intermediate:
config CC_HAS_FOO
def_bool y
Then, Kconfig moves onto the evaluation stage to resolve inter-symbol
dependency as explained in kconfig-language.txt.
Variables
---------
Like in Make, a variable in Kconfig works as a macro variable. A macro
variable is expanded "in place" to yield a text string that may then be
expanded further. To get the value of a variable, enclose the variable name in
$( ). The parentheses are required even for single-letter variable names; $X is
a syntax error. The curly brace form as in ${CC} is not supported either.
There are two types of variables: simply expanded variables and recursively
expanded variables.
A simply expanded variable is defined using the := assignment operator. Its
righthand side is expanded immediately upon reading the line from the Kconfig
file.
A recursively expanded variable is defined using the = assignment operator.
Its righthand side is simply stored as the value of the variable without
expanding it in any way. Instead, the expansion is performed when the variable
is used.
There is another type of assignment operator; += is used to append text to a
variable. The righthand side of += is expanded immediately if the lefthand
side was originally defined as a simple variable. Otherwise, its evaluation is
deferred.
The variable reference can take parameters, in the following form:
$(name,arg1,arg2,arg3)
You can consider the parameterized reference as a function. (more precisely,
"user-defined function" in contrast to "built-in function" listed below).
Useful functions must be expanded when they are used since the same function is
expanded differently if different parameters are passed. Hence, a user-defined
function is defined using the = assignment operator. The parameters are
referenced within the body definition with $(1), $(2), etc.
In fact, recursively expanded variables and user-defined functions are the same
internally. (In other words, "variable" is "function with zero argument".)
When we say "variable" in a broad sense, it includes "user-defined function".
Built-in functions
------------------
Like Make, Kconfig provides several built-in functions. Every function takes a
particular number of arguments.
In Make, every built-in function takes at least one argument. Kconfig allows
zero argument for built-in functions, such as $(fileno), $(lineno). You could
consider those as "built-in variable", but it is just a matter of how we call
it after all. Let's say "built-in function" here to refer to natively supported
functionality.
Kconfig currently supports the following built-in functions.
- $(shell,command)
The "shell" function accepts a single argument that is expanded and passed
to a subshell for execution. The standard output of the command is then read
and returned as the value of the function. Every newline in the output is
replaced with a space. Any trailing newlines are deleted. The standard error
is not returned, nor is any program exit status.
- $(info,text)
The "info" function takes a single argument and prints it to stdout.
It evaluates to an empty string.
- $(warning-if,condition,text)
The "warning-if" function takes two arguments. If the condition part is "y",
the text part is sent to stderr. The text is prefixed with the name of the
current Kconfig file and the current line number.
- $(error-if,condition,text)
The "error-if" function is similar to "warning-if", but it terminates the
parsing immediately if the condition part is "y".
- $(filename)
The 'filename' takes no argument, and $(filename) is expanded to the file
name being parsed.
- $(lineno)
The 'lineno' takes no argument, and $(lineno) is expanded to the line number
being parsed.
Make vs Kconfig
---------------
Kconfig adopts Make-like macro language, but the function call syntax is
slightly different.
A function call in Make looks like this:
$(func-name arg1,arg2,arg3)
The function name and the first argument are separated by at least one
whitespace. Then, leading whitespaces are trimmed from the first argument,
while whitespaces in the other arguments are kept. You need to use a kind of
trick to start the first parameter with spaces. For example, if you want
to make "info" function print " hello", you can write like follows:
empty :=
space := $(empty) $(empty)
$(info $(space)$(space)hello)
Kconfig uses only commas for delimiters, and keeps all whitespaces in the
function call. Some people prefer putting a space after each comma delimiter:
$(func-name, arg1, arg2, arg3)
In this case, "func-name" will receive " arg1", " arg2", " arg3". The presence
of leading spaces may matter depending on the function. The same applies to
Make - for example, $(subst .c, .o, $(sources)) is a typical mistake; it
replaces ".c" with " .o".
In Make, a user-defined function is referenced by using a built-in function,
'call', like this:
$(call my-func,arg1,arg2,arg3)
Kconfig invokes user-defined functions and built-in functions in the same way.
The omission of 'call' makes the syntax shorter.
In Make, some functions treat commas verbatim instead of argument separators.
For example, $(shell echo hello, world) runs the command "echo hello, world".
Likewise, $(info hello, world) prints "hello, world" to stdout. You could say
this is _useful_ inconsistency.
In Kconfig, for simpler implementation and grammatical consistency, commas that
appear in the $( ) context are always delimiters. It means
$(shell, echo hello, world)
is an error because it is passing two parameters where the 'shell' function
accepts only one. To pass commas in arguments, you can use the following trick:
comma := ,
$(shell, echo hello$(comma) world)
Caveats
-------
A variable (or function) cannot be expanded across tokens. So, you cannot use
a variable as a shorthand for an expression that consists of multiple tokens.
The following works:
RANGE_MIN := 1
RANGE_MAX := 3
config FOO
int "foo"
range $(RANGE_MIN) $(RANGE_MAX)
But, the following does not work:
RANGES := 1 3
config FOO
int "foo"
range $(RANGES)
A variable cannot be expanded to any keyword in Kconfig. The following does
not work:
MY_TYPE := tristate
config FOO
$(MY_TYPE) "foo"
default y
Obviously from the design, $(shell command) is expanded in the textual
substitution phase. You cannot pass symbols to the 'shell' function.
The following does not work as expected.
config ENDIAN_FLAG
string
default "-mbig-endian" if CPU_BIG_ENDIAN
default "-mlittle-endian" if CPU_LITTLE_ENDIAN
config CC_HAS_ENDIAN_FLAG
def_bool $(shell $(srctree)/scripts/gcc-check-flag ENDIAN_FLAG)
Instead, you can do like follows so that any function call is statically
expanded.
config CC_HAS_ENDIAN_FLAG
bool
default $(shell $(srctree)/scripts/gcc-check-flag -mbig-endian) if CPU_BIG_ENDIAN
default $(shell $(srctree)/scripts/gcc-check-flag -mlittle-endian) if CPU_LITTLE_ENDIAN
......@@ -3,10 +3,10 @@
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/kconfig-language.txt.
#
mainmenu "Linux/$ARCH $KERNELVERSION Kernel Configuration"
mainmenu "Linux/$(ARCH) $(KERNELVERSION) Kernel Configuration"
config SRCARCH
string
option env="SRCARCH"
comment "Compiler: $(CC_VERSION_TEXT)"
source "arch/$SRCARCH/Kconfig"
source "scripts/Kconfig.include"
source "arch/$(SRCARCH)/Kconfig"
......@@ -7684,8 +7684,9 @@ M: Masahiro Yamada <yamada.masahiro@socionext.com>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git kconfig
L: linux-kbuild@vger.kernel.org
S: Maintained
F: Documentation/kbuild/kconfig-language.txt
F: Documentation/kbuild/kconfig*
F: scripts/kconfig/
F: scripts/Kconfig.include
KDUMP
M: Dave Young <dyoung@redhat.com>
......
......@@ -316,12 +316,9 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
# CROSS_COMPILE can be set on the command line
# make CROSS_COMPILE=ia64-linux-
# Alternatively CROSS_COMPILE can be set in the environment.
# A third alternative is to store a setting in .config so that plain
# "make" in the configured kernel build directory always uses that.
# Default value for CROSS_COMPILE is not to prefix executables
# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
# Architecture as present in compile.h
UTS_MACHINE := $(ARCH)
......@@ -445,6 +442,8 @@ export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
export KBUILD_ARFLAGS
export CC_VERSION_TEXT := $(shell $(CC) --version | head -n 1)
# When compiling out-of-tree modules, put MODVERDIR in the module
# tree rather than in the kernel tree. The kernel tree might
# even be read-only.
......@@ -504,7 +503,7 @@ KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
KBUILD_AFLAGS += $(call cc-option,-fno-PIE)
# check for 'asm goto'
ifeq ($(call shell-cached,$(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y)
ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y)
CC_HAVE_ASM_GOTO := 1
KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO
......@@ -807,7 +806,7 @@ KBUILD_CFLAGS_KERNEL += $(call cc-option,-fdata-sections,)
endif
# arch Makefile may override CC so keep this after arch Makefile is included
NOSTDINC_FLAGS += -nostdinc -isystem $(call shell-cached,$(CC) -print-file-name=include)
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
# warn about C99 declaration after statement
KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
......@@ -1630,7 +1629,6 @@ clean: $(clean-dirs)
-o -name '*.asn1.[ch]' \
-o -name '*.symtypes' -o -name 'modules.order' \
-o -name modules.builtin -o -name '.tmp_*.o.*' \
-o -name .cache.mk \
-o -name '*.c.[012]*.*' \
-o -name '*.ll' \
-o -name '*.gcno' \) -type f -print | xargs rm -f
......
......@@ -60,7 +60,7 @@ config SUPERH
<http://www.linux-sh.org/>.
config SUPERH32
def_bool ARCH = "sh"
def_bool "$(ARCH)" = "sh"
select HAVE_KPROBES
select HAVE_KRETPROBES
select HAVE_IOREMAP_PROT if MMU && !X2TLB
......@@ -79,7 +79,7 @@ config SUPERH32
select HAVE_CC_STACKPROTECTOR
config SUPERH64
def_bool ARCH = "sh64"
def_bool "$(ARCH)" = "sh64"
select HAVE_EXIT_THREAD
select KALLSYMS
......
config 64BIT
bool "64-bit kernel" if ARCH = "sparc"
default ARCH = "sparc64"
bool "64-bit kernel" if "$(ARCH)" = "sparc"
default "$(ARCH)" = "sparc64"
help
SPARC is a family of RISC microprocessors designed and marketed by
Sun Microsystems, incorporated. They are very widely found in Sun
......
......@@ -54,10 +54,6 @@ config HZ
int
default 100
config SUBARCH
string
option env="SUBARCH"
config NR_CPUS
int
range 1 1
......
# SPDX-License-Identifier: GPL-2.0
# Select 32 or 64 bit
config 64BIT
bool "64-bit kernel" if ARCH = "x86"
default ARCH != "i386"
bool "64-bit kernel" if "$(ARCH)" = "x86"
default "$(ARCH)" != "i386"
---help---
Say yes to build a 64-bit kernel - formerly known as x86_64
Say no to build a 32-bit kernel - formerly known as i386
......
# SPDX-License-Identifier: GPL-2.0
mainmenu "User Mode Linux/$SUBARCH $KERNELVERSION Kernel Configuration"
mainmenu "User Mode Linux/$(SUBARCH) $(KERNELVERSION) Kernel Configuration"
comment "Compiler: $(CC_VERSION_TEXT)"
source "scripts/Kconfig.include"
source "arch/um/Kconfig.common"
......@@ -16,8 +20,8 @@ config UML_X86
select GENERIC_FIND_FIRST_BIT
config 64BIT
bool "64-bit kernel" if SUBARCH = "x86"
default SUBARCH != "i386"
bool "64-bit kernel" if "$(SUBARCH)" = "x86"
default "$(SUBARCH)" != "i386"
config X86_32
def_bool !64BIT
......
config ARCH
string
option env="ARCH"
config KERNELVERSION
string
option env="KERNELVERSION"
config DEFCONFIG_LIST
string
depends on !UML
option defconfig_list
default "/lib/modules/$UNAME_RELEASE/.config"
default "/lib/modules/$(shell,uname --release)/.config"
default "/etc/kernel-config"
default "/boot/config-$UNAME_RELEASE"
default "$ARCH_DEFCONFIG"
default "arch/$ARCH/defconfig"
default "/boot/config-$(shell,uname --release)"
default ARCH_DEFCONFIG
default "arch/$(ARCH)/defconfig"
config CONSTRUCTORS
bool
......@@ -54,15 +46,6 @@ config INIT_ENV_ARG_LIMIT
Maximum of each of the number of arguments and environment
variables passed to init from the kernel command line.
config CROSS_COMPILE
string "Cross-compiler tool prefix"
help
Same as running 'make CROSS_COMPILE=prefix-' but stored for
default make runs in this kernel build directory. You don't
need to set this unless you want the configured kernel build
directory to select the cross-compiler automatically.
config COMPILE_TEST
bool "Compile also drivers which will not load"
depends on !UML
......
......@@ -8,8 +8,6 @@ squote := '
empty :=
space := $(empty) $(empty)
space_escape := _-_SPACE_-_
right_paren := )
left_paren := (
pound := \#
###
......@@ -57,7 +55,6 @@ kecho := $($(quiet)kecho)
# to specify a valid file as first prerequisite (often the kbuild file)
define filechk
$(Q)set -e; \
$(kecho) ' CHK $@'; \
mkdir -p $(dir $@); \
$(filechk_$(1)) < $< > $@.tmp; \
if [ -r $@ ] && cmp -s $@ $@.tmp; then \
......@@ -83,71 +80,6 @@ cc-cross-prefix = \
echo $(c); \
fi)))
# Tools for caching Makefile variables that are "expensive" to compute.
#
# Here we want to help deal with variables that take a long time to compute
# by making it easy to store these variables in a cache.
#
# The canonical example here is testing for compiler flags. On a simple system
# each call to the compiler takes 10 ms, but on a system with a compiler that's
# called through various wrappers it can take upwards of 100 ms. If we have
# 100 calls to the compiler this can take 1 second (on a simple system) or 10
# seconds (on a complicated system).
#
# The "cache" will be in Makefile syntax and can be directly included.
# Any time we try to reference a variable that's not in the cache we'll
# calculate it and store it in the cache for next time.
# Include values from last time
make-cache := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/,$(if $(obj),$(obj)/)).cache.mk
$(make-cache): ;
-include $(make-cache)
cached-data := $(filter __cached_%, $(.VARIABLES))
# If cache exceeds 1000 lines, shrink it down to 500.
ifneq ($(word 1000,$(cached-data)),)
$(shell tail -n 500 $(make-cache) > $(make-cache).tmp; \
mv $(make-cache).tmp $(make-cache))
endif
create-cache-dir := $(if $(KBUILD_SRC),$(if $(cache-data),,1))
# Usage: $(call __sanitize-opt,Hello=Hola$(comma)Goodbye Adios)
#
# Convert all '$', ')', '(', '\', '=', ' ', ',', ':' to '_'
__sanitize-opt = $(subst $$,_,$(subst $(right_paren),_,$(subst $(left_paren),_,$(subst \,_,$(subst =,_,$(subst $(space),_,$(subst $(comma),_,$(subst :,_,$(1)))))))))
# Usage: $(call shell-cached,shell_command)
# Example: $(call shell-cached,md5sum /usr/bin/gcc)
#
# If we've already seen a call to this exact shell command (even in a
# previous invocation of make!) we'll return the value. If not, we'll
# compute it and store the result for future runs.
#
# This is a bit of voodoo, but basic explanation is that if the variable
# was undefined then we'll evaluate the shell command and store the result
# into the variable. We'll then store that value in the cache and finally
# output the value.
#
# NOTE: The $$(2) here isn't actually a parameter to __run-and-store. We
# happen to know that the caller will have their shell command in $(2) so the
# result of "call"ing this will produce a reference to that $(2). The reason
# for this strangeness is to avoid an extra level of eval (and escaping) of
# $(2).
define __run-and-store
ifeq ($(origin $(1)),undefined)
$$(eval $(1) := $$(shell $$(2)))
ifeq ($(create-cache-dir),1)
$$(shell mkdir -p $(dir $(make-cache)))
$$(eval create-cache-dir :=)
endif
$$(shell echo '$(1) := $$($(1))' >> $(make-cache))
endif
endef
__shell-cached = $(eval $(call __run-and-store,$(1)))$($(1))
shell-cached = $(call __shell-cached,__cached_$(call __sanitize-opt,$(1)),$(1))
# output directory for tests below
TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
......@@ -155,36 +87,30 @@ TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
# Exit code chooses option. "$$TMP" serves as a temporary file and is
# automatically cleaned up.
__try-run = set -e; \
try-run = $(shell set -e; \
TMP="$(TMPOUT).$$$$.tmp"; \
TMPO="$(TMPOUT).$$$$.o"; \
if ($(1)) >/dev/null 2>&1; \
then echo "$(2)"; \
else echo "$(3)"; \
fi; \
rm -f "$$TMP" "$$TMPO"
try-run = $(shell $(__try-run))
# try-run-cached
# This works like try-run, but the result is cached.
try-run-cached = $(call shell-cached,$(__try-run))
rm -f "$$TMP" "$$TMPO")
# as-option
# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
as-option = $(call try-run-cached,\
as-option = $(call try-run,\
$(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2))
# as-instr
# Usage: cflags-y += $(call as-instr,instr,option1,option2)
as-instr = $(call try-run-cached,\
as-instr = $(call try-run,\
printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
# __cc-option
# Usage: MY_CFLAGS += $(call __cc-option,$(CC),$(MY_CFLAGS),-march=winchip-c6,-march=i586)
__cc-option = $(call try-run-cached,\
__cc-option = $(call try-run,\
$(1) -Werror $(2) $(3) -c -x c /dev/null -o "$$TMP",$(3),$(4))
# Do not attempt to build with gcc plugins during cc-option tests.
......@@ -204,23 +130,23 @@ hostcc-option = $(call __cc-option, $(HOSTCC),\
# cc-option-yn
# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
cc-option-yn = $(call try-run-cached,\
cc-option-yn = $(call try-run,\
$(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
# cc-disable-warning
# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
cc-disable-warning = $(call try-run-cached,\
cc-disable-warning = $(call try-run,\
$(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
# cc-name
# Expands to either gcc or clang
cc-name = $(call shell-cached,$(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc)
cc-name = $(shell $(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc)
# cc-version
cc-version = $(call shell-cached,$(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
# cc-fullversion
cc-fullversion = $(call shell-cached,$(CONFIG_SHELL) \
cc-fullversion = $(shell $(CONFIG_SHELL) \
$(srctree)/scripts/gcc-version.sh -p $(CC))
# cc-ifversion
......@@ -233,21 +159,21 @@ cc-if-fullversion = $(shell [ $(cc-fullversion) $(1) $(2) ] && echo $(3) || echo
# cc-ldoption
# Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both)
cc-ldoption = $(call try-run-cached,\
cc-ldoption = $(call try-run,\
$(CC) $(1) $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2))
# ld-option
# Usage: LDFLAGS += $(call ld-option, -X)
ld-option = $(call try-run-cached, $(LD) $(LDFLAGS) $(1) -v,$(1),$(2))
ld-option = $(call try-run, $(LD) $(LDFLAGS) $(1) -v,$(1),$(2))
# ar-option
# Usage: KBUILD_ARFLAGS := $(call ar-option,D)
# Important: no spaces around options
ar-option = $(call try-run-cached, $(AR) rc$(1) "$$TMP",$(1),$(2))
ar-option = $(call try-run, $(AR) rc$(1) "$$TMP",$(1),$(2))
# ld-version
# Note this is mainly for HJ Lu's 3 number binutil versions
ld-version = $(call shell-cached,$(LD) --version | $(srctree)/scripts/ld-version.sh)
ld-version = $(shell $(LD) --version | $(srctree)/scripts/ld-version.sh)
# ld-ifversion
# Usage: $(call ld-ifversion, -ge, 22252, y)
......
# Kconfig helper macros
# Convenient variables
comma := ,
quote := "
squote := '
empty :=
space := $(empty) $(empty)
dollar := $
right_paren := )
left_paren := (
# $(if-success,<command>,<then>,<else>)
# Return <then> if <command> exits with 0, <else> otherwise.
if-success = $(shell,{ $(1); } >/dev/null 2>&1 && echo "$(2)" || echo "$(3)")
# $(success,<command>)
# Return y if <command> exits with 0, n otherwise
success = $(if-success,$(1),y,n)
# $(cc-option,<flag>)
# Return y if the compiler supports <flag>, n otherwise
cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)
# $(ld-option,<flag>)
# Return y if the linker supports <flag>, n otherwise
ld-option = $(success,$(LD) -v $(1))
......@@ -2,9 +2,6 @@
# Generated files
#
*.moc
gconf.glade.h
*.pot
*.mo
#
# configuration programs
......@@ -14,4 +11,3 @@ mconf
nconf
qconf
gconf
kxgettext
......@@ -3,7 +3,7 @@
# Kernel configuration targets
# These targets are used from top-level makefile
PHONY += xconfig gconfig menuconfig config syncconfig update-po-config \
PHONY += xconfig gconfig menuconfig config syncconfig \
localmodconfig localyesconfig
ifdef KBUILD_KCONFIG
......@@ -55,29 +55,6 @@ localyesconfig localmodconfig: $(obj)/conf
fi
$(Q)rm -f .tmp.config
# Create new linux.pot file
# Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files
update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h
$(Q)$(kecho) " GEN config.pot"
$(Q)xgettext --default-domain=linux \
--add-comments --keyword=_ --keyword=N_ \
--from-code=UTF-8 \
--files-from=$(srctree)/scripts/kconfig/POTFILES.in \
--directory=$(srctree) --directory=$(objtree) \
--output $(obj)/config.pot
$(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot
$(Q)(for i in `ls $(srctree)/arch/*/Kconfig \
$(srctree)/arch/*/um/Kconfig`; \
do \
$(kecho) " GEN $$i"; \
$(obj)/kxgettext $$i \
>> $(obj)/config.pot; \
done )
$(Q)$(kecho) " GEN linux.pot"
$(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \
--output $(obj)/linux.pot
$(Q)rm -f $(obj)/config.pot
# These targets map 1:1 to the commandline options of 'conf'
simple-targets := oldconfig allnoconfig allyesconfig allmodconfig \
alldefconfig randconfig listnewconfig olddefconfig
......@@ -151,8 +128,7 @@ clean-dirs += tests/.cache
# Help text used by make help
help:
@echo ' config - Update current config utilising a line-oriented program'
@echo ' nconfig - Update current config utilising a ncurses menu based'
@echo ' program'
@echo ' nconfig - Update current config utilising a ncurses menu based program'
@echo ' menuconfig - Update current config utilising a menu based program'
@echo ' xconfig - Update current config utilising a Qt based front-end'
@echo ' gconfig - Update current config utilising a GTK+ based front-end'
......@@ -172,141 +148,77 @@ help:
@echo ' kvmconfig - Enable additional options for kvm guest kernel support'
@echo ' xenconfig - Enable additional options for xen dom0 and guest kernel support'
@echo ' tinyconfig - Configure the tiniest possible kernel'
# lxdialog stuff
check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
# Use recursively expanded variables so we do not call gcc unless
# we really need to do so. (Do not call gcc as part of make mrproper)
HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \
-DLOCALE
@echo ' testconfig - Run Kconfig unit tests (requires python3 and pytest)'
# ===========================================================================
# Shared Makefile for the various kconfig executables:
# conf: Used for defconfig, oldconfig and related targets
# nconf: Used for the nconfig target.
# Utilizes ncurses
# mconf: Used for the menuconfig target
# Utilizes the lxdialog package
# qconf: Used for the xconfig target
# Based on Qt which needs to be installed to compile it
# gconf: Used for the gconfig target
# Based on GTK+ which needs to be installed to compile it
# object files used by all kconfig flavours
lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o
lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o
conf-objs := conf.o zconf.tab.o
mconf-objs := mconf.o zconf.tab.o $(lxdialog)
nconf-objs := nconf.o zconf.tab.o nconf.gui.o
kxgettext-objs := kxgettext.o zconf.tab.o
qconf-cxxobjs := qconf.o
qconf-objs := zconf.tab.o
gconf-objs := gconf.o zconf.tab.o
hostprogs-y := conf nconf mconf kxgettext qconf gconf
hostprogs-y := conf
targets += zconf.lex.c
clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck
clean-files += gconf.glade.h
clean-files += config.pot linux.pot
# Check that we have the required ncurses stuff installed for lxdialog (menuconfig)
PHONY += $(obj)/dochecklxdialog
$(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/dochecklxdialog
$(obj)/dochecklxdialog:
$(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTLOADLIBES_mconf)
always := dochecklxdialog
# Add environment specific flags
HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS))
HOST_EXTRACXXFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCXX) $(HOSTCXXFLAGS))
# generated files seem to need this to find local include files
HOSTCFLAGS_zconf.lex.o := -I$(src)
HOSTCFLAGS_zconf.tab.o := -I$(src)
HOSTLOADLIBES_qconf = $(KC_QT_LIBS)
HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS)
HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0`
HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
-Wno-missing-prototypes
HOSTLOADLIBES_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
HOSTLOADLIBES_nconf = $(shell \
pkg-config --libs menuw panelw ncursesw 2>/dev/null \
|| pkg-config --libs menu panel ncurses 2>/dev/null \
|| echo "-lmenu -lpanel -lncurses" )
$(obj)/qconf.o: $(obj)/.tmp_qtcheck
ifeq ($(MAKECMDGOALS),xconfig)
$(obj)/.tmp_qtcheck: $(src)/Makefile
-include $(obj)/.tmp_qtcheck
# Qt needs some extra effort...
$(obj)/.tmp_qtcheck:
@set -e; $(kecho) " CHECK qt"; \
if pkg-config --exists Qt5Core; then \
cflags="-std=c++11 -fPIC `pkg-config --cflags Qt5Core Qt5Gui Qt5Widgets`"; \
libs=`pkg-config --libs Qt5Core Qt5Gui Qt5Widgets`; \
moc=`pkg-config --variable=host_bins Qt5Core`/moc; \
elif pkg-config --exists QtCore; then \
cflags=`pkg-config --cflags QtCore QtGui`; \
libs=`pkg-config --libs QtCore QtGui`; \
moc=`pkg-config --variable=moc_location QtCore`; \
else \
echo >&2 "*"; \
echo >&2 "* Could not find Qt via pkg-config."; \
echo >&2 "* Please install either Qt 4.8 or 5.x. and make sure it's in PKG_CONFIG_PATH"; \
echo >&2 "*"; \
exit 1; \
fi; \
echo "KC_QT_CFLAGS=$$cflags" > $@; \
echo "KC_QT_LIBS=$$libs" >> $@; \
echo "KC_QT_MOC=$$moc" >> $@
endif
# nconf: Used for the nconfig target based on ncurses
hostprogs-y += nconf
nconf-objs := nconf.o zconf.tab.o nconf.gui.o
$(obj)/gconf.o: $(obj)/.tmp_gtkcheck
ifeq ($(MAKECMDGOALS),gconfig)
-include $(obj)/.tmp_gtkcheck
# GTK+ needs some extra effort, too...
$(obj)/.tmp_gtkcheck:
@if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then \
if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \
touch $@; \
else \
echo >&2 "*"; \
echo >&2 "* GTK+ is present but version >= 2.0.0 is required."; \
echo >&2 "*"; \
false; \
fi \
else \
echo >&2 "*"; \
echo >&2 "* Unable to find the GTK+ installation. Please make sure that"; \
echo >&2 "* the GTK+ 2.0 development package is correctly installed..."; \
echo >&2 "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \
echo >&2 "*"; \
false; \
fi
endif
HOSTLOADLIBES_nconf = $(shell . $(obj)/.nconf-cfg && echo $$libs)
HOSTCFLAGS_nconf.o = $(shell . $(obj)/.nconf-cfg && echo $$cflags)
HOSTCFLAGS_nconf.gui.o = $(shell . $(obj)/.nconf-cfg && echo $$cflags)
$(obj)/zconf.tab.o: $(obj)/zconf.lex.c
$(obj)/nconf.o: $(obj)/.nconf-cfg
# mconf: Used for the menuconfig target based on lxdialog
hostprogs-y += mconf
lxdialog := checklist.o inputbox.o menubox.o textbox.o util.o yesno.o
mconf-objs := mconf.o zconf.tab.o $(addprefix lxdialog/, $(lxdialog))
$(obj)/qconf.o: $(obj)/qconf.moc
HOSTLOADLIBES_mconf = $(shell . $(obj)/.mconf-cfg && echo $$libs)
$(foreach f, mconf.o $(lxdialog), \
$(eval HOSTCFLAGS_$f = $$(shell . $(obj)/.mconf-cfg && echo $$$$cflags)))
$(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/.mconf-cfg
# qconf: Used for the xconfig target based on Qt
hostprogs-y += qconf
qconf-cxxobjs := qconf.o
qconf-objs := zconf.tab.o
HOSTLOADLIBES_qconf = $(shell . $(obj)/.qconf-cfg && echo $$libs)
HOSTCXXFLAGS_qconf.o = $(shell . $(obj)/.qconf-cfg && echo $$cflags)
$(obj)/qconf.o: $(obj)/.qconf-cfg $(obj)/qconf.moc
quiet_cmd_moc = MOC $@
cmd_moc = $(KC_QT_MOC) -i $< -o $@
cmd_moc = $(shell . $(obj)/.qconf-cfg && echo $$moc) -i $< -o $@
$(obj)/%.moc: $(src)/%.h $(obj)/.tmp_qtcheck
$(obj)/%.moc: $(src)/%.h $(obj)/.qconf-cfg
$(call cmd,moc)
# Extract gconf menu items for i18n support
$(obj)/gconf.glade.h: $(obj)/gconf.glade
$(Q)intltool-extract --type=gettext/glade --srcdir=$(srctree) \
$(obj)/gconf.glade
# gconf: Used for the gconfig target based on GTK+
hostprogs-y += gconf
gconf-objs := gconf.o zconf.tab.o
HOSTLOADLIBES_gconf = $(shell . $(obj)/.gconf-cfg && echo $$libs)
HOSTCFLAGS_gconf.o = $(shell . $(obj)/.gconf-cfg && echo $$cflags)
$(obj)/gconf.o: $(obj)/.gconf-cfg
$(obj)/zconf.tab.o: $(obj)/zconf.lex.c
# check if necessary packages are available, and configure build flags
define filechk_conf_cfg
$(CONFIG_SHELL) $<
endef
$(obj)/.%conf-cfg: $(src)/%conf-cfg.sh FORCE
$(call filechk,conf_cfg)
clean-files += .*conf-cfg
scripts/kconfig/lxdialog/checklist.c
scripts/kconfig/lxdialog/inputbox.c
scripts/kconfig/lxdialog/menubox.c
scripts/kconfig/lxdialog/textbox.c
scripts/kconfig/lxdialog/util.c
scripts/kconfig/lxdialog/yesno.c
scripts/kconfig/mconf.c
scripts/kconfig/conf.c
scripts/kconfig/confdata.c
scripts/kconfig/gconf.c
scripts/kconfig/gconf.glade.h
scripts/kconfig/qconf.cc
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Needed for systems without gettext
$* -x c -o /dev/null - > /dev/null 2>&1 << EOF
#include <libintl.h>
int main()
{
gettext("");
return 0;
}
EOF
if [ ! "$?" -eq "0" ]; then
echo -DKBUILD_NO_NLS;
fi
......@@ -3,7 +3,6 @@
* Released under the terms of the GNU GPL v2.0.
*/
#include <locale.h>
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
......@@ -86,7 +85,7 @@ static int conf_askvalue(struct symbol *sym, const char *def)
enum symbol_type type = sym_get_type(sym);
if (!sym_has_value(sym))
printf(_("(NEW) "));
printf("(NEW) ");
line[0] = '\n';
line[1] = 0;
......@@ -133,7 +132,7 @@ static int conf_string(struct menu *menu)
const char *def;
while (1) {
printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
printf("%*s%s ", indent - 1, "", menu->prompt->text);
printf("(%s) ", sym->name);
def = sym_get_string_value(sym);
if (sym_get_string_value(sym))
......@@ -166,7 +165,7 @@ static int conf_sym(struct menu *menu)
tristate oldval, newval;
while (1) {
printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
printf("%*s%s ", indent - 1, "", menu->prompt->text);
if (sym->name)
printf("(%s) ", sym->name);
putchar('[');
......@@ -251,7 +250,7 @@ static int conf_choice(struct menu *menu)
case no:
return 1;
case mod:
printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
return 0;
case yes:
break;
......@@ -261,7 +260,7 @@ static int conf_choice(struct menu *menu)
while (1) {
int cnt, def;
printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
def_sym = sym_get_choice_value(sym);
cnt = def = 0;
line[0] = 0;
......@@ -269,7 +268,7 @@ static int conf_choice(struct menu *menu)
if (!menu_is_visible(child))
continue;
if (!child->sym) {
printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
printf("%*c %s\n", indent, '*', menu_get_prompt(child));
continue;
}
cnt++;
......@@ -278,14 +277,14 @@ static int conf_choice(struct menu *menu)
printf("%*c", indent, '>');
} else
printf("%*c", indent, ' ');
printf(" %d. %s", cnt, _(menu_get_prompt(child)));
printf(" %d. %s", cnt, menu_get_prompt(child));
if (child->sym->name)
printf(" (%s)", child->sym->name);
if (!sym_has_value(child->sym))
printf(_(" (NEW)"));
printf(" (NEW)");
printf("\n");
}
printf(_("%*schoice"), indent - 1, "");
printf("%*schoice", indent - 1, "");
if (cnt == 1) {
printf("[1]: 1\n");
goto conf_childs;
......@@ -372,7 +371,7 @@ static void conf(struct menu *menu)
if (prompt)
printf("%*c\n%*c %s\n%*c\n",
indent, '*',
indent, '*', _(prompt),
indent, '*', prompt,
indent, '*');
default:
;
......@@ -437,7 +436,7 @@ static void check_conf(struct menu *menu)
}
} else {
if (!conf_cnt++)
printf(_("*\n* Restart config...\n*\n"));
printf("*\n* Restart config...\n*\n");
rootEntry = menu_get_parent_menu(menu);
conf(rootEntry);
}
......@@ -498,10 +497,6 @@ int main(int ac, char **av)
const char *name, *defconfig_file = NULL /* gcc uninit */;
struct stat tmpstat;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
tty_stdio = isatty(0) && isatty(1);
while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
......@@ -559,7 +554,7 @@ int main(int ac, char **av)
}
}
if (ac == optind) {
fprintf(stderr, _("%s: Kconfig file missing\n"), av[0]);
fprintf(stderr, "%s: Kconfig file missing\n", av[0]);
conf_usage(progname);
exit(1);
}
......@@ -569,12 +564,12 @@ int main(int ac, char **av)
if (sync_kconfig) {
name = conf_get_configname();
if (stat(name, &tmpstat)) {
fprintf(stderr, _("***\n"
fprintf(stderr, "***\n"
"*** Configuration file \"%s\" not found!\n"
"***\n"
"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
"*** \"make menuconfig\" or \"make xconfig\").\n"
"***\n"), name);
"***\n", name);
exit(1);
}
}
......@@ -585,9 +580,9 @@ int main(int ac, char **av)
defconfig_file = conf_get_default_confname();
if (conf_read(defconfig_file)) {
fprintf(stderr,
_("***\n"
"***\n"
"*** Can't find default configuration \"%s\"!\n"
"***\n"),
"***\n",
defconfig_file);
exit(1);
}
......@@ -611,7 +606,7 @@ int main(int ac, char **av)
if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
if (conf_read_simple(name, S_DEF_USER)) {
fprintf(stderr,
_("*** Can't read seed configuration \"%s\"!\n"),
"*** Can't read seed configuration \"%s\"!\n",
name);
exit(1);
}
......@@ -628,7 +623,7 @@ int main(int ac, char **av)
if (conf_read_simple(name, S_DEF_USER) &&
conf_read_simple("all.config", S_DEF_USER)) {
fprintf(stderr,
_("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
"*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n",
name);
exit(1);
}
......@@ -642,7 +637,7 @@ int main(int ac, char **av)
name = getenv("KCONFIG_NOSILENTUPDATE");
if (name && *name) {
fprintf(stderr,
_("\n*** The configuration requires explicit update.\n\n"));
"\n*** The configuration requires explicit update.\n\n");
return 1;
}
}
......@@ -694,22 +689,22 @@ int main(int ac, char **av)
* All other commands are only used to generate a config.
*/
if (conf_get_changed() && conf_write(NULL)) {
fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
fprintf(stderr, "\n*** Error during writing of the configuration.\n\n");
exit(1);
}
if (conf_write_autoconf()) {
fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
fprintf(stderr, "\n*** Error during update of the configuration.\n\n");
return 1;
}
} else if (input_mode == savedefconfig) {
if (conf_write_defconfig(defconfig_file)) {
fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n",
defconfig_file);
return 1;
}
} else if (input_mode != listnewconfig) {
if (conf_write(NULL)) {
fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
fprintf(stderr, "\n*** Error during writing of the configuration.\n\n");
exit(1);
}
}
......
......@@ -30,7 +30,7 @@ static void conf_message(const char *fmt, ...)
static const char *conf_filename;
static int conf_lineno, conf_warnings;
const char conf_defname[] = "arch/$ARCH/defconfig";
const char conf_defname[] = "arch/$(ARCH)/defconfig";
static void conf_warning(const char *fmt, ...)
{
......@@ -81,39 +81,13 @@ const char *conf_get_autoconfig_name(void)
return name ? name : "include/config/auto.conf";
}
static char *conf_expand_value(const char *in)
{
struct symbol *sym;
const char *src;
static char res_value[SYMBOL_MAXLENGTH];
char *dst, name[SYMBOL_MAXLENGTH];
res_value[0] = 0;
dst = name;
while ((src = strchr(in, '$'))) {
strncat(res_value, in, src - in);
src++;
dst = name;
while (isalnum(*src) || *src == '_')
*dst++ = *src++;
*dst = 0;
sym = sym_lookup(name, 0);
sym_calc_value(sym);
strcat(res_value, sym_get_string_value(sym));
in = src;
}
strcat(res_value, in);
return res_value;
}
char *conf_get_default_confname(void)
{
struct stat buf;
static char fullname[PATH_MAX+1];
char *env, *name;
name = conf_expand_value(conf_defname);
name = expand_string(conf_defname);
env = getenv(SRCTREE);
if (env) {
sprintf(fullname, "%s/%s", env, name);
......@@ -274,10 +248,11 @@ int conf_read_simple(const char *name, int def)
if (expr_calc_value(prop->visible.expr) == no ||
prop->expr->type != E_SYMBOL)
continue;
name = conf_expand_value(prop->expr->left.sym->name);
sym_calc_value(prop->expr->left.sym);
name = sym_get_string_value(prop->expr->left.sym);
in = zconf_fopen(name);
if (in) {
conf_message(_("using defaults found in %s"),
conf_message("using defaults found in %s",
name);
goto load;
}
......@@ -745,7 +720,7 @@ int conf_write(const char *name)
struct menu *menu;
const char *basename;
const char *str;
char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
char dirname[PATH_MAX+1], tmpname[PATH_MAX+22], newname[PATH_MAX+8];
char *env;
dirname[0] = 0;
......@@ -831,7 +806,7 @@ int conf_write(const char *name)
return 1;
}
conf_message(_("configuration written to %s"), newname);
conf_message("configuration written to %s", newname);
sym_set_change_count(0);
......
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
PKG="gtk+-2.0 gmodule-2.0 libglade-2.0"
if ! pkg-config --exists $PKG; then
echo >&2 "*"
echo >&2 "* Unable to find the GTK+ installation. Please make sure that"
echo >&2 "* the GTK+ 2.0 development package is correctly installed."
echo >&2 "* You need $PKG"
echo >&2 "*"
exit 1
fi
if ! pkg-config --atleast-version=2.0.0 gtk+-2.0; then
echo >&2 "*"
echo >&2 "* GTK+ is present but version >= 2.0.0 is required."
echo >&2 "*"
exit 1
fi
echo cflags=\"$(pkg-config --cflags $PKG)\"
echo libs=\"$(pkg-config --libs $PKG)\"
......@@ -137,7 +137,7 @@ void init_main_window(const gchar * glade_file)
xml = glade_xml_new(glade_file, "window1", NULL);
if (!xml)
g_error(_("GUI loading failed !\n"));
g_error("GUI loading failed !\n");
glade_xml_signal_autoconnect(xml);
main_wnd = glade_xml_get_widget(xml, "window1");
......@@ -233,7 +233,7 @@ void init_left_tree(void)
column = gtk_tree_view_column_new();
gtk_tree_view_append_column(view, column);
gtk_tree_view_column_set_title(column, _("Options"));
gtk_tree_view_column_set_title(column, "Options");
renderer = gtk_cell_renderer_toggle_new();
gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
......@@ -276,7 +276,7 @@ void init_right_tree(void)
column = gtk_tree_view_column_new();
gtk_tree_view_append_column(view, column);
gtk_tree_view_column_set_title(column, _("Options"));
gtk_tree_view_column_set_title(column, "Options");
renderer = gtk_cell_renderer_pixbuf_new();
gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column),
......@@ -305,7 +305,7 @@ void init_right_tree(void)
renderer = gtk_cell_renderer_text_new();
gtk_tree_view_insert_column_with_attributes(view, -1,
_("Name"), renderer,
"Name", renderer,
"text", COL_NAME,
"foreground-gdk",
COL_COLOR, NULL);
......@@ -329,7 +329,7 @@ void init_right_tree(void)
COL_COLOR, NULL);
renderer = gtk_cell_renderer_text_new();
gtk_tree_view_insert_column_with_attributes(view, -1,
_("Value"), renderer,
"Value", renderer,
"text", COL_VALUE,
"editable",
COL_EDIT,
......@@ -368,7 +368,7 @@ static void text_insert_help(struct menu *menu)
{
GtkTextBuffer *buffer;
GtkTextIter start, end;
const char *prompt = _(menu_get_prompt(menu));
const char *prompt = menu_get_prompt(menu);
struct gstr help = str_new();
menu_get_ext_help(menu, &help);
......@@ -422,7 +422,7 @@ gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
if (!conf_get_changed())
return FALSE;
dialog = gtk_dialog_new_with_buttons(_("Warning !"),
dialog = gtk_dialog_new_with_buttons("Warning !",
GTK_WINDOW(main_wnd),
(GtkDialogFlags)
(GTK_DIALOG_MODAL |
......@@ -436,7 +436,7 @@ gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event,
gtk_dialog_set_default_response(GTK_DIALOG(dialog),
GTK_RESPONSE_CANCEL);
label = gtk_label_new(_("\nSave configuration ?\n"));
label = gtk_label_new("\nSave configuration ?\n");
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
gtk_widget_show(label);
......@@ -496,7 +496,7 @@ load_filename(GtkFileSelection * file_selector, gpointer user_data)
(user_data));
if (conf_read(fn))
text_insert_msg(_("Error"), _("Unable to load configuration !"));
text_insert_msg("Error", "Unable to load configuration !");
else
display_tree(&rootmenu);
}
......@@ -505,7 +505,7 @@ void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
{
GtkWidget *fs;
fs = gtk_file_selection_new(_("Load file..."));
fs = gtk_file_selection_new("Load file...");
g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
"clicked",
G_CALLBACK(load_filename), (gpointer) fs);
......@@ -524,7 +524,7 @@ void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data)
void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
{
if (conf_write(NULL))
text_insert_msg(_("Error"), _("Unable to save configuration !"));
text_insert_msg("Error", "Unable to save configuration !");
}
......@@ -537,7 +537,7 @@ store_filename(GtkFileSelection * file_selector, gpointer user_data)
(user_data));
if (conf_write(fn))
text_insert_msg(_("Error"), _("Unable to save configuration !"));
text_insert_msg("Error", "Unable to save configuration !");
gtk_widget_destroy(GTK_WIDGET(user_data));
}
......@@ -546,7 +546,7 @@ void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data)
{
GtkWidget *fs;
fs = gtk_file_selection_new(_("Save file as..."));
fs = gtk_file_selection_new("Save file as...");
g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button),
"clicked",
G_CALLBACK(store_filename), (gpointer) fs);
......@@ -639,7 +639,7 @@ on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data)
void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
{
GtkWidget *dialog;
const gchar *intro_text = _(
const gchar *intro_text =
"Welcome to gkc, the GTK+ graphical configuration tool\n"
"For each option, a blank box indicates the feature is disabled, a\n"
"check indicates it is enabled, and a dot indicates that it is to\n"
......@@ -654,7 +654,7 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
"option.\n"
"\n"
"Toggling Show Debug Info under the Options menu will show \n"
"the dependencies, which you can then match by examining other options.");
"the dependencies, which you can then match by examining other options.";
dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
GTK_DIALOG_DESTROY_WITH_PARENT,
......@@ -671,8 +671,8 @@ void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
{
GtkWidget *dialog;
const gchar *about_text =
_("gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
"Based on the source code from Roman Zippel.\n");
"gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
"Based on the source code from Roman Zippel.\n";
dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
GTK_DIALOG_DESTROY_WITH_PARENT,
......@@ -689,9 +689,9 @@ void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
{
GtkWidget *dialog;
const gchar *license_text =
_("gkc is released under the terms of the GNU GPL v2.\n"
"gkc is released under the terms of the GNU GPL v2.\n"
"For more information, please see the source code or\n"
"visit http://www.fsf.org/licenses/licenses.html\n");
"visit http://www.fsf.org/licenses/licenses.html\n";
dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
GTK_DIALOG_DESTROY_WITH_PARENT,
......@@ -1049,7 +1049,7 @@ static gchar **fill_row(struct menu *menu)
bzero(row, sizeof(row));
row[COL_OPTION] =
g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
g_strdup_printf("%s %s", menu_get_prompt(menu),
sym && !sym_has_value(sym) ? "(NEW)" : "");
if (opt_mode == OPT_ALL && !menu_is_visible(menu))
......@@ -1102,7 +1102,7 @@ static gchar **fill_row(struct menu *menu)
if (def_menu)
row[COL_VALUE] =
g_strdup(_(menu_get_prompt(def_menu)));
g_strdup(menu_get_prompt(def_menu));
}
if (sym->flags & SYMBOL_CHOICEVAL)
row[COL_BTNRAD] = GINT_TO_POINTER(TRUE);
......@@ -1447,10 +1447,6 @@ int main(int ac, char *av[])
char *env;
gchar *glade_file;
bindtextdomain(PACKAGE, LOCALEDIR);
bind_textdomain_codeset(PACKAGE, "UTF-8");
textdomain(PACKAGE);
/* GTK stuffs */
gtk_set_locale();
gtk_init(&ac, &av);
......
......@@ -32,7 +32,6 @@ static struct kconf_id kconf_id_array[] = {
{ "on", T_ON, TF_PARAM },
{ "modules", T_OPT_MODULES, TF_OPTION },
{ "defconfig_list", T_OPT_DEFCONFIG_LIST, TF_OPTION },
{ "env", T_OPT_ENV, TF_OPTION },
{ "allnoconfig_y", T_OPT_ALLNOCONFIG_Y, TF_OPTION },
};
......
/*
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005
*
* Released under the terms of the GNU GPL v2.0
*/
#include <stdlib.h>
#include <string.h>
#include "lkc.h"
static char *escape(const char* text, char *bf, int len)
{
char *bfp = bf;
int multiline = strchr(text, '\n') != NULL;
int eol = 0;
int textlen = strlen(text);
if ((textlen > 0) && (text[textlen-1] == '\n'))
eol = 1;
*bfp++ = '"';
--len;
if (multiline) {
*bfp++ = '"';
*bfp++ = '\n';
*bfp++ = '"';
len -= 3;
}
while (*text != '\0' && len > 1) {
if (*text == '"')
*bfp++ = '\\';
else if (*text == '\n') {
*bfp++ = '\\';
*bfp++ = 'n';
*bfp++ = '"';
*bfp++ = '\n';
*bfp++ = '"';
len -= 5;
++text;
goto next;
}
else if (*text == '\\') {
*bfp++ = '\\';
len--;
}
*bfp++ = *text++;
next:
--len;
}
if (multiline && eol)
bfp -= 3;
*bfp++ = '"';
*bfp = '\0';
return bf;
}
struct file_line {
struct file_line *next;
const char *file;
int lineno;
};
static struct file_line *file_line__new(const char *file, int lineno)
{
struct file_line *self = malloc(sizeof(*self));
if (self == NULL)
goto out;
self->file = file;
self->lineno = lineno;
self->next = NULL;
out:
return self;
}
struct message {
const char *msg;
const char *option;
struct message *next;
struct file_line *files;
};
static struct message *message__list;
static struct message *message__new(const char *msg, char *option,
const char *file, int lineno)
{
struct message *self = malloc(sizeof(*self));
if (self == NULL)
goto out;
self->files = file_line__new(file, lineno);
if (self->files == NULL)
goto out_fail;
self->msg = xstrdup(msg);
if (self->msg == NULL)
goto out_fail_msg;
self->option = option;
self->next = NULL;
out:
return self;
out_fail_msg:
free(self->files);
out_fail:
free(self);
self = NULL;
goto out;
}
static struct message *mesage__find(const char *msg)
{
struct message *m = message__list;
while (m != NULL) {
if (strcmp(m->msg, msg) == 0)
break;
m = m->next;
}
return m;
}
static int message__add_file_line(struct message *self, const char *file,
int lineno)
{
int rc = -1;
struct file_line *fl = file_line__new(file, lineno);
if (fl == NULL)
goto out;
fl->next = self->files;
self->files = fl;
rc = 0;
out:
return rc;
}
static int message__add(const char *msg, char *option, const char *file,
int lineno)
{
int rc = 0;
char bf[16384];
char *escaped = escape(msg, bf, sizeof(bf));
struct message *m = mesage__find(escaped);
if (m != NULL)
rc = message__add_file_line(m, file, lineno);
else {
m = message__new(escaped, option, file, lineno);
if (m != NULL) {
m->next = message__list;
message__list = m;
} else
rc = -1;
}
return rc;
}
static void menu_build_message_list(struct menu *menu)
{
struct menu *child;
message__add(menu_get_prompt(menu), NULL,
menu->file == NULL ? "Root Menu" : menu->file->name,
menu->lineno);
if (menu->sym != NULL && menu_has_help(menu))
message__add(menu_get_help(menu), menu->sym->name,
menu->file == NULL ? "Root Menu" : menu->file->name,
menu->lineno);
for (child = menu->list; child != NULL; child = child->next)
if (child->prompt != NULL)
menu_build_message_list(child);
}
static void message__print_file_lineno(struct message *self)
{
struct file_line *fl = self->files;
putchar('\n');
if (self->option != NULL)
printf("# %s:00000\n", self->option);
printf("#: %s:%d", fl->file, fl->lineno);
fl = fl->next;
while (fl != NULL) {
printf(", %s:%d", fl->file, fl->lineno);
fl = fl->next;
}
putchar('\n');
}
static void message__print_gettext_msgid_msgstr(struct message *self)
{
message__print_file_lineno(self);
printf("msgid %s\n"
"msgstr \"\"\n", self->msg);
}
static void menu__xgettext(void)
{
struct message *m = message__list;
while (m != NULL) {
/* skip empty lines ("") */
if (strlen(m->msg) > sizeof("\"\""))
message__print_gettext_msgid_msgstr(m);
m = m->next;
}
}
int main(int ac, char **av)
{
conf_parse(av[1]);
menu_build_message_list(menu_get_root_menu(NULL));
menu__xgettext();
return 0;
}
......@@ -8,15 +8,6 @@
#include "expr.h"
#ifndef KBUILD_NO_NLS
# include <libintl.h>
#else
static inline const char *gettext(const char *txt) { return txt; }
static inline void textdomain(const char *domainname) {}
static inline void bindtextdomain(const char *name, const char *dir) {}
static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; }
#endif
#ifdef __cplusplus
extern "C" {
#endif
......@@ -29,11 +20,6 @@ extern "C" {
#define PACKAGE "linux"
#endif
#define LOCALEDIR "/usr/share/locale"
#define _(text) gettext(text)
#define N_(text) (text)
#ifndef CONFIG_
#define CONFIG_ "CONFIG_"
#endif
......@@ -58,7 +44,6 @@ enum conf_def_mode {
#define T_OPT_MODULES 1
#define T_OPT_DEFCONFIG_LIST 2
#define T_OPT_ENV 3
#define T_OPT_ALLNOCONFIG_Y 4
struct kconf_id {
......@@ -117,6 +102,7 @@ void *xmalloc(size_t size);
void *xcalloc(size_t nmemb, size_t size);
void *xrealloc(void *p, size_t size);
char *xstrdup(const char *s);
char *xstrndup(const char *s, size_t n);
struct gstr {
size_t len;
......@@ -134,9 +120,6 @@ void str_printf(struct gstr *gs, const char *fmt, ...);
const char *str_get(struct gstr *gs);
/* symbol.c */
extern struct expr *sym_env_list;
void sym_init(void);
void sym_clear_all_valid(void);
struct symbol *sym_choice_default(struct symbol *sym);
const char *sym_get_string_default(struct symbol *sym);
......
......@@ -31,7 +31,6 @@ extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
struct symbol * sym_lookup(const char *name, int flags);
struct symbol * sym_find(const char *name);
char *sym_expand_string_value(const char *in);
const char * sym_escape_string_value(const char *in);
struct symbol ** sym_re_search(const char *pattern);
const char * sym_type_name(enum symbol_type type);
......@@ -49,5 +48,19 @@ const char * sym_get_string_value(struct symbol *sym);
const char * prop_get_type_name(enum prop_type type);
/* preprocess.c */
enum variable_flavor {
VAR_SIMPLE,
VAR_RECURSIVE,
VAR_APPEND,
};
void env_write_dep(FILE *f, const char *auto_conf_name);
void variable_add(const char *name, const char *value,
enum variable_flavor flavor);
void variable_all_del(void);
char *expand_string(const char *in);
char *expand_dollar(const char **str);
char *expand_one_token(const char **str);
/* expr.c */
void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Check ncurses compatibility
# What library to link
ldflags()
{
pkg-config --libs ncursesw 2>/dev/null && exit
pkg-config --libs ncurses 2>/dev/null && exit
for ext in so a dll.a dylib ; do
for lib in ncursesw ncurses curses ; do
$cc -print-file-name=lib${lib}.${ext} | grep -q /
if [ $? -eq 0 ]; then
echo "-l${lib}"
exit
fi
done
done
exit 1
}
# Where is ncurses.h?
ccflags()
{
if pkg-config --cflags ncursesw 2>/dev/null; then
echo '-DCURSES_LOC="<ncurses.h>" -DNCURSES_WIDECHAR=1'
elif pkg-config --cflags ncurses 2>/dev/null; then
echo '-DCURSES_LOC="<ncurses.h>"'
elif [ -f /usr/include/ncursesw/curses.h ]; then
echo '-I/usr/include/ncursesw -DCURSES_LOC="<curses.h>"'
echo ' -DNCURSES_WIDECHAR=1'
elif [ -f /usr/include/ncurses/ncurses.h ]; then
echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
elif [ -f /usr/include/ncurses/curses.h ]; then
echo '-I/usr/include/ncurses -DCURSES_LOC="<curses.h>"'
elif [ -f /usr/include/ncurses.h ]; then
echo '-DCURSES_LOC="<ncurses.h>"'
else
echo '-DCURSES_LOC="<curses.h>"'
fi
}
# Temp file, try to clean up after us
tmp=.lxdialog.tmp
trap "rm -f $tmp" 0 1 2 3 15
# Check if we can link to ncurses
check() {
$cc -x c - -o $tmp 2>/dev/null <<'EOF'
#include CURSES_LOC
main() {}
EOF
if [ $? != 0 ]; then
echo " *** Unable to find the ncurses libraries or the" 1>&2
echo " *** required header files." 1>&2
echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2
echo " *** " 1>&2
echo " *** Install ncurses (ncurses-devel or libncurses-dev " 1>&2
echo " *** depending on your distribution) and try again." 1>&2
echo " *** " 1>&2
exit 1
fi
}
usage() {
printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n"
}
if [ $# -eq 0 ]; then
usage
exit 1
fi
cc=""
case "$1" in
"-check")
shift
cc="$@"
check
;;
"-ccflags")
ccflags
;;
"-ldflags")
shift
cc="$@"
ldflags
;;
"*")
usage
exit 1
;;
esac
......@@ -103,8 +103,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
int x = width / 2 - 11;
int y = height - 2;
print_button(dialog, gettext("Select"), y, x, selected == 0);
print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
print_button(dialog, "Select", y, x, selected == 0);
print_button(dialog, " Help ", y, x + 14, selected == 1);
wmove(dialog, y, x + 1 + 14 * selected);
wrefresh(dialog);
......
......@@ -26,16 +26,10 @@
#include <string.h>
#include <stdbool.h>
#ifndef KBUILD_NO_NLS
# include <libintl.h>
#else
# define gettext(Msgid) ((const char *) (Msgid))
#endif
#ifdef __sun__
#define CURS_MACROS
#endif
#include CURSES_LOC
#include <ncurses.h>
/*
* Colors in ncurses 1.9.9e do not work properly since foreground and
......
......@@ -31,8 +31,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
int x = width / 2 - 11;
int y = height - 2;
print_button(dialog, gettext(" Ok "), y, x, selected == 0);
print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
print_button(dialog, " Ok ", y, x, selected == 0);
print_button(dialog, " Help ", y, x + 14, selected == 1);
wmove(dialog, y, x + 1 + 14 * selected);
wrefresh(dialog);
......
......@@ -157,11 +157,11 @@ static void print_buttons(WINDOW * win, int height, int width, int selected)
int x = width / 2 - 28;
int y = height - 2;
print_button(win, gettext("Select"), y, x, selected == 0);
print_button(win, gettext(" Exit "), y, x + 12, selected == 1);
print_button(win, gettext(" Help "), y, x + 24, selected == 2);
print_button(win, gettext(" Save "), y, x + 36, selected == 3);
print_button(win, gettext(" Load "), y, x + 48, selected == 4);
print_button(win, "Select", y, x, selected == 0);
print_button(win, " Exit ", y, x + 12, selected == 1);
print_button(win, " Help ", y, x + 24, selected == 2);
print_button(win, " Save ", y, x + 36, selected == 3);
print_button(win, " Load ", y, x + 48, selected == 4);
wmove(win, y, x + 1 + 12 * selected);
wrefresh(win);
......
......@@ -129,7 +129,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height,
print_title(dialog, title, width);
print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE);
print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
wnoutrefresh(dialog);
getyx(dialog, cur_y, cur_x); /* Save cursor position */
......
......@@ -29,8 +29,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
int x = width / 2 - 10;
int y = height - 2;
print_button(dialog, gettext(" Yes "), y, x, selected == 0);
print_button(dialog, gettext(" No "), y, x + 13, selected == 1);
print_button(dialog, " Yes ", y, x, selected == 0);
print_button(dialog, " No ", y, x + 13, selected == 1);
wmove(dialog, y, x + 1 + 13 * selected);
wrefresh(dialog);
......
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
PKG="ncursesw"
PKG2="ncurses"
if pkg-config --exists $PKG; then
echo cflags=\"$(pkg-config --cflags $PKG)\"
echo libs=\"$(pkg-config --libs $PKG)\"
exit 0
fi
if pkg-config --exists $PKG2; then
echo cflags=\"$(pkg-config --cflags $PKG2)\"
echo libs=\"$(pkg-config --libs $PKG2)\"
exit 0
fi
# Unfortunately, some distributions (e.g. openSUSE) cannot find ncurses
# by pkg-config.
if [ -f /usr/include/ncursesw/ncurses.h ]; then
echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\"
echo libs=\"-lncursesw\"
exit 0
fi
if [ -f /usr/include/ncurses/ncurses.h ]; then
echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\"
echo libs=\"-lncurses\"
exit 0
fi
if [ -f /usr/include/ncurses.h ]; then
echo cflags=\"-D_GNU_SOURCE\"
echo libs=\"-lncurses\"
exit 0
fi
echo >&2 "*"
echo >&2 "* Unable to find the ncurses package."
echo >&2 "* Install ncurses (ncurses-devel or libncurses-dev"
echo >&2 "* depending on your distribution)."
echo >&2 "*"
exit 1
This diff is collapsed.
......@@ -214,9 +214,6 @@ void menu_add_option(int token, char *arg)
zconf_error("trying to redefine defconfig symbol");
sym_defconfig_list->flags |= SYMBOL_AUTO;
break;
case T_OPT_ENV:
prop_add_env(arg);
break;
case T_OPT_ALLNOCONFIG_Y:
current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
break;
......@@ -711,7 +708,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
struct menu *submenu[8], *menu, *location = NULL;
struct jump_key *jump = NULL;
str_printf(r, _("Prompt: %s\n"), _(prop->text));
str_printf(r, "Prompt: %s\n", prop->text);
menu = prop->menu->parent;
for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
bool accessible = menu_is_visible(menu);
......@@ -744,16 +741,16 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
}
if (i > 0) {
str_printf(r, _(" Location:\n"));
str_printf(r, " Location:\n");
for (j = 4; --i >= 0; j += 2) {
menu = submenu[i];
if (jump && menu == location)
jump->offset = strlen(r->s);
str_printf(r, "%*c-> %s", j, ' ',
_(menu_get_prompt(menu)));
menu_get_prompt(menu));
if (menu->sym) {
str_printf(r, " (%s [=%s])", menu->sym->name ?
menu->sym->name : _("<choice>"),
menu->sym->name : "<choice>",
sym_get_string_value(menu->sym));
}
str_append(r, "\n");
......@@ -817,23 +814,23 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
prop = get_symbol_prop(sym);
if (prop) {
str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name,
str_printf(r, " Defined at %s:%d\n", prop->menu->file->name,
prop->menu->lineno);
if (!expr_is_yes(prop->visible.expr)) {
str_append(r, _(" Depends on: "));
str_append(r, " Depends on: ");
expr_gstr_print(prop->visible.expr, r);
str_append(r, "\n");
}
}
get_symbol_props_str(r, sym, P_SELECT, _(" Selects: "));
get_symbol_props_str(r, sym, P_SELECT, " Selects: ");
if (sym->rev_dep.expr) {
expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, " Selected by [y]:\n");
expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, " Selected by [m]:\n");
expr_gstr_print_revdep(sym->rev_dep.expr, r, no, " Selected by [n]:\n");
}
get_symbol_props_str(r, sym, P_IMPLY, _(" Implies: "));
get_symbol_props_str(r, sym, P_IMPLY, " Implies: ");
if (sym->implied.expr) {
expr_gstr_print_revdep(sym->implied.expr, r, yes, " Implied by [y]:\n");
expr_gstr_print_revdep(sym->implied.expr, r, mod, " Implied by [m]:\n");
......@@ -852,7 +849,7 @@ struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
get_symbol_str(&res, sym, head);
if (!i)
str_append(&res, _("No matches found.\n"));
str_append(&res, "No matches found.\n");
return res;
}
......@@ -867,7 +864,7 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
help_text = menu_get_help(menu);
}
str_printf(help, "%s\n", _(help_text));
str_printf(help, "%s\n", help_text);
if (sym)
get_symbol_str(help, sym, NULL);
}
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
PKG="ncursesw menuw panelw"
PKG2="ncurses menu panel"
if pkg-config --exists $PKG; then
echo cflags=\"$(pkg-config --cflags $PKG)\"
echo libs=\"$(pkg-config --libs $PKG)\"
exit 0
fi
if pkg-config --exists $PKG2; then
echo cflags=\"$(pkg-config --cflags $PKG2)\"
echo libs=\"$(pkg-config --libs $PKG2)\"
exit 0
fi
# Unfortunately, some distributions (e.g. openSUSE) cannot find ncurses
# by pkg-config.
if [ -f /usr/include/ncursesw/ncurses.h ]; then
echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncursesw\"
echo libs=\"-lncursesw -lmenuw -lpanelw\"
exit 0
fi
if [ -f /usr/include/ncurses/ncurses.h ]; then
echo cflags=\"-D_GNU_SOURCE -I/usr/include/ncurses\"
echo libs=\"-lncurses -lmenu -lpanel\"
exit 0
fi
if [ -f /usr/include/ncurses.h ]; then
echo cflags=\"-D_GNU_SOURCE\"
echo libs=\"-lncurses -lmenu -lpanel\"
exit 0
fi
echo >&2 "*"
echo >&2 "* Unable to find the ncurses package."
echo >&2 "* Install ncurses (ncurses-devel or libncurses-dev"
echo >&2 "* depending on your distribution)."
echo >&2 "*"
exit 1
This diff is collapsed.
......@@ -14,7 +14,6 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <locale.h>
#include <ncurses.h>
#include <menu.h>
#include <panel.h>
......
This diff is collapsed.
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
PKG="Qt5Core Qt5Gui Qt5Widgets"
PKG2="QtCore QtGui"
if pkg-config --exists $PKG; then
echo cflags=\"-std=c++11 -fPIC $(pkg-config --cflags Qt5Core Qt5Gui Qt5Widgets)\"
echo libs=\"$(pkg-config --libs $PKG)\"
echo moc=\"$(pkg-config --variable=host_bins Qt5Core)/moc\"
exit 0
fi
if pkg-config --exists $PKG2; then
echo cflags=\"$(pkg-config --cflags $PKG2)\"
echo libs=\"$(pkg-config --libs $PKG2)\"
echo moc=\"$(pkg-config --variable=moc_location QtCore)\"
exit 0
fi
echo >&2 "*"
echo >&2 "* Could not find Qt via pkg-config."
echo >&2 "* Please install either Qt 4.8 or 5.x. and make sure it's in PKG_CONFIG_PATH"
echo >&2 "*"
exit 1
This diff is collapsed.
......@@ -33,33 +33,6 @@ struct symbol *sym_defconfig_list;
struct symbol *modules_sym;
tristate modules_val;
struct expr *sym_env_list;
static void sym_add_default(struct symbol *sym, const char *def)
{
struct property *prop = prop_alloc(P_DEFAULT, sym);
prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
}
void sym_init(void)
{
struct symbol *sym;
struct utsname uts;
static bool inited = false;
if (inited)
return;
inited = true;
uname(&uts);
sym = sym_lookup("UNAME_RELEASE", 0);
sym->type = S_STRING;
sym->flags |= SYMBOL_AUTO;
sym_add_default(sym, uts.release);
}
enum symbol_type sym_get_type(struct symbol *sym)
{
enum symbol_type type = sym->type;
......@@ -906,59 +879,6 @@ struct symbol *sym_find(const char *name)
return symbol;
}
/*
* Expand symbol's names embedded in the string given in argument. Symbols'
* name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
* the empty string.
*/
char *sym_expand_string_value(const char *in)
{
const char *src;
char *res;
size_t reslen;
/*
* Note: 'in' might come from a token that's about to be
* freed, so make sure to always allocate a new string
*/
reslen = strlen(in) + 1;
res = xmalloc(reslen);
res[0] = '\0';
while ((src = strchr(in, '$'))) {
char *p, name[SYMBOL_MAXLENGTH];
const char *symval = "";
struct symbol *sym;
size_t newlen;
strncat(res, in, src - in);
src++;
p = name;
while (isalnum(*src) || *src == '_')
*p++ = *src++;
*p = '\0';
sym = sym_find(name);
if (sym != NULL) {
sym_calc_value(sym);
symval = sym_get_string_value(sym);
}
newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
if (newlen > reslen) {
reslen = newlen;
res = xrealloc(res, reslen);
}
strcat(res, symval);
in = src;
}
strcat(res, in);
return res;
}
const char *sym_escape_string_value(const char *in)
{
const char *p;
......@@ -1401,32 +1321,3 @@ const char *prop_get_type_name(enum prop_type type)
}
return "unknown";
}
static void prop_add_env(const char *env)
{
struct symbol *sym, *sym2;
struct property *prop;
char *p;
sym = current_entry->sym;
sym->flags |= SYMBOL_AUTO;
for_all_properties(sym, prop, P_ENV) {
sym2 = prop_get_symbol(prop);
if (strcmp(sym2->name, env))
menu_warn(current_entry, "redefining environment symbol from %s",
sym2->name);
return;
}
prop = prop_alloc(P_ENV, sym);
prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
sym_env_list->right.sym = sym;
p = getenv(env);
if (p)
sym_add_default(sym, p);
else
menu_warn(current_entry, "environment variable %s undefined", env);
}
#
# Automatically generated file; DO NOT EDIT.
# Linux Kernel Configuration
# Main menu
#
# CONFIG_A is not set
# SPDX-License-Identifier: GPL-2.0
# 'info' prints the argument to stdout.
$(info,hello world 0)
# 'warning-if', if the first argument is y, sends the second argument to stderr,
# and the message is prefixed with the current file name and line number.
$(warning-if,y,hello world 1)
# 'error-if' is similar, but it terminates the parsing immediately.
# The following is just no-op since the first argument is not y.
$(error-if,n,this should not be printed)
# Shorthand
warning = $(warning-if,y,$(1))
# 'shell' executes a command, and returns its stdout.
$(warning,$(shell,echo hello world 3))
# Every newline in the output is replaced with a space,
# but any trailing newlines are deleted.
$(warning,$(shell,printf 'hello\nworld\n\n4\n\n\n'))
# 'filename' is expanded to the currently parsed file name,
# 'lineno' to the line number.
$(warning,filename=$(filename))
$(warning,lineno=$(lineno))
# SPDX-License-Identifier: GPL-2.0
"""
Built-in function tests.
"""
def test(conf):
assert conf.oldaskconfig() == 0
assert conf.stdout_contains('expected_stdout')
assert conf.stderr_matches('expected_stderr')
Kconfig:8: hello world 1
Kconfig:18: hello world 3
Kconfig:22: hello world 4
Kconfig:26: filename=Kconfig
Kconfig:27: lineno=27
# SPDX-License-Identifier: GPL-2.0
X = $(Y)
Y = $(X)
$(info $(X))
# SPDX-License-Identifier: GPL-2.0
"""
Detect circular variable expansion.
If a recursively expanded variable references itself (eventually),
it should fail with an error message.
"""
def test(conf):
assert conf.oldaskconfig() != 0
assert conf.stderr_matches('expected_stderr')
Kconfig:5: Recursive variable 'X' references itself (eventually)
# SPDX-License-Identifier: GPL-2.0
# Shorthand
warning = $(warning-if,y,$(1))
# You can not pass commas directly to a function since they are treated as
# delimiters. You can use the following trick to do so.
comma := ,
$(warning,hello$(comma) world)
# Like Make, single quotes, double quotes, spaces are treated verbatim.
# The following prints the text as-is.
$(warning, ' " '" ' ''' "'")
# Unlike Make, '$' has special meaning only when it is followed by '('.
# No need to escape '$' itself.
$(warning,$)
$(warning,$$)
$ := 1
$(warning,$($))
# You need a trick to escape '$' followed by '('
# The following should print "$(X)". It should not be expanded further.
dollar := $
$(warning,$(dollar)(X))
# You need a trick to treat unbalanced parentheses.
# The following should print "(".
left_paren := (
$(warning,$(left_paren))
# A simple expanded should not be expanded multiple times.
# The following should print "$(X)". It should not be expanded further.
Y := $(dollar)(X)
$(warning,$(Y))
# The following should print "$(X)" as well.
Y = $(dollar)(X)
$(warning,$(Y))
# The following should print "$(".
# It should not be emit "unterminated reference" error.
unterminated := $(dollar)(
$(warning,$(unterminated))
# SPDX-License-Identifier: GPL-2.0
"""
Escape sequence tests.
"""
def test(conf):
assert conf.oldaskconfig() == 0
assert conf.stderr_matches('expected_stderr')
Kconfig:9: hello, world
Kconfig:13: ' " '" ' ''' "'"
Kconfig:17: $
Kconfig:18: $$
Kconfig:20: 1
Kconfig:25: $(X)
Kconfig:30: (
Kconfig:35: $(X)
Kconfig:39: $(X)
Kconfig:44: $(
# SPDX-License-Identifier: GPL-2.0
# Shorthand
warning = $(warning-if,y,$(1))
# Simply expanded variable.
X := 1
SIMPLE := $(X)
X := 2
$(warning,SIMPLE = $(SIMPLE))
# Recursively expanded variable.
X := 1
RECURSIVE = $(X)
X := 2
$(warning,RECURSIVE = $(RECURSIVE))
# Append something to a simply expanded variable.
Y := 3
SIMPLE += $(Y)
Y := 4
$(warning,SIMPLE = $(SIMPLE))
# Append something to a recursively expanded variable.
Y := 3
RECURSIVE += $(Y)
Y := 4
$(warning,RECURSIVE = $(RECURSIVE))
# Use += operator to an undefined variable.
# This works as a recursively expanded variable.
Y := 3
UNDEFINED_VARIABLE += $(Y)
Y := 4
$(warning,UNDEFINED_VARIABLE = $(UNDEFINED_VARIABLE))
# You can use variable references for the lefthand side of assignment statement.
X := A
Y := B
$(X)$(Y) := 5
$(warning,AB = $(AB))
# User-defined function.
greeting = $(1), my name is $(2).
$(warning,$(greeting,Hello,John))
# The number of arguments is not checked for user-defined functions.
# If some arguments are optional, it is useful to pass fewer parameters.
# $(2) will be blank in this case.
$(warning,$(greeting,Hello))
# Unreferenced parameters are just ignored.
$(warning,$(greeting,Hello,John,ignored,ignored))
# SPDX-License-Identifier: GPL-2.0
"""
Variable and user-defined function tests.
"""
def test(conf):
assert conf.oldaskconfig() == 0
assert conf.stderr_matches('expected_stderr')
Kconfig:10: SIMPLE = 1
Kconfig:16: RECURSIVE = 2
Kconfig:22: SIMPLE = 1 3
Kconfig:28: RECURSIVE = 2 4
Kconfig:35: UNDEFINED_VARIABLE = 4
Kconfig:41: AB = 5
Kconfig:45: Hello, my name is John.
Kconfig:50: Hello, my name is .
Kconfig:53: Hello, my name is John.
......@@ -14,18 +14,16 @@
struct file *file_lookup(const char *name)
{
struct file *file;
char *file_name = sym_expand_string_value(name);
for (file = file_list; file; file = file->next) {
if (!strcmp(name, file->name)) {
free(file_name);
return file;
}
}
file = xmalloc(sizeof(*file));
memset(file, 0, sizeof(*file));
file->name = file_name;
file->name = xstrdup(name);
file->next = file_list;
file_list = file;
return file;
......@@ -34,8 +32,6 @@ struct file *file_lookup(const char *name)
/* write a dependency file as used by kbuild to track dependencies */
int file_write_dep(const char *name)
{
struct symbol *sym, *env_sym;
struct expr *e;
struct file *file;
FILE *out;
......@@ -54,21 +50,7 @@ int file_write_dep(const char *name)
fprintf(out, "\n%s: \\\n"
"\t$(deps_config)\n\n", conf_get_autoconfig_name());
expr_list_for_each_sym(sym_env_list, e, sym) {
struct property *prop;
const char *value;
prop = sym_get_env_prop(sym);
env_sym = prop_get_symbol(prop);
if (!env_sym)
continue;
value = getenv(env_sym->name);
if (!value)
value = "";
fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value);
fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name());
fprintf(out, "endif\n");
}
env_write_dep(out, conf_get_autoconfig_name());
fprintf(out, "\n$(deps_config): ;\n");
fclose(out);
......@@ -165,3 +147,14 @@ char *xstrdup(const char *s)
fprintf(stderr, "Out of memory.\n");
exit(1);
}
char *xstrndup(const char *s, size_t n)
{
char *p;
p = strndup(s, n);
if (p)
return p;
fprintf(stderr, "Out of memory.\n");
exit(1);
}
%option nostdinit noyywrap never-interactive full ecs
%option 8bit nodefault yylineno
%option noinput
%x COMMAND HELP STRING PARAM
%x COMMAND HELP STRING PARAM ASSIGN_VAL
%{
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0.
*/
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -35,6 +35,8 @@ struct buffer *current_buf;
static int last_ts, first_ts;
static char *expand_token(const char *in, size_t n);
static void append_expanded_string(const char *in);
static void zconf_endhelp(void);
static void zconf_endfile(void);
......@@ -101,17 +103,28 @@ n [A-Za-z0-9_-]
<COMMAND>{
{n}+ {
const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
BEGIN(PARAM);
current_pos.file = current_file;
current_pos.lineno = yylineno;
if (id && id->flags & TF_COMMAND) {
BEGIN(PARAM);
yylval.id = id;
return id->token;
}
alloc_string(yytext, yyleng);
yylval.string = text;
return T_WORD;
return T_VARIABLE;
}
({n}|$)+ {
/* this token includes at least one '$' */
yylval.string = expand_token(yytext, yyleng);
if (strlen(yylval.string))
return T_VARIABLE;
free(yylval.string);
}
"=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_RECURSIVE; return T_ASSIGN; }
":=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_SIMPLE; return T_ASSIGN; }
"+=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_APPEND; return T_ASSIGN; }
[[:blank:]]+
. warn_ignored_character(*yytext);
\n {
BEGIN(INITIAL);
......@@ -119,6 +132,16 @@ n [A-Za-z0-9_-]
}
}
<ASSIGN_VAL>{
[^[:blank:]\n]+.* {
alloc_string(yytext, yyleng);
yylval.string = text;
return T_ASSIGN_VAL;
}
\n { BEGIN(INITIAL); return T_EOL; }
.
}
<PARAM>{
"&&" return T_AND;
"||" return T_OR;
......@@ -147,6 +170,13 @@ n [A-Za-z0-9_-]
yylval.string = text;
return T_WORD;
}
({n}|[/.$])+ {
/* this token includes at least one '$' */
yylval.string = expand_token(yytext, yyleng);
if (strlen(yylval.string))
return T_WORD;
free(yylval.string);
}
#.* /* comment */
\\\n ;
[[:blank:]]+
......@@ -157,12 +187,13 @@ n [A-Za-z0-9_-]
}
<STRING>{
[^'"\\\n]+/\n {
"$".* append_expanded_string(yytext);
[^$'"\\\n]+/\n {
append_string(yytext, yyleng);
yylval.string = text;
return T_WORD_QUOTE;
}
[^'"\\\n]+ {
[^$'"\\\n]+ {
append_string(yytext, yyleng);
}
\\.?/\n {
......@@ -249,6 +280,58 @@ n [A-Za-z0-9_-]
}
%%
static char *expand_token(const char *in, size_t n)
{
char *out;
int c;
char c2;
const char *rest, *end;
new_string();
append_string(in, n);
/* get the whole line because we do not know the end of token. */
while ((c = input()) != EOF) {
if (c == '\n') {
unput(c);
break;
}
c2 = c;
append_string(&c2, 1);
}
rest = text;
out = expand_one_token(&rest);
/* push back unused characters to the input stream */
end = rest + strlen(rest);
while (end > rest)
unput(*--end);
free(text);
return out;
}
static void append_expanded_string(const char *str)
{
const char *end;
char *res;
str++;
res = expand_dollar(&str);
/* push back unused characters to the input stream */
end = str + strlen(str);
while (end > str)
unput(*--end);
append_string(res, strlen(res));
free(res);
}
void zconf_starthelp(void)
{
new_string();
......
......@@ -41,6 +41,7 @@ static struct menu *current_menu, *current_entry;
struct expr *expr;
struct menu *menu;
const struct kconf_id *id;
enum variable_flavor flavor;
}
%token <id>T_MAINMENU
......@@ -77,6 +78,9 @@ static struct menu *current_menu, *current_entry;
%token T_CLOSE_PAREN
%token T_OPEN_PAREN
%token T_EOL
%token <string> T_VARIABLE
%token <flavor> T_ASSIGN
%token <string> T_ASSIGN_VAL
%left T_OR
%left T_AND
......@@ -92,7 +96,7 @@ static struct menu *current_menu, *current_entry;
%type <id> end
%type <id> option_name
%type <menu> if_entry menu_entry choice_entry
%type <string> symbol_option_arg word_opt
%type <string> symbol_option_arg word_opt assign_val
%destructor {
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
......@@ -109,7 +113,7 @@ static struct menu *current_menu, *current_entry;
%%
input: nl start | start;
start: mainmenu_stmt stmt_list | no_mainmenu_stmt stmt_list;
start: mainmenu_stmt stmt_list | stmt_list;
/* mainmenu entry */
......@@ -118,19 +122,6 @@ mainmenu_stmt: T_MAINMENU prompt nl
menu_add_prompt(P_MENU, $2, NULL);
};
/* Default main menu, if there's no mainmenu entry */
no_mainmenu_stmt: /* empty */
{
/*
* Hack: Keep the main menu title on the heap so we can safely free it
* later regardless of whether it comes from the 'prompt' in
* mainmenu_stmt or here
*/
menu_add_prompt(P_MENU, xstrdup("Linux Kernel Configuration"), NULL);
};
stmt_list:
/* empty */
| stmt_list common_stmt
......@@ -156,6 +147,7 @@ common_stmt:
| config_stmt
| menuconfig_stmt
| source_stmt
| assignment_stmt
;
option_error:
......@@ -524,31 +516,42 @@ symbol: nonconst_symbol
word_opt: /* empty */ { $$ = NULL; }
| T_WORD
/* assignment statement */
assignment_stmt: T_VARIABLE T_ASSIGN assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); }
assign_val:
/* empty */ { $$ = xstrdup(""); };
| T_ASSIGN_VAL
;
%%
void conf_parse(const char *name)
{
const char *tmp;
struct symbol *sym;
int i;
zconf_initscan(name);
sym_init();
_menu_init();
if (getenv("ZCONF_DEBUG"))
yydebug = 1;
yyparse();
/* Variables are expanded in the parse phase. We can free them here. */
variable_all_del();
if (yynerrs)
exit(1);
if (!modules_sym)
modules_sym = sym_find( "n" );
tmp = rootmenu.prompt->text;
rootmenu.prompt->text = _(rootmenu.prompt->text);
rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
free((char*)tmp);
if (!menu_has_prompt(&rootmenu)) {
current_entry = &rootmenu;
menu_add_prompt(P_MENU, "Main menu", NULL);
}
menu_finalize(&rootmenu);
for_all_symbols(i, sym) {
......@@ -780,3 +783,4 @@ void zconfdump(FILE *out)
#include "expr.c"
#include "symbol.c"
#include "menu.c"
#include "preprocess.c"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment