From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 696FCC11F64 for ; Thu, 1 Jul 2021 06:21:02 +0000 (UTC) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E4A5B61607 for ; Thu, 1 Jul 2021 06:21:01 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E4A5B61607 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id B1BD3832CE; Thu, 1 Jul 2021 08:17:33 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Qx8Jl/Ar"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 7E06E8329E; Thu, 1 Jul 2021 08:17:12 +0200 (CEST) Received: from mail-qv1-xf2c.google.com (mail-qv1-xf2c.google.com [IPv6:2607:f8b0:4864:20::f2c]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 27A7083203 for ; Thu, 1 Jul 2021 08:16:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=seanga2@gmail.com Received: by mail-qv1-xf2c.google.com with SMTP id h18so2446386qve.1 for ; Wed, 30 Jun 2021 23:16:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=KrenbhitxI/89hlMktPHIkJa/RPxpeWWf4iVsXFkbyc=; b=Qx8Jl/Ar1i2UZ7euldCAVJbFcEyq95U9zSs1DFv1J4YQ5K0WUSlyLRyobR7LrP5T41 omENFxanp5Skj/BlBAtaXLOAIx8ovztxJ/HbXMYADqXL3cPhtVrRqsb2OvJhy2tQRn8T Z7seSxmH/AfscdSM0n1PCaf0S6unXTTgM+h/vn8wprtXFBfIYWv8PHGncTdwy8EgMXGQ jKijulXq1uwZIFaDWmZXps5gGvoG4PN8aaJSqqKSv1CWHHavXU7jnmotSFGhGtL1N5u5 7+aIixW3XCb4JbS1tV2xtQEnYjzvdXOK1vlXBGiqGNzKmoSC/9KsCOheTK9wQ6bemezl dpuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=KrenbhitxI/89hlMktPHIkJa/RPxpeWWf4iVsXFkbyc=; b=tqXjG3dAQt6l8nV8KvSX/VH5QZ+/QhTofRl05H39vQZgeopcrPofjfNwUbzcnooa/4 6J9UGFCTDoZAt7TYBLI2SamA2bk4EA1AC+QrJcaqq3xZiqG2+6DsJd8umoLcSz+/6sDv r+clki8CnpEPgJkvIPyk4Pr0yibTMT2+DtAdZdNcZTpYwXIz45fKPvZ6u8T6pyut2bvM UW86XCKO9etftRGjotnNEnc6yZfAVhXOLzp0HMyK7osjd32L4zTTql6FzYUPV3WmJcTf iCtHYZuUO3JsW0qz/aseOKf+AizofCIX1JEXrf3+VDwP1XhMZVtg46A/Ww1d1ZMhbGXt dyuw== X-Gm-Message-State: AOAM531MHJQv/ZzmPZgw74Uik3DypO6vAr3cD6sOOrVP/oCnOqp/GR7V NbocoNNH2i6MhIXkylO/b96mLnq17zA= X-Google-Smtp-Source: ABdhPJzK0xWO3nVR/eUr2mIodOJuTyDdRpWTtSoTmJE1rPNcDq6Mmo52dEx1YlZMNEeO5eDosI10ww== X-Received: by 2002:a0c:a124:: with SMTP id d33mr2535075qva.40.1625120195845; Wed, 30 Jun 2021 23:16:35 -0700 (PDT) Received: from godwin.fios-router.home (pool-74-96-87-9.washdc.fios.verizon.net. [74.96.87.9]) by smtp.gmail.com with ESMTPSA id g21sm1684673qts.90.2021.06.30.23.16.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Jun 2021 23:16:35 -0700 (PDT) From: Sean Anderson To: u-boot@lists.denx.de, Tom Rini Cc: =?UTF-8?q?Marek=20Beh=C3=BAn?= , Wolfgang Denk , Simon Glass , Roland Gaudig , Heinrich Schuchardt , Kostas Michalopoulos , Sean Anderson Subject: [RFC PATCH 28/28] cli: lil: Load procs from the environment Date: Thu, 1 Jul 2021 02:16:11 -0400 Message-Id: <20210701061611.957918-29-seanga2@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210701061611.957918-1-seanga2@gmail.com> References: <20210701061611.957918-1-seanga2@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean When we start up the LIL interpreter, go through every variable and see if it looks like a new procedure. If it does, try and parse it. For the return trip, every time that we create a new procedure, create a new global variable containing that procedure. The end result of this is that procedures should now be saved to the environment in the same way that variables are. So you can do => proc foo {args} { ... } => env save and foo will be there after you reboot. Signed-off-by: Sean Anderson --- common/cli.c | 54 ++++++++++++++++++++++++++++------- common/cli_lil.c | 71 ++++++++++++++++++++++++++++++++++------------- include/cli_lil.h | 17 ++++++++++++ 3 files changed, 113 insertions(+), 29 deletions(-) diff --git a/common/cli.c b/common/cli.c index 391fee0ec7..c71f75e684 100644 --- a/common/cli.c +++ b/common/cli.c @@ -16,9 +16,11 @@ #include #include #include +#include #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -26,6 +28,21 @@ DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_LIL static struct lil *lil; +static enum lil_error print_lil_err(struct lil *lil) +{ + enum lil_error ret; + const char *err_msg; + + ret = lil_error(lil, &err_msg); + if (ret) { + if (err_msg) + printf("error: %s\n", err_msg); + else + printf("error: %d\n", ret); + } + return ret; +} + static int env_setvar(struct lil *lil, const char *name, struct lil_value **value) { @@ -41,16 +58,40 @@ static int env_getvar(struct lil *lil, const char *name, return 1; } +static int env_register_proc(struct env_entry *entry, void *priv) +{ + struct lil *lil = priv; + struct lil_value *name; + const char *name_str, prefix[] = "proc"; + + /* Skip variables which are obviously not procedures */ + if (strncmp(entry->data, prefix, sizeof(prefix) - 1)) + return 0; + + name = lil_parse_eval(lil, entry->data, 0, true); + name_str = lil_to_string(name); + if (strcmp(entry->key, name_str)) + log_debug("proc %s created by variable %s\n", + name_str, entry->key); + lil_free_value(name); + return print_lil_err(lil); +} + +static int env_initprocs(struct lil *lil) +{ + return hwalk_r(&env_htab, env_register_proc, lil); +} + static const struct lil_callbacks env_callbacks = { .setvar = env_setvar, .getvar = env_getvar, + .initprocs = env_initprocs, }; static int lil_run(const char *cmd) { - int err; struct lil_value *result = lil_parse_eval(lil, cmd, 0, true); - const char *err_msg, *strres = lil_to_string(result); + const char *strres = lil_to_string(result); /* The result may be very big, so use puts */ if (strres && strres[0]) { @@ -59,14 +100,7 @@ static int lil_run(const char *cmd) } lil_free_value(result); - err = lil_error(lil, &err_msg); - if (err) { - if (err_msg) - printf("error: %s\n", err_msg); - else - printf("error: %d\n", err); - } - return !!err; + return !!print_lil_err(lil); } #endif diff --git a/common/cli_lil.c b/common/cli_lil.c index 2a8600ffb6..7b4a56dbd0 100644 --- a/common/cli_lil.c +++ b/common/cli_lil.c @@ -3218,9 +3218,11 @@ static struct lil_value *fnc_reflect(struct lil *lil, size_t argc, static struct lil_value *fnc_proc(struct lil *lil, size_t argc, struct lil_value **argv) { + static const char fmt[] = "proc %s {%s} %s"; + size_t n; struct lil_func *cmd; - struct lil_list *args; - struct lil_value *name, *code; + struct lil_list *fargs; + struct lil_value *name, *args, *code, *val; if (argc != 3) { lil_set_error_argc(lil, 3); @@ -3228,34 +3230,62 @@ static struct lil_value *fnc_proc(struct lil *lil, size_t argc, } name = lil_clone_value(argv[0]); - if (!name) { - lil_set_error_oom(lil); - return NULL; - } - - args = lil_subst_to_list(lil, argv[1]); - if (!args) - goto err_args; - code = lil_clone_value(argv[2]); - if (!code) { + if (!name || !code) { lil_set_error_oom(lil); - goto err_code; + goto err_name_fargs_code; } + fargs = lil_subst_to_list(lil, argv[1]); + if (!fargs) + goto err_name_fargs_code; + cmd = add_func(lil, lil_to_string(name)); if (!cmd) goto err_func; - cmd->argnames = args; + cmd->argnames = fargs; cmd->code = code; + args = lil_list_to_value(fargs); + code = lil_quote_value(code); + if (!args || !code) { + lil_set_error_oom(lil); + goto err_quote_val; + } + + n = snprintf(NULL, 0, fmt, lil_to_string(name), lil_to_string(args), + lil_to_string(code)); + val = alloc_value_len(NULL, n); + if (!val) { + lil_set_error_oom(lil); + goto err_quote_val; + } + + snprintf(val->d, n + 1, fmt, lil_to_string(name), lil_to_string(args), + lil_to_string(code)); + val->l = n; + if (!lil_set_var(lil, lil_to_string(name), val, LIL_SETVAR_GLOBAL)) + goto err_set; + + lil_free_value(val); + lil_free_value(code); + lil_free_value(args); + return name; -err_func: +err_set: + lil_free_value(val); +err_quote_val: + del_func(lil, cmd); + lil_free_value(code); + lil_free_value(args); + lil_free_value(name); + return NULL; + +err_func: + lil_free_list(fargs); +err_name_fargs_code: lil_free_value(code); -err_code: - lil_free_list(args); -err_args: lil_free_value(name); return NULL; } @@ -4235,12 +4265,15 @@ static void register_stdcmds(struct lil *lil) struct cmd_tbl *cmdtp, *start = ll_entry_start(struct cmd_tbl, cmd); const int len = ll_entry_count(struct cmd_tbl, cmd); + lil_register(lil, "proc", fnc_proc); + if (lil->callbacks.initprocs) + lil->callbacks.initprocs(lil); + lil_register(lil, "decr", fnc_decr); lil_register(lil, "eval", fnc_eval); lil_register(lil, "expr", fnc_expr); lil_register(lil, "for", fnc_for); lil_register(lil, "foreach", fnc_foreach); - lil_register(lil, "proc", fnc_proc); lil_register(lil, "if", fnc_if); lil_register(lil, "incr", fnc_incr); lil_register(lil, "local", fnc_local); diff --git a/include/cli_lil.h b/include/cli_lil.h index 6fbc270f1b..47a2eeefc9 100644 --- a/include/cli_lil.h +++ b/include/cli_lil.h @@ -94,6 +94,23 @@ struct lil_callbacks { */ int (*getvar)(struct lil *lil, const char *name, struct lil_value **value); + + /** + * @initprocs: Called when procedures should be created + * + * @lil: The LIL interpreter + * + * This is called once in lil_new() when user functions should be added. + * When this is called, the only function registered is "proc". You can + * register functions by calling lil_parse_eval() with code which + * initializes a procedure. + * + * In practice, this is expected to be used to initialize procedures + * from environmental variables. + * + * @Return: 0 if ok, or non-zero on error. + */ + int (*initprocs)(struct lil *lil); }; /** -- 2.32.0