Received: by 10.213.65.68 with SMTP id h4csp1102561imn; Sat, 31 Mar 2018 19:31:14 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+hsrgMSm61JdtT0vdx7lJASLptKkCBTNr8wyQbDHDmo9UXft9cL8ROOrn7qm+n56b+3XqY X-Received: by 2002:a17:902:7084:: with SMTP id z4-v6mr5013859plk.395.1522549873992; Sat, 31 Mar 2018 19:31:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1522549873; cv=none; d=google.com; s=arc-20160816; b=PMPy6giNgW/m/8jBtyRdzhgQlzI0pvtUHbymYgGKrxxvxVwjcvMfvE9qxpE/05za77 U+XU4f5CnI1LD1h6E978HoYD27atjgqbnIa/fTwjrGLnFr+HcSv5sO10J4Pw1+9GdZmG HPKtf2dk5z5FQwsTSkJFbf0zOytcdmhtUNb6bp/9qQqn7ngT2JZ3XytcJAMHN/Q+77ZG kvTmiKtZtnCeQCuvxfgmECEVfhBsG7LwBZaltmLeblHpcWc1xZBalTqAIA6kY6fFaHxW 33wfcjJy0vgdIKv3CT5NjkMnfYGOJmuYv9xvk5eYxGzB6aKjZDGts63EH3fQ0b8iuwcX B9hA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :references:in-reply-to:mime-version:dkim-signature :arc-authentication-results; bh=sHQ4zePPjAtnlwYNQR3TJkKf2DBCTD1Uo6wYGDboTE4=; b=Si4C92HiOlLStgvxbVTP6OnV7abkjSKbTgxPy1dy+ErNAAH2g2d0qiIsF0MmKHXDc4 DrYt6aCvN+CSJhwE5TsziaknGcBbSu3NkXuv7pVxYetPxxlRMV4nvvNVSgJLb8xtZxvI vbovW754+XDEg+Xx1KqhDSuYrOt8WxhYKHkvuycCYL0Q49kIkKbY2vePZ/ip6iX2GKK/ X2XmsUjeRIX5qqy2SFr4TGfGCvaCUYydPxWET8QhJ70AbWTmWPaLeQUnJMm/l+i7C+pE GS0sGSo24Z9Abd9ivCbWpNYhxZXxb94B78bj94CKyLYCH/tPCodSwwkh8xVl52tCwp7L uRvQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=UnHwjLXt; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l14si2190472pgc.117.2018.03.31.19.30.29; Sat, 31 Mar 2018 19:31:13 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=UnHwjLXt; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753045AbeDAC1b (ORCPT + 99 others); Sat, 31 Mar 2018 22:27:31 -0400 Received: from mail-vk0-f66.google.com ([209.85.213.66]:34286 "EHLO mail-vk0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752919AbeDAC13 (ORCPT ); Sat, 31 Mar 2018 22:27:29 -0400 Received: by mail-vk0-f66.google.com with SMTP id z190so6772297vkg.1; Sat, 31 Mar 2018 19:27:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=sHQ4zePPjAtnlwYNQR3TJkKf2DBCTD1Uo6wYGDboTE4=; b=UnHwjLXtpBNN+vMz6Ck4+VUaM4Fd05exV/aX8ctg5WAUCqZfFtkwKLyFgYIwwcGR+j F8PDm1v0njiVvCM+JihGg3N0yQqWo/woMHxp8f/wQCXE9fkU7u9y9rTHARcue8iLCLuk zqn7K7MmGE+l8LY+uVJjrJSb/E+hotSIO0+wfxlFnOMZjetXjoQeTcCcUH/m96eaMmvb CUrU9DEP5kjngVY55OlXvwdpGSzjN/XoMhBJRlgVgA8Opy/61i2rhl0nnM+hlQDUeE/p eSEVYDDtP5HJhNWnOzTJ/on2ELsvEbl+uLjNpiEsf+hm+cKIjWhVooBmAywSw5Zg3nS6 amCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=sHQ4zePPjAtnlwYNQR3TJkKf2DBCTD1Uo6wYGDboTE4=; b=ZnAcc9mxKETB2Rj/qxTNPwrc1Eb3CqSOfFv+zJ7FTCyFmfiNz8DfftDkGDmPf4GXiR iv9M9PP47iuzCzOo/WvQPw+TwftFYkgu/bbyzN23z9B7il6aLzr+ik072ilKL3y0ZBn4 KrUKiAyGMLF3OC6XzxR85zaNbvadx82FWaTW74FqvS/pyIMcZFdEFqNe3WfTB2y33sDh v3nRTd94l/P4BKA7SeR3m6YwATvJAS8L7kGk+WnxddmwhZoN0TQh86aQCnuylNxHQZZI c9K7E45GNPjFoVY/51htaFTZ01ieW3QGVocedUvXxmRnWuVqQ8KA4umwmnI7IY/U3ile YZqA== X-Gm-Message-State: ALQs6tBQDbXKj0ChxZ837GocTxZRf2nFKg0EQvtLfHu8CMAc8rxhh7Ne GSSCZ1fpli7RDoz/Pq7mKfBzigxKw/XEt4RevpM= X-Received: by 10.31.75.132 with SMTP id y126mr2490613vka.154.1522549647696; Sat, 31 Mar 2018 19:27:27 -0700 (PDT) MIME-Version: 1.0 Received: by 10.103.206.5 with HTTP; Sat, 31 Mar 2018 19:27:27 -0700 (PDT) In-Reply-To: <1522128575-5326-5-git-send-email-yamada.masahiro@socionext.com> References: <1522128575-5326-1-git-send-email-yamada.masahiro@socionext.com> <1522128575-5326-5-git-send-email-yamada.masahiro@socionext.com> From: Ulf Magnusson Date: Sun, 1 Apr 2018 04:27:27 +0200 Message-ID: Subject: Re: [PATCH v2 04/21] kconfig: reference environments directly and remove 'option env=' syntax To: Masahiro Yamada Cc: Linux Kbuild mailing list , Sam Ravnborg , Linus Torvalds , Arnd Bergmann , Kees Cook , Thomas Gleixner , Greg Kroah-Hartman , Randy Dunlap , "Luis R . Rodriguez" , Nicolas Pitre , Linux Kernel Mailing List , Ingo Molnar Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Here's a more in-depth review: On Tue, Mar 27, 2018 at 7:29 AM, Masahiro Yamada 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', "Environment variables" would be clearer. I've never seen them called "environments". > '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, s/environments/environment variables/ > 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 > --- > > 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"= > - 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). > - The new behavior needs to be documented later as well (but iirc you already mentioned that somewhere else). > - "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 > . > > 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 > + > +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; > +} This function might be unnecessary -- see below. > + > +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) This function is basically just getenv() with some dependency housekeeping added. A name like env_get() or env_lookup() would be clearer I think. > +{ > + struct env *e; > + const char *value; > + > + e = env_list_lookup(name); > + if (e) > + return xstrdup(e->value); Not sure this bit is needed. It is always safe to get the value from getenv(). See below. > + > + value = getenv(name); > + if (!value) { > + fprintf(stderr, "environment variable \"%s\" undefined\n", name); > + value = ""; > + } > + > + /* > + * we need to remember all referenced environments. s/environments/environment variables/ > + * They will be written out to include/config/auto.conf.cmd > + */ > + env_list_add(name, value); AFAICS, we only need the following functionality: 1. Record referenced environment variables along with their value 2. Go through all the recorded environment variables and write dependency information For (1), I think it would be better to simply have env_list_add() (or some other suitable name) add the variable to the list if it isn't already there (like a kind of set). It is always safe to get the value of the environment variable from getenv(), and that seems less confusing. > + > + return xstrdup(value); The returned string is never modified, and the result from getenv() never gets stale, so I think the strdup() is unnecessary. The function could return a const char * to avoid accidental modification. > +} > + > +/* works like env_expand, but 'name' does not need to be null-terminated */ > +char *env_expand_n(const char *name, size_t n) Could be renamed to something like env_get_n(), and could return a const char * if the above modification is made. > +{ > + 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 Renumber to 3? Looks like a bitmask to me otherwise. > > 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 > #include > #include > + > +#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 s/environments/environment variables/ > + * 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); 'value' might be a clearer name than 'new'. > + > + reslen = strlen(res) + (p - in) + strlen(new) + 1; > + res = xrealloc(res, reslen); > + strncat(res, in, p - in); > + strcat(res, new); > + free(new); Not needed it env_expand_n() (env_get_n()) is modified to return the value from getenv() directly. 'new' is never modified either. > + 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_-] > } > > { > + "$".* expand_string(yytext); > "&&" return T_AND; > "||" return T_OR; > "(" return T_OPEN_PAREN; > @@ -157,12 +159,13 @@ n [A-Za-z0-9_-] > } > > { > - [^'"\\\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); > +} (In case any other reviewers jump in -- see earlier messages in this thread for some gotchas related to this.) > + > void zconf_starthelp(void) > { > new_string(); > diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y > index 262c464..4ff4ac9 100644 > --- a/scripts/kconfig/zconf.y > +++ b/scripts/kconfig/zconf.y > @@ -534,7 +534,6 @@ void conf_parse(const char *name) > > zconf_initscan(name); > > - sym_init(); > _menu_init(); > > if (getenv("ZCONF_DEBUG")) > @@ -775,6 +774,7 @@ void zconfdump(FILE *out) > } > > #include "zconf.lex.c" > +#include "env.c" > #include "util.c" > #include "confdata.c" > #include "expr.c" > -- > 2.7.4 > Cheers, Ulf