aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2018-04-18 20:10:43 -0600
committerTom Tromey <tom@tromey.com>2018-05-04 15:58:09 -0600
commit56bcdbea2bed27ea83bf0e4fe472ab744b4beaa1 (patch)
tree8d7b32e4411b6a6f73e51fde7b20f0489d685dc2 /gdb
parenta913fffbdee21fdd50e8de0596358be425775678 (diff)
downloadfsf-binutils-gdb-56bcdbea2bed27ea83bf0e4fe472ab744b4beaa1.zip
fsf-binutils-gdb-56bcdbea2bed27ea83bf0e4fe472ab744b4beaa1.tar.gz
fsf-binutils-gdb-56bcdbea2bed27ea83bf0e4fe472ab744b4beaa1.tar.bz2
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.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog16
-rw-r--r--gdb/NEWS2
-rw-r--r--gdb/cli/cli-script.c93
-rw-r--r--gdb/cli/cli-script.h15
-rw-r--r--gdb/gdbcmd.h2
-rw-r--r--gdb/python/python.c19
-rw-r--r--gdb/testsuite/ChangeLog5
-rw-r--r--gdb/testsuite/gdb.python/python.exp3
8 files changed, 123 insertions, 32 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 0559c0b..f91a976 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,21 @@
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>
+
PR python/22731:
* NEWS: Mention that breakpoint commands are writable.
* python/py-breakpoint.c (bppy_set_commands): New function.
diff --git a/gdb/NEWS b/gdb/NEWS
index da7147b..cef5580 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -34,6 +34,8 @@ set|show record btrace cpu
** The commands attached to a breakpoint can be set by assigning to
the breakpoint's "commands" field.
+ ** gdb.execute can now execute multi-line gdb commands.
+
* New targets
RiscV ELF riscv*-*-elf
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index e336c58..a62e4fe 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -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 (&current_ui->instream, nullptr);
+ scoped_restore save_async = make_scoped_restore (&current_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
execute_user_command (struct cmd_list_element *c, const char *args)
{
- struct ui *ui = current_ui;
counted_command_line cmdlines_copy;
- enum command_control_type ret;
extern unsigned int max_user_call_depth;
/* 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)
error (_("Max user call depth exceeded -- command aborted."));
- /* Set the instream to 0, indicating execution of a
- user-defined function. */
- scoped_restore restore_instream
- = make_scoped_restore (&ui->instream, nullptr);
-
- scoped_restore save_async = make_scoped_restore (&current_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;
- }
+ execute_control_commands (cmdlines, 0);
}
/* 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. */
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 value *val;
@@ -483,7 +522,7 @@ execute_control_command_1 (struct command_line *cmd)
{
/* A simple command, execute it and return. */
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;
break;
}
@@ -538,7 +577,7 @@ execute_control_command_1 (struct command_line *cmd)
{
scoped_restore save_nesting
= 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
looping. */
@@ -593,7 +632,7 @@ execute_control_command_1 (struct command_line *cmd)
{
scoped_restore save_nesting
= 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 (ret != simple_control)
@@ -644,7 +683,7 @@ execute_control_command_1 (struct command_line *cmd)
}
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
breakpoint commands while running the MI interpreter. */
@@ -652,7 +691,7 @@ execute_control_command (struct command_line *cmd)
scoped_restore save_uiout
= make_scoped_restore (&current_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
diff --git a/gdb/cli/cli-script.h b/gdb/cli/cli-script.h
index 3bebd0e..736ebb3 100644
--- a/gdb/cli/cli-script.h
+++ b/gdb/cli/cli-script.h
@@ -122,10 +122,23 @@ extern void show_user_1 (struct cmd_list_element *c,
const char *name,
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 */
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
execute_control_command_untraced (struct command_line *cmd);
diff --git a/gdb/gdbcmd.h b/gdb/gdbcmd.h
index 342c8b2..b675ae8 100644
--- a/gdb/gdbcmd.h
+++ b/gdb/gdbcmd.h
@@ -135,8 +135,6 @@ extern struct cmd_list_element *save_cmdlist;
extern void execute_command (const char *, int);
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,
struct ui_file *);
extern void print_command_lines (struct ui_out *,
diff --git a/gdb/python/python.c b/gdb/python/python.c
index b486be7..db37331 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -588,6 +588,20 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
{
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 (&current_ui->async, 0);
scoped_restore save_uiout = make_scoped_restore (&current_uiout);
@@ -599,9 +613,10 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
scoped_restore preventer = prevent_dont_repeat ();
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
- execute_command (arg, from_tty);
+ execute_control_commands (lines.get (), from_tty);
}
CATCH (except, RETURN_MASK_ALL)
{
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 24d9d34..761fb73 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,10 @@
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>
+
PR python/22731:
* gdb.python/py-breakpoint.exp: Test setting breakpoint commands.
diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp
index cee195f..f6bf93a 100644
--- a/gdb/testsuite/gdb.python/python.exp
+++ b/gdb/testsuite/gdb.python/python.exp
@@ -119,6 +119,9 @@ gdb_test_no_output \
"python x = gdb.execute('printf \"%d\", 23', to_string = True)"
gdb_test "python print (x)" "23"
+gdb_test "python gdb.execute('echo 2\\necho 3\\\\n\\n')" "23" \
+ "multi-line execute"
+
# Test post_event.
gdb_py_test_multiple "post event insertion" \
"python" "" \