Received: by 2002:ac0:a594:0:0:0:0:0 with SMTP id m20-v6csp169810imm; Mon, 21 May 2018 04:13:16 -0700 (PDT) X-Google-Smtp-Source: AB8JxZrh4ivl63GOc6DUVMeLN4VEwRgmKM864sqvtsLSR6/cO5LW8E9IQJXxF7JNc5RIp3DYWhZy X-Received: by 2002:a17:902:b087:: with SMTP id p7-v6mr20036418plr.227.1526901196766; Mon, 21 May 2018 04:13:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1526901196; cv=none; d=google.com; s=arc-20160816; b=eFsiriO1Yz4MWNj6YhAvgPORWga73bXJ+OYaRJ653qkMUiUb6BkYFkQw17DVsP7qIi aoZ0dmmmBZZFubXzruAIv7ocdMr01JMCVIwSBJzS8MuWKbUL9/ywy9PSPNIyJqyKPT/t eXhSuFtSYceInlyGAfeQDiQx7i2b62pTyjiGI5nD+89leLr8bKO102Tyq0QsjmF/V9eA m+sGbDPJYVI0wU+KhJM4mWUXWcIkt7sBywW8rAn6oZN5t2k+/GfBgG79w9x9/EANLMCi zyjSqOsYEY13LiMzUBObXXBiyLRrBjMNidRA6FeYGoUMXAarCgBFSn9sEAm9vpievnjx vyKg== 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=WI390XVyQQYzSgG9cRuKgt/NCrxEWGf7Mi+j+HDH2dk=; b=0+PzRx3dCxOS8DXp4beIbSyoXw7Diaw+thoQ8xy0Rb5ICH11oxb3kIMCzIAVDv3BTL lNuGC6HvAKhi2WMEJS5XLlp10C3ZuBTkjqXyqA8ovUjUPdeVXRq+O52kmT8O9TKULFdh ZNYkYfAHB07u0d0174tiuikWuYXgCCaY0nMjlvk8Q4l2vnqaH4bXSLijBoKOcoaTbt81 Z5b3dbmFhx9LtwPB2kQs+DKw3BIz2sj8Q2bT9KmGUD1VBZcUS4a7dA/a7JWVpOh/lTIi 09U+GmF7DQmiLCPG/LFpWzaqn+UYoRJQRB2PH0mo69Bex61MlbQjhkDlO3Jm/mLKWwDE P9Gw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=vO8dByF7; 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 32-v6si10145401plg.586.2018.05.21.04.13.02; Mon, 21 May 2018 04:13:16 -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=vO8dByF7; 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 S1751905AbeEULLs (ORCPT + 99 others); Mon, 21 May 2018 07:11:48 -0400 Received: from mail-oi0-f68.google.com ([209.85.218.68]:45895 "EHLO mail-oi0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751173AbeEULLp (ORCPT ); Mon, 21 May 2018 07:11:45 -0400 Received: by mail-oi0-f68.google.com with SMTP id b130-v6so12624374oif.12; Mon, 21 May 2018 04:11:45 -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=WI390XVyQQYzSgG9cRuKgt/NCrxEWGf7Mi+j+HDH2dk=; b=vO8dByF7BwlyvGKgOOTPs1uy7yMGS9vKL1xCWJ6t75zdUKGfyyj8Jx28nGDyO6DfDQ CScX6AeXnfh+PNGfZjfNyGOUChkknFbYDAtzkJdmcDm+Kv2E4e1kMfS1Ho2CHanhqVUW +us6gURnPKcF5iddzWeJXW6Q6HVGx6M9m/c0z7nbUWcJ2ZuDOPZz9E26u8Pn3Vik4aoV 8NoW+F4kb7f3f5EdqBKQC9ePLkE3qJB49CuaZ+vT6z8ttMVPAyMOnGRurJKcgn2b44bC NFyAy1oiiyU2mwyq2n9NNRBBx42yD8N59oEqJikcyhj5FfFCJF5P7Pvh4H8j+B3gm4te VwsQ== 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=WI390XVyQQYzSgG9cRuKgt/NCrxEWGf7Mi+j+HDH2dk=; b=lvNSf8SkCH4jOZolmFD37LwTkqo4my72S3eIhMlp1bttTRMTPmlslqB699rqUN6PFJ 4wQz9ADpnI6xCSl2c2+UKZ2Y0QYpgTFmaPMxm4JuoiRUR0Pi6xoAqgmiFwmiap7B4Lar bnR2w/tRJ1J2Xs8euCGBrOdX4Y/4MrvGJ9IYuB5RsPnI5wKdafvaaGoT7IFcu2ZBWo6f UVfFgnAaZi9ALQXKjUWMOOZmJv9s2DqsrPxuY4E8D/5fKeKdl9sPaJywyrQyeItCRqli 9gzY6MSNuefqFDgfPI3XCsLECw3O2u3TIpR2UNfjF97GB4/BHv7vylGqBk8IZkJgtJ0l wRxg== X-Gm-Message-State: ALKqPwflSDOADj201urxwUmbCi/aogngtXJAGqHIMstSLJYj/IkdT5x+ eHH4t4oG6qyns4P1oHYJLAU74BiYCUZjmu07+y0= X-Received: by 2002:aca:6856:: with SMTP id d83-v6mr10995163oic.66.1526901104965; Mon, 21 May 2018 04:11:44 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:a9d:185:0:0:0:0:0 with HTTP; Mon, 21 May 2018 04:11:44 -0700 (PDT) In-Reply-To: References: <1526537830-22606-1-git-send-email-yamada.masahiro@socionext.com> <1526537830-22606-4-git-send-email-yamada.masahiro@socionext.com> From: Ulf Magnusson Date: Mon, 21 May 2018 13:11:44 +0200 Message-ID: Subject: Re: [PATCH v4 03/31] kconfig: reference environment variables directly and remove 'option env=' To: Masahiro Yamada Cc: Linux Kbuild mailing list , Linus Torvalds , Sam Ravnborg , "Luis R . Rodriguez" , Linux Kernel Mailing List , Nicholas Piggin , Kees Cook , Emese Revfy , X86 ML 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 On Mon, May 21, 2018 at 1:06 PM, Ulf Magnusson wrote: > On Mon, May 21, 2018 at 6:43 AM, Masahiro Yamada > wrote: >> Hi. >> >> >> >> 2018-05-21 0:46 GMT+09:00 Ulf Magnusson : >> >>> s/environments/environment variables/ >> >> Will fix. >> >> >>> >>>> + * They will be written out to include/config/auto.conf.cmd >>>> + */ >>>> + env_add(name, value); >>>> + >>>> + return xstrdup(value); >>>> +} >>>> + >>>> +void env_write_dep(FILE *f, const char *autoconfig_name) >>>> +{ >>>> + struct env *e, *tmp; >>>> + >>>> + list_for_each_entry_safe(e, tmp, &env_list, node) { >>>> + fprintf(f, "ifneq \"$(%s)\" \"%s\"\n", e->name, e->value); >>>> + fprintf(f, "%s: FORCE\n", autoconfig_name); >>>> + fprintf(f, "endif\n"); >>>> + env_del(e); >>>> + } >>>> +} >>>> + >>>> +static char *eval_clause(const char *in) >>>> +{ >>>> + char *res, *name; >>>> + >>>> + /* >>>> + * Returns an empty string because '$()' should be evaluated >>>> + * to a null string. >>>> + */ >>> >>> Do you know of cases where this is more useful than erroring out? >>> >>> Not saying it doesn't make sense. Just curious. >> >> >> I just followed how Make works. >> >> Anyway, eval_clause() will return null string for null input. >> I will remove that hunk. >> >> >> >> >>>> + if (!*in) >>>> + return xstrdup(""); >>>> + >>>> + name = expand_string(in); >>>> + >>>> + res = env_expand(name); >>>> + free(name); >>>> + >>>> + return res; >>>> +} >>>> + >>>> +/* >>>> + * Expand a string that follows '$' >>>> + * >>>> + * For example, if the input string is >>>> + * ($(FOO)$($(BAR)))$(BAZ) >>>> + * this helper evaluates >>>> + * $($(FOO)$($(BAR))) >>>> + * and returns the resulted string, then updates 'str' to point to the next >>> >>> s/resulted/resulting/ >>> >>> Maybe something like this would make the behavior a bit clearer: >>> >>> ...and returns a new string containing the expansion, also advancing >>> 'str' to point to the next character after... (note that this function does >>> a recursive expansion) ... >> >> >> Is this OK? >> >> /* >> * Expand a string that follows '$' >> * >> * For example, if the input string is >> * ($(FOO)$($(BAR)))$(BAZ) >> * this helper evaluates >> * $($(FOO)$($(BAR))) >> * and returns a new string containing the expansion (note that the string is >> * recursively expanded), also advancing 'str' to point to the next character >> * after the corresponding closing parenthesis, in this case, *str will be >> * $(BAR) >> */ > > Looks fine to me. > >> >> >> >>>> + * character after the corresponding closing parenthesis, in this case, *str >>>> + * will be >>>> + * $(BAR) >>>> + */ >>>> +char *expand_dollar(const char **str) >>>> +{ >>>> + const char *p = *str; >>>> + const char *q; >>>> + char *tmp, *out; >>>> + int nest = 0; >>>> + >>>> + /* '$$' represents an escaped '$' */ >>>> + if (*p == '$') { >>>> + *str = p + 1; >>>> + return xstrdup("$"); >>>> + } >>>> + >>>> + /* >>>> + * Kconfig does not support single-letter variable as in $A >>>> + * or curly braces as in ${CC}. >>>> + */ >>>> + if (*p != '(') >>>> + pperror("syntax error: '$' not followed by '('", p); >>> >>> Could say "not followed by '(' by or '$'". >> >> Will do. >> >> >>>> + >>>> + p++; >>>> + q = p; >>>> + while (*q) { >>>> + if (*q == '(') { >>>> + nest++; >>>> + } else if (*q == ')') { >>>> + if (nest-- == 0) >>>> + break; >>>> + } >>>> + q++; >>>> + } >>>> + >>>> + if (!*q) >>>> + pperror("unterminated reference to '%s': missing ')'", p); >>>> + >>>> + tmp = xmalloc(q - p + 1); >>>> + memcpy(tmp, p, q - p); >>>> + tmp[q - p] = 0; >>>> + *str = q + 1; >>>> + out = eval_clause(tmp); >>>> + free(tmp); >>>> + >>>> + return out; >>> >>> This might be a bit clearer, since the 'str' update and the expansion >>> are independent: >> >> Indeed, will do. >> >>> >>> /* Advance 'str' to after the expanded initial portion of the string */ >>> *str = q + 1; >>> >>> /* Save the "FOO" part of "(FOO)" into 'tmp' and expand it recursively */ >>> tmp = xmalloc(q - p + 1); >>> memcpy(tmp, p, q - p); >>> tmp[q - p] = '\0'; >>> out = eval_clause(tmp); >>> free(tmp); >>> >>> return out; >>> >>> ...or switched around, but thought putting the 'str' bit first might >>> emphasize that it isn't modified. >> >> >> I prefer advancing the pointer at last. > > Yeah, it's a bit less weird in a way... > >> >> >> >> >>>> +} >>>> + >>>> +/* >>>> + * Expand variables in the given string. Undefined variables >>>> + * expand to an empty string. >>> >>> I wonder what the tradeoffs are vs. erroring out here (or leaving >>> undefined variables as-is). >> >> >> I want to stick to the Make-like behavior here and exploit it in some cases. >> We can set some variables in some arch/*/Kconfig, >> but unset in the others. >> >> >> >> >> In some arch/*/Kconfig: >> >> min-gcc-version := 40900 >> >> >> >> >> In init/Kconfig: >> >> # GCC 4.5 is required to build Linux Kernel. >> # Some architectures may override it (from arch/*/Kconfig) for their >> requirement. >> min-gcc-version := $(if,$(min-gcc-version),$(min-gcc-version),40500) >> >> ... check the gcc version, then show error >> if it is older than $(min-gcc-version). > > OK, makes sense. Fine by me. > >>>> + * The returned string must be freed when done. >>>> + */ >>>> +char *expand_string(const char *in) >>>> +{ >>>> + const char *prev_in, *p; >>>> + char *new, *out; >>>> + size_t outlen; >>>> + >>>> + out = xmalloc(1); >>>> + *out = 0; >>>> + >>>> + while ((p = strchr(in, '$'))) { >>>> + prev_in = in; >>>> + in = p + 1; >>>> + new = expand_dollar(&in); >>>> + outlen = strlen(out) + (p - prev_in) + strlen(new) + 1; >>>> + out = xrealloc(out, outlen); >>>> + strncat(out, prev_in, p - prev_in); >>>> + strcat(out, new); >>>> + free(new); >>> >>> Some code duplication with expand_one_token() here. Do you think >>> something could be factored out/reorganized? >> >> >> Yes. For example, the following would work. >> If you prefer that, I can update it in v5. >> >> >> >> >> static char *__expand_string(const char **str, bool (*is_end)(const char *)) >> { >> const char *in, *prev_in, *p; >> char *new, *out; >> size_t outlen; >> >> out = xmalloc(1); >> *out = 0; >> >> p = in = *str; >> >> while (1) { >> if (*p == '$') { >> prev_in = in; >> in = p + 1; >> new = expand_dollar(&in); >> outlen = strlen(out) + (p - prev_in) + strlen(new) + 1; >> out = xrealloc(out, outlen); >> strncat(out, prev_in, p - prev_in); >> strcat(out, new); >> free(new); >> p = in; >> continue; >> } >> >> if (is_end(p)) >> break; >> >> p++; >> } >> >> outlen = strlen(out) + (p - in) + 1; >> out = xrealloc(out, outlen); >> strncat(out, in, p - in); >> >> *str = p; >> >> return out; >> } >> >> static bool is_end_of_str(const char *s) >> { >> return !*s; >> } >> >> char *expand_string(const char *in) >> { >> return __expand_string(&in, is_end_of_str); >> } >> >> static bool is_end_of_token(const char *s) >> { >> return !(isalnum(*s) || *s == '_' || *s == '-' || *s == '.' || >> *s == '/'); >> } >> >> char *expand_one_token(const char **str) >> { >> return __expand_string(str, is_end_of_token); >> } > > Yep, something like that would be nicer I think. > > This variant might work too (untested): > > dollar_i = p; dollar_p makes more sense. Cheers, Ulf