public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Pedro Alves <pedro@palves.net>
To: Keith Seitz <keiths@redhat.com>, gdb-patches@sourceware.org
Cc: Wendy.Peikes@netapp.com
Subject: Re: [RFC PATCH 2/2] Allow and evaluate expressions in command arguments
Date: Fri, 17 Feb 2023 22:31:09 +0000	[thread overview]
Message-ID: <7ce34978-479b-aea3-0ce5-b94e66ecf5bf@palves.net> (raw)
In-Reply-To: <20230125193825.3665649-3-keiths@redhat.com>

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);
> 


  parent reply	other threads:[~2023-02-17 22:31 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <BYAPR06MB6117A6A68D09026F27C310D4E54C9@BYAPR06MB6117.namprd06.prod.outlook.com>
     [not found] ` <BYAPR06MB611721469E1454F0CD94259DE55D9@BYAPR06MB6117.namprd06.prod.outlook.com>
2022-10-05 23:19   ` [PATCH] gdb: allow env var specifications in cmds 'set log', 'source', 'shell' Peikes, Wendy
2022-10-05 23:19     ` Peikes, Wendy
2022-10-06 19:34     ` Keith Seitz
2022-10-26  0:25       ` Peikes, Wendy
2023-01-25 19:38         ` [RFC PATCH 0/2] Command expression evaulation substitution Keith Seitz
2023-01-25 19:38           ` [RFC PATCH 1/2] Add $_env convenience function Keith Seitz
2023-02-03 17:18             ` Andrew Burgess
2023-02-03 18:34               ` Keith Seitz
2023-01-25 19:38           ` [RFC PATCH 2/2] Allow and evaluate expressions in command arguments Keith Seitz
2023-02-03 17:22             ` Andrew Burgess
2023-02-03 18:49               ` Keith Seitz
2023-02-17 22:31             ` Pedro Alves [this message]
2023-01-25 20:21           ` [RFC PATCH 0/2] Command expression evaulation substitution Peikes, Wendy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7ce34978-479b-aea3-0ce5-b94e66ecf5bf@palves.net \
    --to=pedro@palves.net \
    --cc=Wendy.Peikes@netapp.com \
    --cc=gdb-patches@sourceware.org \
    --cc=keiths@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).