From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) by sourceware.org (Postfix) with ESMTPS id F41E2385828E for ; Fri, 17 Feb 2023 22:31:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F41E2385828E Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=palves.net Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wm1-f54.google.com with SMTP id ja15-20020a05600c556f00b003dc52fed235so1875169wmb.1 for ; Fri, 17 Feb 2023 14:31:14 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:content-language:in-reply-to:mime-version :user-agent:date:message-id:from:references:cc:to:subject :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=BGlCQMmOYFEgQq0Kl4CWdBR30WFuVFzTY4SWe7dtCJU=; b=ZhOvu8TFPJBkMGcZIscB2RLmUVx4iZkFXJvCI35ATXkTrrbptS8aeXW5Yh0vJ9FxPZ yQETr8o7r9bAsKv0YdIq6J/uIBQOge9sbzZeaMMg2sMxHJh/coicFeGS6mPeFHWUf2Ua smCRdAKpMo/UjpSVbXyGYYjUa8qdns28PHiCTdMHsRTMog0OEgSfm9WnDgLCwj9ZM/2K To9HAc78rUAY8aUOBX4z/Pj6MHEW3E/d5N73gya7kX9GiGnS7qszMmdmMJ7Qv+ASaC9k U/Yo+qnAhU9ara9a0prgbDRxbAIqyUtHzXH2f0QqqFSCIbzVv6AR6qlvELX3yBNRgAFg wGNg== X-Gm-Message-State: AO0yUKXuFfEUXO7F/C/W4hx/9S0fKnMVixwu9HnHgLkohCP4QITIO6A9 snYf/Cg8IwbTJkcc53LcrUU46UfH/RyNIA== X-Google-Smtp-Source: AK7set91eEB/y8lH1cHBaspNWJkrbzkR8aN0LR5frqvwnj8//CMGMuRGXRTCy1u2Q5/wCU0WoJQ5gA== X-Received: by 2002:a05:600c:6011:b0:3e2:2057:b9d6 with SMTP id az17-20020a05600c601100b003e22057b9d6mr3032129wmb.20.1676673073575; Fri, 17 Feb 2023 14:31:13 -0800 (PST) Received: from ?IPv6:2001:8a0:f92b:9e00::1fe? ([2001:8a0:f92b:9e00::1fe]) by smtp.gmail.com with ESMTPSA id 1-20020a05600c028100b003e200dc15f5sm6299581wmk.42.2023.02.17.14.31.12 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 17 Feb 2023 14:31:13 -0800 (PST) Subject: Re: [RFC PATCH 2/2] Allow and evaluate expressions in command arguments To: Keith Seitz , gdb-patches@sourceware.org Cc: Wendy.Peikes@netapp.com References: <20230125193825.3665649-1-keiths@redhat.com> <20230125193825.3665649-3-keiths@redhat.com> From: Pedro Alves Message-ID: <7ce34978-479b-aea3-0ce5-b94e66ecf5bf@palves.net> Date: Fri, 17 Feb 2023 22:31:09 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.10.1 MIME-Version: 1.0 In-Reply-To: <20230125193825.3665649-3-keiths@redhat.com> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,GIT_PATCH_0,HEADER_FROM_DIFFERENT_DOMAINS,KAM_DMARC_STATUS,NICE_REPLY_A,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Hi Keith! On 2023-01-25 7:38 p.m., Keith Seitz via Gdb-patches wrote: > This patch adds support for arbitrary expressions to be passed to > GDB commands, evaluated, and the results substituted into command > arguments. > > This allows users to pass arbitrary expressions into commands which > currently do not support any way of doing this. This is especially > useful with, for example, convenience variables and functions. > > Example: > $ export MYDIR="tmp" > $ export MYFILE="simple" > $ gdb -nx -q > (gdb) file $($_env("HOME"))/$($_env("MYDIR"))/$($_env("MYFILE")) > Reading symbols from /home/keiths/tmp/simple... > (gdb) > > In order to mark the bounds of expressions to be evaluated, I've > introduced the (arbitrary) marker "$()". Everything contained inside > this marker will be passed to the expression parser, evaluated, printed > as a string, and then substituted for the original expression. I'm afraid I think we can't take this in this form. The reason is that CLI commands don't have a common parser, every command parses things its own way. And then we have commands which take language expressions. So there's substantial risk that whatever syntax we come up with, conflicts with syntax used by either some command, or some language. This is a similar reason why we ended up with a "pipe" command instead of teaching the command parser about the pipe character itself. I think an approach like that would work. So you'd add a new prefix command whose job is to do some expansion, and then execute the resulting command. "eval" is actually similar. Or maybe exactly it? Maybe we don't need a new command, but we add enough internal functions so that you can use "eval" for this. So if we have your $_env convenience function, we should be able to write: (gdb) eval "file %s/%s/%s", $_env("HOME"), $_env("MYDIR"), $_env("MYFILE") If that doesn't work, then I think we should fix it. Pedro Alves > --- > gdb/top.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 65 insertions(+) > > diff --git a/gdb/top.c b/gdb/top.c > index 205eb360ba3..3f394b5b63c 100644 > --- a/gdb/top.c > +++ b/gdb/top.c > @@ -57,6 +57,8 @@ > #include "gdbsupport/pathstuff.h" > #include "cli/cli-style.h" > #include "pager.h" > +#include "valprint.h" > +#include "cp-support.h" /* for find_toplevel_char */ > > /* readline include files. */ > #include "readline/readline.h" > @@ -567,6 +569,60 @@ set_repeat_arguments (const char *args) > repeat_arguments = args; > } > > +/* Evaluate and expand any expressions in the command line list of arguments > + given by ORIG_ARGS. All occurrences of "$(expr)" will be replaced with a > + string representation of the evaluated EXPR. */ > + > +#define EVAL_START_STRING "$(" > +#define EVAL_END_TOKEN ')' > + > +static std::string > +expand_command_arg (const char *orig_arg) > +{ > + std::string new_arg = orig_arg; > + std::string::size_type n = new_arg.find (EVAL_START_STRING); > + > + /* These needs adjustment to output "simple" strings. For example, > + if a char value is used, we end up with "97 'a'" instead of simply "a". */ > + struct value_print_options opts; > + get_user_print_options (&opts); > + > + string_file stb; > + > + while (n != std::string::npos) > + { > + const char *args = new_arg.c_str (); > + const char *c = find_toplevel_char (args + n + 2, EVAL_END_TOKEN); > + > + if (c != nullptr) > + { > + std::string expr = new_arg.substr (n + 2, c - args - n - 2); > + struct value *val = parse_and_eval (expr.c_str ()); > + > + value_print (val, &stb, &opts); > + > + /* If value_print returns a quote-enclosed string, remove the > + quote characters. */ > + std::string r = stb.release (); > + > + if (*r.begin () == '\"' && *r.rbegin () == '\"') > + { > + r.erase (r.begin ()); > + r.pop_back (); > + } > + > + new_arg.replace (n, c - args - n + 1, r); > + n = new_arg.find (EVAL_START_STRING); > + } > + } > + > +#if 0 > + if (new_arg != orig_arg) > + printf ("NEW_ARG = %s\n", new_arg.c_str ()); > +#endif > + return new_arg; > +} > + > /* Execute the line P as a command, in the current user context. > Pass FROM_TTY as second argument to the defining function. */ > > @@ -657,6 +713,15 @@ execute_command (const char *p, int from_tty) > if (c->deprecated_warn_user) > deprecated_cmd_warning (line, cmdlist); > > + /* Do any expression substitutions on ARG. */ > + std::string expanded_arg; > + > + if (arg != nullptr) > + { > + expanded_arg = expand_command_arg (arg); > + arg = expanded_arg.c_str (); > + } > + > /* c->user_commands would be NULL in the case of a python command. */ > if (c->theclass == class_user && c->user_commands) > execute_user_command (c, arg); >