Received: by 10.213.65.68 with SMTP id h4csp1208289imn; Sat, 31 Mar 2018 23:08:49 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+jrab3v/B/xo7g3hbO0cZmbxlcMTpchq7/hSAKFfK9gP/zPAlelnlyrz8TWVJbUWDZ4hE9 X-Received: by 10.98.10.156 with SMTP id 28mr3914479pfk.33.1522562929477; Sat, 31 Mar 2018 23:08:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1522562929; cv=none; d=google.com; s=arc-20160816; b=tT+nLosXskFm4nSI4c60tD/v7XIvCRLoYHVZ6NW6hlGfLNg4HfV4jv0b/68Ja6PoQZ lyD7W/RadjQBWNYj/ZMqwQFSazjbEbTu2QAaYOvEI4TCz1M71lCOCDOJRxUB7cP/2t8c QOItGgJ/HJSAHiw2Ay87iF9VLx9sOBtPgLNODpAxDU6YFOR/ABrYZ1lvApw+mPPvyByJ G5ld9G5R4d4TBkIrpa2DFP07F32r65fzc1Bx+P6EfbWRWXNd3sFuWYa6JQZe3JyE3WI2 E9nJ+/Tgeg2Q7jljHLFZgCwg+Sgsm/HnFTDRaFTrhgLXBWrFrYznFcU9u9cCVcI0sSCg VzAQ== 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=XmELWTyJzp0dyKO8Z/dHPcatImXLLovNf6h5F7oVLWk=; b=c2jZhIDYjhYVmGOGhEld5KLHV29488ZM/KYkSVTEodvYna9Iu1DwKVqgW/1oq/z7b7 XStfjyVN3BVhRbQ9B/tckQj0NM04sk+8hCf1HObgwH8/E+xGR3OzAOMsI+yVQjYm2u9z +7Iw8cBHUYQyIUVQakKgr9Jgp60iu0PhMlB1+X12lIFYnlPo70W2iaba6Lsc6l5SMTQ+ kCZ3A1SXarFhqcaJOXe5x0NXhY1WH/QzEFvpCKrNspVDIE6hHYgq/GUjeuC7azcIEK2S xtgyCYc+jK4bdH81fl2SrinZPwRhUcqLLdIZjrAHiVQpuJhizfEoW4B0bEh++qK/cpJV wsRQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=Le2qRhtQ; 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 g3-v6si12184082pll.290.2018.03.31.23.08.14; Sat, 31 Mar 2018 23:08:49 -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=Le2qRhtQ; 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 S1751005AbeDAGFk (ORCPT + 99 others); Sun, 1 Apr 2018 02:05:40 -0400 Received: from mail-ua0-f193.google.com ([209.85.217.193]:41379 "EHLO mail-ua0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750737AbeDAGFi (ORCPT ); Sun, 1 Apr 2018 02:05:38 -0400 Received: by mail-ua0-f193.google.com with SMTP id g2so1527988uan.8; Sat, 31 Mar 2018 23:05:37 -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=XmELWTyJzp0dyKO8Z/dHPcatImXLLovNf6h5F7oVLWk=; b=Le2qRhtQRB67Ap+b0H+1jnVDEGLUjtlb6TBTqhE8znJRowYaGHRWemBOVtqsTt3TQI GQTVPYKxqyeUl4kKzO52Tk3ttyJGLGooKjZzE8sigGKqsXHGxZCuYDuoAMZjjyg9H61p iHtAoHsxVl8O4dlahuQ+sF17tYtWuW6vVy4jnmyyzyG65C2jx5hIxTrI/qk247zGGE/3 NYWI2epVLecK4EIM8R65SyFkltssUhJkcmxm3KXotRJNuPcUNlr4hrpn5gQuECyX+Zmc AICyLNgn+u+I0r6j3GRVW8QQoRchexVMY9P8OZgBbrI4Mv9R76Vxv+uHK2o9j0Ydql1d 4hkw== 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=XmELWTyJzp0dyKO8Z/dHPcatImXLLovNf6h5F7oVLWk=; b=HMakHOS23LA6udmHjqNXKkHjYiyydLOv+mPZcLp5AL38Eh4xxfgROqxt5XLK+HVWuF /Gvs+PPKRpy4/ONQP+NNdpthBZiAEWwezrjZZmDm5nxh37c4gIDupSMM5vm9dXhTkzQc 6014c6dXBhbk5tdrem3g9Pk+fQX6LF3697o/XVwZygAN8eyVCSLFsMWkwjl9q5FnTcqc m8n4BC8Tv0XzJYU9UoMba8dTER4by0F8fBMCDtcT8KNma+yqDcjWukVB4jCr86Nms4kR UReUXtnbsI2pzZ/M0nHy4cL7HqnGhjwJPkHfslu7azbnKvjVvPEAnSlL9HgUEaoH/bd3 vH7Q== X-Gm-Message-State: AElRT7HkhGZaLMXfDPznqHs5aR9bHgwJXt+BTYKyvAqN0+rzWBuvElqo bEW7MCtD0MMZ62dbYX3mIJqw/UkOtpcDvsvnPs4= X-Received: by 10.176.93.26 with SMTP id u26mr2881382uaf.70.1522562735800; Sat, 31 Mar 2018 23:05:35 -0700 (PDT) MIME-Version: 1.0 Received: by 10.103.206.5 with HTTP; Sat, 31 Mar 2018 23:05:35 -0700 (PDT) In-Reply-To: <1522128575-5326-10-git-send-email-yamada.masahiro@socionext.com> References: <1522128575-5326-1-git-send-email-yamada.masahiro@socionext.com> <1522128575-5326-10-git-send-email-yamada.masahiro@socionext.com> From: Ulf Magnusson Date: Sun, 1 Apr 2018 08:05:35 +0200 Message-ID: Subject: Re: [PATCH v2 09/21] kconfig: add 'macro' keyword to support user-defined function 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 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 Tue, Mar 27, 2018 at 7:29 AM, Masahiro Yamada wrote: > Now, we got a basic ability to test compiler capability in Kconfig. > > config CC_HAS_STACKPROTECTOR > def_bool $(shell (($CC -Werror -fstack-protector -c -x c /dev/null -o /dev/null) && echo y) || echo n) > > This works, but it is ugly to repeat this long boilerplate. > > We want to describe like this: > > config CC_HAS_STACKPROTECTOR > bool > default $(cc-option -fstack-protector) > > It is straight-forward to add a new function, but I do not like to > hard-code specialized functions like this. Hence, here is another > feature to add functions from Kconfig files. > > A user-defined function is defined with a special keyword 'macro'. > It can be referenced in the same way as built-in functions. This > feature was also inspired by Makefile where user-defined functions > are referenced by $(call func-name, args...), but I omitted the 'call' > to makes it shorter. > > The macro definition can contain $(1), $(2), ... which will be replaced > with arguments from the caller. The macro works just as a textual > shorthand, which is also expanded in the lexer phase. > > [Example Code] > > macro success $(shell ($(1) && echo y) || echo n) > > config TRUE > bool "true" > default $(success true) > > config FALSE > bool "false" > default $(success false) > > [Result] > > $ make -s alldefconfig > $ tail -n 2 .config > CONFIG_TRUE=y > # CONFIG_FALSE is not set > > [Example Code] > > macro success $(shell ($(1) && echo y) || echo n) > > macro cc-option $(success $CC -Werror $(1) -c -x c /dev/null -o /dev/null) > > config CC_HAS_STACKPROTECTOR > def_bool $(cc-option -fstack-protector) > > [Result] > $ make -s alldefconfig > $ tail -n 1 .config > CONFIG_CC_HAS_STACKPROTECTOR=y > > Signed-off-by: Masahiro Yamada > --- > > Reminder for myself: > Update Documentation/kbuild/kconfig-language.txt > > Changes in v2: > - Use 'macro' directly instead of inside the string type symbol. > > scripts/kconfig/function.c | 59 +++++++++++++++++++++++++++++++++++++++++++-- > scripts/kconfig/lkc_proto.h | 1 + > scripts/kconfig/zconf.l | 31 ++++++++++++++++++++++++ > 3 files changed, 89 insertions(+), 2 deletions(-) > > diff --git a/scripts/kconfig/function.c b/scripts/kconfig/function.c > index 913685f..389bb44 100644 > --- a/scripts/kconfig/function.c > +++ b/scripts/kconfig/function.c > @@ -15,6 +15,7 @@ static LIST_HEAD(function_list); > struct function { > char *name; > char *(*func)(struct function *f, int argc, char *argv[]); > + char *macro; > struct list_head node; > }; > > @@ -31,7 +32,8 @@ static struct function *func_lookup(const char *name) > } > > static void func_add(const char *name, > - char *(*func)(struct function *f, int argc, char *argv[])) > + char *(*func)(struct function *f, int argc, char *argv[]), > + const char *macro) > { > struct function *f; > > @@ -44,6 +46,7 @@ static void func_add(const char *name, > f = xmalloc(sizeof(*f)); > f->name = xstrdup(name); > f->func = func; > + f->macro = macro ? xstrdup(macro) : NULL; > > list_add_tail(&f->node, &function_list); > } > @@ -51,6 +54,7 @@ static void func_add(const char *name, > static void func_del(struct function *f) > { > list_del(&f->node); > + free(f->macro); > free(f->name); > free(f); > } > @@ -108,6 +112,57 @@ char *func_eval_n(const char *func, size_t n) > return res; > } > > +/* run user-defined function */ > +static char *do_macro(struct function *f, int argc, char *argv[]) > +{ > + char *new; > + char *src, *p, *res; > + size_t newlen; > + int n; > + > + new = xmalloc(1); > + *new = 0; new = '\0' would be consistent with the rest of the code. > + > + /* > + * This is a format string. $(1), $(2), ... must be replaced with > + * function arguments. > + */ > + src = f->macro; > + p = src; > + > + while ((p = strstr(p, "$("))) { > + if (isdigit(p[2]) && p[3] == ')') { > + n = p[2] - '0'; > + if (n < argc) { > + newlen = strlen(new) + (p - src) + > + strlen(argv[n]) + 1; > + new = xrealloc(new, newlen); > + strncat(new, src, p - src); > + strcat(new, argv[n]); > + src = p + 4; > + } Might be nice to warn when a macro call has missing arguments. > + p += 2; > + } > + p += 2; > + } I had to stare at this for a while to see how it worked. What do you think of this tweak? while ((p = strstr(p, "$("))) { if (isdigit(p[2]) && p[3] == ')') { n = p[2] - '0'; if (n < argc) { newlen = strlen(new) + (p - src) + strlen(argv[n]) + 1; new = xrealloc(new, newlen); strncat(new, src, p - src); strcat(new, argv[n]); /* * Jump past macro parameter ("$(n)") and remember the * position */ p += 4; src = p; continue; } } /* Jump past "$(" that isn't from a macro parameter */ p += 2; } > + > + newlen = strlen(new) + strlen(src) + 1; > + new = xrealloc(new, newlen); > + strcat(new, src); > + > + res = expand_string_value(new); > + > + free(new); > + > + return res; > +} > + > +/* add user-defined function (macro) */ > +void func_add_macro(const char *name, const char *macro) > +{ > + func_add(name, do_macro, macro); > +} > + > /* built-in functions */ > static char *do_shell(struct function *f, int argc, char *argv[]) > { > @@ -157,7 +212,7 @@ static char *do_shell(struct function *f, int argc, char *argv[]) > void func_init(void) > { > /* register built-in functions */ > - func_add("shell", do_shell); > + func_add("shell", do_shell, NULL); > } > > void func_exit(void) > diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h > index 09a4f53..48699c0 100644 > --- a/scripts/kconfig/lkc_proto.h > +++ b/scripts/kconfig/lkc_proto.h > @@ -50,6 +50,7 @@ const char * prop_get_type_name(enum prop_type type); > > /* function.c */ > char *func_eval_n(const char *func, size_t n); > +void func_add_macro(const char *name, const char *macro); > void func_init(void); > void func_exit(void); > > diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l > index 551ca47..6a18c68 100644 > --- a/scripts/kconfig/zconf.l > +++ b/scripts/kconfig/zconf.l > @@ -74,6 +74,36 @@ static void warn_ignored_character(char chr) > "%s:%d:warning: ignoring unsupported character '%c'\n", > zconf_curname(), zconf_lineno(), chr); > } > + > +static void handle_macro(const char *text) > +{ > + char *p, *q; > + > + while (isspace(*text)) > + text++; > + > + p = xstrdup(text); > + > + q = p; > + while (isalnum(*q) || *q == '_' || *q == '-') > + q++; > + > + if (q == p || !*q) { > + yyerror("invalid\n"); > + goto free; > + } > + > + *q = '\0'; > + > + q++; > + while (isspace(*q)) > + q++; > + > + func_add_macro(p, q); > +free: > + free(p); > +} > + > %} > > n [A-Za-z0-9_-] > @@ -82,6 +112,7 @@ n [A-Za-z0-9_-] > int str = 0; > int ts, i; > > +"macro"[ \t].* handle_macro(yytext + 6); > [ \t]*#.*\n | > [ \t]*\n { > return T_EOL; > -- > 2.7.4 > Cheers, Ulf