mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-24 02:24:46 +08:00
Let gdb.execute handle multi-line commands
This changes the Python API so that gdb.execute can now handle multi-line commands, like "commands" or "define". ChangeLog 2018-05-04 Tom Tromey <tom@tromey.com> PR python/22730: * NEWS: Mention gdb.execute change. * gdbcmd.h (execute_control_command): Don't declare. * python/python.c (execute_gdb_command): Use read_command_lines_1, execute_control_commands, execute_control_commands_to_string. * cli/cli-script.h (execute_control_commands) (execute_control_commands_to_string): Declare. (execute_control_command): Add from_tty parameter. * cli/cli-script.c (execute_control_commands) (execute_control_commands_to_string): New functions. (execute_user_command): Use execute_control_commands. (execute_control_command_1): Add "from_tty" parameter. Update. (execute_control_command): Likewise. testsuite/ChangeLog 2018-05-04 Tom Tromey <tom@tromey.com> PR python/22730: * gdb.python/python.exp: Test multi-line execute.
This commit is contained in:
parent
a913fffbde
commit
56bcdbea2b
@ -1,3 +1,19 @@
|
|||||||
|
2018-05-04 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
|
PR python/22730:
|
||||||
|
* NEWS: Mention gdb.execute change.
|
||||||
|
* gdbcmd.h (execute_control_command): Don't declare.
|
||||||
|
* python/python.c (execute_gdb_command): Use read_command_lines_1,
|
||||||
|
execute_control_commands, execute_control_commands_to_string.
|
||||||
|
* cli/cli-script.h (execute_control_commands)
|
||||||
|
(execute_control_commands_to_string): Declare.
|
||||||
|
(execute_control_command): Add from_tty parameter.
|
||||||
|
* cli/cli-script.c (execute_control_commands)
|
||||||
|
(execute_control_commands_to_string): New functions.
|
||||||
|
(execute_user_command): Use execute_control_commands.
|
||||||
|
(execute_control_command_1): Add "from_tty" parameter. Update.
|
||||||
|
(execute_control_command): Likewise.
|
||||||
|
|
||||||
2018-05-04 Tom Tromey <tom@tromey.com>
|
2018-05-04 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
PR python/22731:
|
PR python/22731:
|
||||||
|
2
gdb/NEWS
2
gdb/NEWS
@ -34,6 +34,8 @@ set|show record btrace cpu
|
|||||||
** The commands attached to a breakpoint can be set by assigning to
|
** The commands attached to a breakpoint can be set by assigning to
|
||||||
the breakpoint's "commands" field.
|
the breakpoint's "commands" field.
|
||||||
|
|
||||||
|
** gdb.execute can now execute multi-line gdb commands.
|
||||||
|
|
||||||
* New targets
|
* New targets
|
||||||
|
|
||||||
RiscV ELF riscv*-*-elf
|
RiscV ELF riscv*-*-elf
|
||||||
|
@ -374,12 +374,69 @@ execute_cmd_post_hook (struct cmd_list_element *c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See cli-script.h. */
|
||||||
|
|
||||||
|
void
|
||||||
|
execute_control_commands (struct command_line *cmdlines, int from_tty)
|
||||||
|
{
|
||||||
|
/* Set the instream to 0, indicating execution of a
|
||||||
|
user-defined function. */
|
||||||
|
scoped_restore restore_instream
|
||||||
|
= make_scoped_restore (¤t_ui->instream, nullptr);
|
||||||
|
scoped_restore save_async = make_scoped_restore (¤t_ui->async, 0);
|
||||||
|
scoped_restore save_nesting
|
||||||
|
= make_scoped_restore (&command_nest_depth, command_nest_depth + 1);
|
||||||
|
|
||||||
|
while (cmdlines)
|
||||||
|
{
|
||||||
|
enum command_control_type ret = execute_control_command (cmdlines,
|
||||||
|
from_tty);
|
||||||
|
if (ret != simple_control && ret != break_control)
|
||||||
|
{
|
||||||
|
warning (_("Error executing canned sequence of commands."));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cmdlines = cmdlines->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See cli-script.h. */
|
||||||
|
|
||||||
|
std::string
|
||||||
|
execute_control_commands_to_string (struct command_line *commands,
|
||||||
|
int from_tty)
|
||||||
|
{
|
||||||
|
/* GDB_STDOUT should be better already restored during these
|
||||||
|
restoration callbacks. */
|
||||||
|
set_batch_flag_and_restore_page_info save_page_info;
|
||||||
|
|
||||||
|
string_file str_file;
|
||||||
|
|
||||||
|
{
|
||||||
|
current_uiout->redirect (&str_file);
|
||||||
|
ui_out_redirect_pop redirect_popper (current_uiout);
|
||||||
|
|
||||||
|
scoped_restore save_stdout
|
||||||
|
= make_scoped_restore (&gdb_stdout, &str_file);
|
||||||
|
scoped_restore save_stderr
|
||||||
|
= make_scoped_restore (&gdb_stderr, &str_file);
|
||||||
|
scoped_restore save_stdlog
|
||||||
|
= make_scoped_restore (&gdb_stdlog, &str_file);
|
||||||
|
scoped_restore save_stdtarg
|
||||||
|
= make_scoped_restore (&gdb_stdtarg, &str_file);
|
||||||
|
scoped_restore save_stdtargerr
|
||||||
|
= make_scoped_restore (&gdb_stdtargerr, &str_file);
|
||||||
|
|
||||||
|
execute_control_commands (commands, from_tty);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move (str_file.string ());
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
execute_user_command (struct cmd_list_element *c, const char *args)
|
execute_user_command (struct cmd_list_element *c, const char *args)
|
||||||
{
|
{
|
||||||
struct ui *ui = current_ui;
|
|
||||||
counted_command_line cmdlines_copy;
|
counted_command_line cmdlines_copy;
|
||||||
enum command_control_type ret;
|
|
||||||
extern unsigned int max_user_call_depth;
|
extern unsigned int max_user_call_depth;
|
||||||
|
|
||||||
/* Ensure that the user commands can't be deleted while they are
|
/* Ensure that the user commands can't be deleted while they are
|
||||||
@ -395,25 +452,7 @@ execute_user_command (struct cmd_list_element *c, const char *args)
|
|||||||
if (user_args_stack.size () > max_user_call_depth)
|
if (user_args_stack.size () > max_user_call_depth)
|
||||||
error (_("Max user call depth exceeded -- command aborted."));
|
error (_("Max user call depth exceeded -- command aborted."));
|
||||||
|
|
||||||
/* Set the instream to 0, indicating execution of a
|
execute_control_commands (cmdlines, 0);
|
||||||
user-defined function. */
|
|
||||||
scoped_restore restore_instream
|
|
||||||
= make_scoped_restore (&ui->instream, nullptr);
|
|
||||||
|
|
||||||
scoped_restore save_async = make_scoped_restore (¤t_ui->async, 0);
|
|
||||||
|
|
||||||
scoped_restore save_nesting
|
|
||||||
= make_scoped_restore (&command_nest_depth, command_nest_depth + 1);
|
|
||||||
while (cmdlines)
|
|
||||||
{
|
|
||||||
ret = execute_control_command (cmdlines);
|
|
||||||
if (ret != simple_control && ret != break_control)
|
|
||||||
{
|
|
||||||
warning (_("Error executing canned sequence of commands."));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cmdlines = cmdlines->next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is called every time GDB prints a prompt. It ensures
|
/* This function is called every time GDB prints a prompt. It ensures
|
||||||
@ -465,7 +504,7 @@ print_command_trace (const char *fmt, ...)
|
|||||||
/* Helper for execute_control_command. */
|
/* Helper for execute_control_command. */
|
||||||
|
|
||||||
static enum command_control_type
|
static enum command_control_type
|
||||||
execute_control_command_1 (struct command_line *cmd)
|
execute_control_command_1 (struct command_line *cmd, int from_tty)
|
||||||
{
|
{
|
||||||
struct command_line *current;
|
struct command_line *current;
|
||||||
struct value *val;
|
struct value *val;
|
||||||
@ -483,7 +522,7 @@ execute_control_command_1 (struct command_line *cmd)
|
|||||||
{
|
{
|
||||||
/* A simple command, execute it and return. */
|
/* A simple command, execute it and return. */
|
||||||
std::string new_line = insert_user_defined_cmd_args (cmd->line);
|
std::string new_line = insert_user_defined_cmd_args (cmd->line);
|
||||||
execute_command (new_line.c_str (), 0);
|
execute_command (new_line.c_str (), from_tty);
|
||||||
ret = cmd->control_type;
|
ret = cmd->control_type;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -538,7 +577,7 @@ execute_control_command_1 (struct command_line *cmd)
|
|||||||
{
|
{
|
||||||
scoped_restore save_nesting
|
scoped_restore save_nesting
|
||||||
= make_scoped_restore (&command_nest_depth, command_nest_depth + 1);
|
= make_scoped_restore (&command_nest_depth, command_nest_depth + 1);
|
||||||
ret = execute_control_command_1 (current);
|
ret = execute_control_command_1 (current, from_tty);
|
||||||
|
|
||||||
/* If we got an error, or a "break" command, then stop
|
/* If we got an error, or a "break" command, then stop
|
||||||
looping. */
|
looping. */
|
||||||
@ -593,7 +632,7 @@ execute_control_command_1 (struct command_line *cmd)
|
|||||||
{
|
{
|
||||||
scoped_restore save_nesting
|
scoped_restore save_nesting
|
||||||
= make_scoped_restore (&command_nest_depth, command_nest_depth + 1);
|
= make_scoped_restore (&command_nest_depth, command_nest_depth + 1);
|
||||||
ret = execute_control_command_1 (current);
|
ret = execute_control_command_1 (current, from_tty);
|
||||||
|
|
||||||
/* If we got an error, get out. */
|
/* If we got an error, get out. */
|
||||||
if (ret != simple_control)
|
if (ret != simple_control)
|
||||||
@ -644,7 +683,7 @@ execute_control_command_1 (struct command_line *cmd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum command_control_type
|
enum command_control_type
|
||||||
execute_control_command (struct command_line *cmd)
|
execute_control_command (struct command_line *cmd, int from_tty)
|
||||||
{
|
{
|
||||||
/* Make sure we use the console uiout. It's possible that we are executing
|
/* Make sure we use the console uiout. It's possible that we are executing
|
||||||
breakpoint commands while running the MI interpreter. */
|
breakpoint commands while running the MI interpreter. */
|
||||||
@ -652,7 +691,7 @@ execute_control_command (struct command_line *cmd)
|
|||||||
scoped_restore save_uiout
|
scoped_restore save_uiout
|
||||||
= make_scoped_restore (¤t_uiout, interp_ui_out (console));
|
= make_scoped_restore (¤t_uiout, interp_ui_out (console));
|
||||||
|
|
||||||
return execute_control_command_1 (cmd);
|
return execute_control_command_1 (cmd, from_tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Like execute_control_command, but first set
|
/* Like execute_control_command, but first set
|
||||||
|
@ -122,10 +122,23 @@ extern void show_user_1 (struct cmd_list_element *c,
|
|||||||
const char *name,
|
const char *name,
|
||||||
struct ui_file *stream);
|
struct ui_file *stream);
|
||||||
|
|
||||||
|
/* Execute the commands in CMDLINES. */
|
||||||
|
|
||||||
|
extern void execute_control_commands (struct command_line *cmdlines,
|
||||||
|
int from_tty);
|
||||||
|
|
||||||
|
/* Run execute_control_commands for COMMANDS. Capture its output into
|
||||||
|
the returned string, do not display it to the screen. BATCH_FLAG
|
||||||
|
will be temporarily set to true. */
|
||||||
|
|
||||||
|
extern std::string execute_control_commands_to_string
|
||||||
|
(struct command_line *commands, int from_tty);
|
||||||
|
|
||||||
/* Exported to gdb/breakpoint.c */
|
/* Exported to gdb/breakpoint.c */
|
||||||
|
|
||||||
extern enum command_control_type
|
extern enum command_control_type
|
||||||
execute_control_command (struct command_line *cmd);
|
execute_control_command (struct command_line *cmd,
|
||||||
|
int from_tty = 0);
|
||||||
|
|
||||||
extern enum command_control_type
|
extern enum command_control_type
|
||||||
execute_control_command_untraced (struct command_line *cmd);
|
execute_control_command_untraced (struct command_line *cmd);
|
||||||
|
@ -135,8 +135,6 @@ extern struct cmd_list_element *save_cmdlist;
|
|||||||
extern void execute_command (const char *, int);
|
extern void execute_command (const char *, int);
|
||||||
extern std::string execute_command_to_string (const char *p, int from_tty);
|
extern std::string execute_command_to_string (const char *p, int from_tty);
|
||||||
|
|
||||||
enum command_control_type execute_control_command (struct command_line *);
|
|
||||||
|
|
||||||
extern void print_command_line (struct command_line *, unsigned int,
|
extern void print_command_line (struct command_line *, unsigned int,
|
||||||
struct ui_file *);
|
struct ui_file *);
|
||||||
extern void print_command_lines (struct ui_out *,
|
extern void print_command_lines (struct ui_out *,
|
||||||
|
@ -588,6 +588,20 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
|
|||||||
{
|
{
|
||||||
struct interp *interp;
|
struct interp *interp;
|
||||||
|
|
||||||
|
std::string arg_copy = arg;
|
||||||
|
bool first = true;
|
||||||
|
char *save_ptr = nullptr;
|
||||||
|
auto reader
|
||||||
|
= [&] ()
|
||||||
|
{
|
||||||
|
const char *result = strtok_r (first ? &arg_copy[0] : nullptr,
|
||||||
|
"\n", &save_ptr);
|
||||||
|
first = false;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
counted_command_line lines = read_command_lines_1 (reader, 1, nullptr);
|
||||||
|
|
||||||
scoped_restore save_async = make_scoped_restore (¤t_ui->async, 0);
|
scoped_restore save_async = make_scoped_restore (¤t_ui->async, 0);
|
||||||
|
|
||||||
scoped_restore save_uiout = make_scoped_restore (¤t_uiout);
|
scoped_restore save_uiout = make_scoped_restore (¤t_uiout);
|
||||||
@ -599,9 +613,10 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
|
|||||||
|
|
||||||
scoped_restore preventer = prevent_dont_repeat ();
|
scoped_restore preventer = prevent_dont_repeat ();
|
||||||
if (to_string)
|
if (to_string)
|
||||||
to_string_res = execute_command_to_string (arg, from_tty);
|
to_string_res = execute_control_commands_to_string (lines.get (),
|
||||||
|
from_tty);
|
||||||
else
|
else
|
||||||
execute_command (arg, from_tty);
|
execute_control_commands (lines.get (), from_tty);
|
||||||
}
|
}
|
||||||
CATCH (except, RETURN_MASK_ALL)
|
CATCH (except, RETURN_MASK_ALL)
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2018-05-04 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
|
PR python/22730:
|
||||||
|
* gdb.python/python.exp: Test multi-line execute.
|
||||||
|
|
||||||
2018-05-04 Tom Tromey <tom@tromey.com>
|
2018-05-04 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
PR python/22731:
|
PR python/22731:
|
||||||
|
@ -119,6 +119,9 @@ gdb_test_no_output \
|
|||||||
"python x = gdb.execute('printf \"%d\", 23', to_string = True)"
|
"python x = gdb.execute('printf \"%d\", 23', to_string = True)"
|
||||||
gdb_test "python print (x)" "23"
|
gdb_test "python print (x)" "23"
|
||||||
|
|
||||||
|
gdb_test "python gdb.execute('echo 2\\necho 3\\\\n\\n')" "23" \
|
||||||
|
"multi-line execute"
|
||||||
|
|
||||||
# Test post_event.
|
# Test post_event.
|
||||||
gdb_py_test_multiple "post event insertion" \
|
gdb_py_test_multiple "post event insertion" \
|
||||||
"python" "" \
|
"python" "" \
|
||||||
|
Loading…
Reference in New Issue
Block a user