Re: [PATCH v2 04/21] kconfig: reference environments directly and remove 'option env=' syntax

From: Ulf Magnusson
Date: Wed Mar 28 2018 - 22:57:08 EST


On Thu, Mar 29, 2018 at 4:19 AM, Ulf Magnusson <ulfalizer@xxxxxxxxx> wrote:
> I've been kinda busy lately, so that's why I disappeared.
>
> I'll try to go over this patchset in more detail over the weekend.
>
> On Tue, Mar 27, 2018 at 7:29 AM, Masahiro Yamada
> <yamada.masahiro@xxxxxxxxxxxxx> wrote:
>> To get an environment value, Kconfig needs to define a symbol using
>> "option env=" syntax. It is tedious to add a config entry for each
>> environment given that we need more environments such as 'CC', 'AS',
>> 'srctree' etc. to evaluate the compiler capability in Kconfig.
>>
>> Adding '$' to symbols is weird. Kconfig can reference symbols directly
>> like this:
>>
>> config FOO
>> string
>> default BAR
>>
>> So, I want to use the following syntax to get environment 'BAR' from
>> the system:
>>
>> config FOO
>> string
>> default $BAR
>>
>> Looking at the code, the symbols prefixed with 'S' are expanded by:
>> - conf_expand_value()
>> This is used to expand 'arch/$ARCH/defconfig' and 'defconfig_list'
>> - expand_string_value()
>> This is used to expand strings in 'source' and 'mainmenu'
>>
>> All of them are fixed values independent of user configuration. So,
>> this kind of syntax should be moved to simply take the environment.
>>
>> This change makes the code much cleaner. The bounce symbols 'SRCARCH',
>> 'ARCH', 'SUBARCH', 'KERNELVERSION' are gone.
>>
>> sym_init() hard-coding 'UNAME_RELEASE' is also gone. 'UNAME_RELEASE'
>> should be be given from the environment.
>>
>> ARCH_DEFCONFIG is a normal symbol, so it should be simply referenced
>> by 'default ARCH_DEFCONFIG'.
>>
>> The environments are expanding in the lexer; when '$' is encountered,
>> it is expanded, and resulted strings are pushed back to the input
>> stream. This makes the implementation simpler.
>>
>> For example, the following code works.
>>
>> [Example code]
>>
>> config TOOLCHAIN_LIST
>> string
>> default "My tools: CC=$CC, AS=$AS, CPP=$CPP"
>>
>> [Result]
>>
>> $ make -s alldefconfig && tail -n 1 .config
>> CONFIG_TOOLCHAIN_LIST="My tools: CC=gcc, AS=as, CPP=gcc -E"
>>
>> Signed-off-by: Masahiro Yamada <yamada.masahiro@xxxxxxxxxxxxx>
>> ---
>>
>> I tested all 'make *config' for arch architectures.
>> I confirmed this commit still produced the same result
>> (by my kconfig test tool).
>>
>>
>> Changes in v2:
>> - Move the string expansion to the lexer phase.
>> - Split environment helpers to env.c
>>
>> Documentation/kbuild/kconfig-language.txt | 8 ---
>> Kconfig | 4 --
>> Makefile | 3 +-
>> arch/sh/Kconfig | 4 +-
>> arch/sparc/Kconfig | 4 +-
>> arch/tile/Kconfig | 2 +-
>> arch/um/Kconfig.common | 4 --
>> arch/x86/Kconfig | 4 +-
>> arch/x86/um/Kconfig | 4 +-
>> init/Kconfig | 10 +---
>> scripts/kconfig/confdata.c | 31 +---------
>> scripts/kconfig/env.c | 95 +++++++++++++++++++++++++++++++
>> scripts/kconfig/kconf_id.c | 1 -
>> scripts/kconfig/lkc.h | 8 +--
>> scripts/kconfig/menu.c | 3 -
>> scripts/kconfig/symbol.c | 56 ------------------
>> scripts/kconfig/util.c | 75 ++++++++----------------
>> scripts/kconfig/zconf.l | 20 ++++++-
>> scripts/kconfig/zconf.y | 2 +-
>> 19 files changed, 158 insertions(+), 180 deletions(-)
>> create mode 100644 scripts/kconfig/env.c
>>
>> diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt
>> index f5b9493..0e966e8 100644
>> --- a/Documentation/kbuild/kconfig-language.txt
>> +++ b/Documentation/kbuild/kconfig-language.txt
>> @@ -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.
>> diff --git a/Kconfig b/Kconfig
>> index 8c4c1cb..e6ece5b 100644
>> --- a/Kconfig
>> +++ b/Kconfig
>> @@ -5,8 +5,4 @@
>> #
>> mainmenu "Linux/$ARCH $KERNELVERSION Kernel Configuration"
>>
>> -config SRCARCH
>> - string
>> - option env="SRCARCH"
>> -
>> source "arch/$SRCARCH/Kconfig"
>> diff --git a/Makefile b/Makefile
>> index 5c395ed..4ae1486 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -284,7 +284,8 @@ include scripts/Kbuild.include
>> # Read KERNELRELEASE from include/config/kernel.release (if it exists)
>> KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
>> KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
>> -export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
>> +UNAME_RELEASE := $(shell uname --release)
>> +export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION UNAME_RELEASE
>>
>> # SUBARCH tells the usermode build what the underlying arch is. That is set
>> # first, and if a usermode build is happening, the "ARCH=um" on the command
>> diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
>> index 97fe293..14f3ef1 100644
>> --- a/arch/sh/Kconfig
>> +++ b/arch/sh/Kconfig
>> @@ -57,7 +57,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
>> @@ -76,7 +76,7 @@ config SUPERH32
>> select HAVE_CC_STACKPROTECTOR
>>
>> config SUPERH64
>> - def_bool ARCH = "sh64"
>> + def_bool "$ARCH" = "sh64"
>> select HAVE_EXIT_THREAD
>> select KALLSYMS
>>
>> diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
>> index 8767e45..86b852e 100644
>> --- a/arch/sparc/Kconfig
>> +++ b/arch/sparc/Kconfig
>> @@ -1,6 +1,6 @@
>> 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
>> diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
>> index ef9d403..acc2182 100644
>> --- a/arch/tile/Kconfig
>> +++ b/arch/tile/Kconfig
>> @@ -119,7 +119,7 @@ config HVC_TILE
>> # Building with ARCH=tilegx (or ARCH=tile) implies using the
>> # 64-bit TILE-Gx toolchain, so force CONFIG_TILEGX on.
>> config TILEGX
>> - def_bool ARCH != "tilepro"
>> + def_bool "$ARCH" != "tilepro"
>> select ARCH_SUPPORTS_ATOMIC_RMW
>> select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
>> select HAVE_ARCH_JUMP_LABEL
>> diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common
>> index c68add8..07f84c8 100644
>> --- a/arch/um/Kconfig.common
>> +++ b/arch/um/Kconfig.common
>> @@ -54,10 +54,6 @@ config HZ
>> int
>> default 100
>>
>> -config SUBARCH
>> - string
>> - option env="SUBARCH"
>> -
>> config NR_CPUS
>> int
>> range 1 1
>> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
>> index 0fa71a7..986fb0a 100644
>> --- a/arch/x86/Kconfig
>> +++ b/arch/x86/Kconfig
>> @@ -1,8 +1,8 @@
>> # 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
>> diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
>> index 13ed827..d355413 100644
>> --- a/arch/x86/um/Kconfig
>> +++ b/arch/x86/um/Kconfig
>> @@ -16,8 +16,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
>> diff --git a/init/Kconfig b/init/Kconfig
>> index df18492..b4814e6 100644
>> --- a/init/Kconfig
>> +++ b/init/Kconfig
>> @@ -1,11 +1,3 @@
>> -config ARCH
>> - string
>> - option env="ARCH"
>> -
>> -config KERNELVERSION
>> - string
>> - option env="KERNELVERSION"
>> -
>> config DEFCONFIG_LIST
>> string
>> depends on !UML
>> @@ -13,7 +5,7 @@ config DEFCONFIG_LIST
>> default "/lib/modules/$UNAME_RELEASE/.config"
>> default "/etc/kernel-config"
>> default "/boot/config-$UNAME_RELEASE"
>> - default "$ARCH_DEFCONFIG"
>> + default ARCH_DEFCONFIG
>> default "arch/$ARCH/defconfig"
>>
>> config CONSTRUCTORS
>> diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
>> index df26c7b..98c2014 100644
>> --- a/scripts/kconfig/confdata.c
>> +++ b/scripts/kconfig/confdata.c
>> @@ -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_value(conf_defname);
>> env = getenv(SRCTREE);
>> if (env) {
>> sprintf(fullname, "%s/%s", env, name);
>> @@ -274,7 +248,8 @@ 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"),
>> diff --git a/scripts/kconfig/env.c b/scripts/kconfig/env.c
>> new file mode 100644
>> index 0000000..9702f5c
>> --- /dev/null
>> +++ b/scripts/kconfig/env.c
>> @@ -0,0 +1,95 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +//
>> +// Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@xxxxxxxxxxxxx>
>> +
>> +static LIST_HEAD(env_list);
>> +
>> +struct env {
>> + char *name;
>> + char *value;
>> + struct list_head node;
>> +};
>> +
>> +static struct env *env_list_lookup(const char *name)
>> +{
>> + struct env *e;
>> +
>> + list_for_each_entry(e, &env_list, node) {
>> + if (!strcmp(name, e->name))
>> + return e;
>> + }
>> +
>> + return NULL;
>> +}
>> +
>> +static void env_list_add(const char *name, const char *value)
>> +{
>> + struct env *e;
>> +
>> + e = xmalloc(sizeof(*e));
>> + e->name = xstrdup(name);
>> + e->value = xstrdup(value);
>> +
>> + list_add_tail(&e->node, &env_list);
>> +}
>> +
>> +static void env_list_del(struct env *e)
>> +{
>> + list_del(&e->node);
>> + free(e->name);
>> + free(e->value);
>> + free(e);
>> +}
>> +
>> +/* the returned pointer must be freed when done */
>> +static char *env_expand(const char *name)
>> +{
>> + struct env *e;
>> + const char *value;
>> +
>> + e = env_list_lookup(name);
>> + if (e)
>> + return xstrdup(e->value);
>> +
>> + value = getenv(name);
>> + if (!value) {
>> + fprintf(stderr, "environment variable \"%s\" undefined\n", name);
>> + value = "";
>> + }
>> +
>> + /*
>> + * we need to remember all referenced environments.
>> + * They will be written out to include/config/auto.conf.cmd
>> + */
>> + env_list_add(name, value);
>> +
>> + return xstrdup(value);
>> +}
>> +
>> +/* works like env_expand, but 'name' does not need to be null-terminated */
>> +char *env_expand_n(const char *name, size_t n)
>> +{
>> + char *tmp, *res;
>> +
>> + tmp = xmalloc(n + 1);
>> + memcpy(tmp, name, n);
>> + *(tmp + n) = '\0';
>> +
>> + res = env_expand(tmp);
>> +
>> + free(tmp);
>> +
>> + return res;
>> +}
>> +
>> +void env_write_dep(FILE *f, const char *autoconfig_name)
>> +{
>> + struct env *env, *tmp;
>> +
>> + list_for_each_entry_safe(env, tmp, &env_list, node) {
>> + fprintf(f, "ifneq \"$(%s)\" \"%s\"\n", env->name, env->value);
>> + fprintf(f, "%s: FORCE\n", autoconfig_name);
>> + fprintf(f, "endif\n");
>> + env_list_del(env);
>> + }
>> +}
>> diff --git a/scripts/kconfig/kconf_id.c b/scripts/kconfig/kconf_id.c
>> index 3ea9c5f..b3e0ea0 100644
>> --- a/scripts/kconfig/kconf_id.c
>> +++ b/scripts/kconfig/kconf_id.c
>> @@ -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 },
>> };
>>
>> diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
>> index c8d9e55..03d007f 100644
>> --- a/scripts/kconfig/lkc.h
>> +++ b/scripts/kconfig/lkc.h
>> @@ -58,7 +58,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 {
>> @@ -95,6 +94,10 @@ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
>> fprintf(stderr, "Error in writing or end of file.\n");
>> }
>>
>> +/* env.c */
>> +char *env_expand_n(const char *name, size_t n);
>> +void env_write_dep(FILE *f, const char *auto_conf_name);
>> +
>> /* menu.c */
>> void _menu_init(void);
>> void menu_warn(struct menu *menu, const char *fmt, ...);
>> @@ -135,9 +138,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);
>> diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
>> index 5c5c137..8148305 100644
>> --- a/scripts/kconfig/menu.c
>> +++ b/scripts/kconfig/menu.c
>> @@ -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;
>> diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
>> index 03143b2..7c9a88e 100644
>> --- a/scripts/kconfig/symbol.c
>> +++ b/scripts/kconfig/symbol.c
>> @@ -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;
>> @@ -1348,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);
>> -}
>> diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
>> index 22201a4..136e497 100644
>> --- a/scripts/kconfig/util.c
>> +++ b/scripts/kconfig/util.c
>> @@ -8,16 +8,18 @@
>> #include <stdarg.h>
>> #include <stdlib.h>
>> #include <string.h>
>> +
>> +#include "list.h"
>> #include "lkc.h"
>>
>> /*
>> - * 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
>> + * Expand environments embedded in the string given in argument. Environments
>> + * to be expanded shall be prefixed by a '$'. Unknown environment expands to
>> * the empty string.
>> */
>> char *expand_string_value(const char *in)
>> {
>> - const char *src;
>> + const char *p, *q;
>> char *res;
>> size_t reslen;
>>
>> @@ -25,39 +27,28 @@ char *expand_string_value(const char *in)
>> * 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);
>> - }
>> + res = xmalloc(1);
>> + *res = '\0';
>>
>> - newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
>> - if (newlen > reslen) {
>> - reslen = newlen;
>> - res = xrealloc(res, reslen);
>> - }
>> + while ((p = strchr(in, '$'))) {
>> + char *new;
>> +
>> + q = p + 1;
>> + while (isalnum(*q) || *q == '_')
>> + q++;
>>
>> - strcat(res, symval);
>> - in = src;
>> + new = env_expand_n(p + 1, q - p - 1);
>> +
>> + reslen = strlen(res) + (p - in) + strlen(new) + 1;
>> + res = xrealloc(res, reslen);
>> + strncat(res, in, p - in);
>> + strcat(res, new);
>> + free(new);
>> + in = q;
>> }
>> +
>> + reslen = strlen(res) + strlen(in) + 1;
>> + res = xrealloc(res, reslen);
>> strcat(res, in);
>>
>> return res;
>> @@ -87,8 +78,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;
>>
>> @@ -107,21 +96,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);
>> diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
>> index 045093d..551ca47 100644
>> --- a/scripts/kconfig/zconf.l
>> +++ b/scripts/kconfig/zconf.l
>> @@ -35,6 +35,7 @@ struct buffer *current_buf;
>>
>> static int last_ts, first_ts;
>>
>> +static void expand_string(const char *in);
>> static void zconf_endhelp(void);
>> static void zconf_endfile(void);
>>
>> @@ -120,6 +121,7 @@ n [A-Za-z0-9_-]
>> }
>>
>> <PARAM>{
>> + "$".* expand_string(yytext);
>> "&&" return T_AND;
>> "||" return T_OR;
>> "(" return T_OPEN_PAREN;
>> @@ -157,12 +159,13 @@ n [A-Za-z0-9_-]
>> }
>>
>> <STRING>{
>> - [^'"\\\n]+/\n {
>> + "$".* expand_string(yytext);
>> + [^$'"\\\n]+/\n {
>> append_string(yytext, yyleng);
>> yylval.string = text;
>> return T_WORD_QUOTE;
>> }
>> - [^'"\\\n]+ {
>> + [^$'"\\\n]+ {
>> append_string(yytext, yyleng);
>> }
>> \\.?/\n {
>> @@ -249,6 +252,19 @@ n [A-Za-z0-9_-]
>> }
>>
>> %%
>> +static void expand_string(const char *in)
>> +{
>> + char *p, *q;
>> +
>> + p = expand_string_value(in);
>> +
>> + q = p + strlen(p);
>> + while (q > p)
>> + unput(*--q);
>> +
>> + free(p);
>> +}
>> +
>
> I like the simplicity of this approach, but I suspect it might be too simple.
>
> For example, the following breaks with a syntax error if $ENV has any
> double quotes in its value:
>
> config FOO
> string "foo"
> default "$ENV"
>
> The following will only work as expected if $ENV expands to a valid
> Kconfig symbol name. If it doesn't, random stuff will happen (most
> likely a syntax error).
>
> config FOO
> string "foo"
> default $ENV
>
> The reason it works if $ENV expands to a valid symbol name is that
> undefined symbols get their name as their (string) value. If the
> symbol happens to be defined, it will be referenced, which seems
> confusing too.
>
> In general, that reinterpretation of expanded values feels a bit icky
> to me, and as something that might add complexity to Kconfig for
> little value. If $ENV outside of quotes absolutely must be supported,
> I think it should be a shorthand for "$ENV" (which means "constant
> value" in Kconfig speak).

If you want something as general as the C preprocessor (which I think
would be overkill and complexity land), then it seems kinda weird to
limit it to certain Kconfig contexts as well: Right now you'd be able
to output arbitrary tokens inside an expression, but you couldn't do
something like generate a 'default X if Y'.

Cheers,
Ulf