Add previous_saved_command_line to allow a command to repeat a previous command.

Currently, a previous command can be repeated when the user types an
empty line.  This is implemented in handle_line_of_input by
returning saved_command_line in case an empty line has been input.

If we want a command to repeat the previous command, we need to save
the previous saved_command_line, as when a command runs, the saved_command_line
already contains the current command line of the command being executed.

As suggested by Tom, the previous_saved_command_line is made static.
At the same time, saved_command_line is also made static.
The support functions/variables for the repeat command logic are now all
located inside top.c.

gdb/ChangeLog
2019-05-31  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* top.h (saved_command_line): Remove declaration.
	* top.c (previous_saved_command_line, previous_repeat_arguments):
	New variables.
	(saved_command_line): Make static, define together with other
	'repeat variables'.
	(dont_repeat): Clear repeat_arguments.
	(repeat_previous, get_saved_command_line, save_command_line):
	New functions.
	(gdb_init): Initialize saved_command_line
	and previous_saved_command_line.
	* main.c (captured_main_1): Remove saved_command_line initialization.
	* event-top.c (handle_line_of_input): Update to use
	the new 'repeat' related functions instead of direct access to
	saved_command_line.
	* command.h (repeat_previous, get_saved_command_line,
	save_command_line): New declarations.
	(dont_repeat): Add comment.
This commit is contained in:
Philippe Waroquiers 2019-04-20 14:02:29 +02:00
parent a0486bac41
commit 68bb5386b8
6 changed files with 125 additions and 24 deletions

View file

@ -1,3 +1,23 @@
2019-05-31 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* top.h (saved_command_line): Remove declaration.
* top.c (previous_saved_command_line, previous_repeat_arguments):
New variables.
(saved_command_line): Make static, define together with other
'repeat variables'.
(dont_repeat): Clear repeat_arguments.
(repeat_previous, get_saved_command_line, save_command_line):
New functions.
(gdb_init): Initialize saved_command_line
and previous_saved_command_line.
* main.c (captured_main_1): Remove saved_command_line initialization.
* event-top.c (handle_line_of_input): Update to use
the new 'repeat' related functions instead of direct access to
saved_command_line.
* command.h (repeat_previous, get_saved_command_line,
save_command_line): New declarations.
(dont_repeat): Add comment.
2019-05-30 Tom Tromey <tromey@adacore.com> 2019-05-30 Tom Tromey <tromey@adacore.com>
* gdbtypes.h (struct range_bounds) <flag_upper_bound_is_count>: * gdbtypes.h (struct range_bounds) <flag_upper_bound_is_count>:

View file

@ -448,7 +448,29 @@ extern void cmd_show_list (struct cmd_list_element *, int, const char *);
extern void error_no_arg (const char *) ATTRIBUTE_NORETURN; extern void error_no_arg (const char *) ATTRIBUTE_NORETURN;
extern void dont_repeat (void);
/* Command line saving and repetition.
Each input line executed is saved to possibly be repeated either
when the user types an empty line, or be repeated by a command
that wants to repeat the previously executed command. The below
functions control command repetition. */
/* Commands call dont_repeat if they do not want to be repeated by null
lines or by repeat_previous (). */
extern void dont_repeat ();
/* Commands call repeat_previous if they want to repeat the previous command.
Such commands that repeat the previous command must indicate
to not repeat themselves, to avoid recursive repeat.
repeat_previous will mark the current command as not repeating,
and will ensure get_saved_command_line returns the previous command,
so that the currently executing command can repeat it. */
extern void repeat_previous ();
/* Prevent dont_repeat from working, and return a cleanup that
restores the previous state. */
extern scoped_restore_tmpl<int> prevent_dont_repeat (void); extern scoped_restore_tmpl<int> prevent_dont_repeat (void);
@ -457,6 +479,18 @@ extern scoped_restore_tmpl<int> prevent_dont_repeat (void);
extern void set_repeat_arguments (const char *args); extern void set_repeat_arguments (const char *args);
/* Returns the saved command line to repeat.
When a command is being executed, this is the currently executing
command line, unless the currently executing command has called
repeat_previous (): in this case, get_saved_command_line returns
the previously saved command line. */
extern char *get_saved_command_line ();
/* Takes a copy of CMD, for possible repetition. */
extern void save_command_line (const char *cmd);
/* Used to mark commands that don't do anything. If we just leave the /* Used to mark commands that don't do anything. If we just leave the
function field NULL, the command is interpreted as a help topic, or function field NULL, the command is interpreted as a help topic, or
as a class of commands. */ as a class of commands. */

View file

@ -634,11 +634,10 @@ command_line_append_input_line (struct buffer *cmd_line_buffer, const char *rl)
If REPEAT, handle command repetitions: If REPEAT, handle command repetitions:
- If the input command line is NOT empty, the command returned is - If the input command line is NOT empty, the command returned is
copied into the global 'saved_command_line' var so that it can saved using save_command_line () so that it can be repeated later.
be repeated later.
- OTOH, if the input command line IS empty, return the previously - OTOH, if the input command line IS empty, return the saved
saved command instead of the empty input line. command instead of the empty input line.
*/ */
char * char *
@ -673,7 +672,7 @@ handle_line_of_input (struct buffer *cmd_line_buffer,
server_command = startswith (cmd, SERVER_COMMAND_PREFIX); server_command = startswith (cmd, SERVER_COMMAND_PREFIX);
if (server_command) if (server_command)
{ {
/* Note that we don't set `saved_command_line'. Between this /* Note that we don't call `save_command_line'. Between this
and the check in dont_repeat, this insures that repeating and the check in dont_repeat, this insures that repeating
will still do the right thing. */ will still do the right thing. */
return cmd + strlen (SERVER_COMMAND_PREFIX); return cmd + strlen (SERVER_COMMAND_PREFIX);
@ -713,7 +712,7 @@ handle_line_of_input (struct buffer *cmd_line_buffer,
for (p1 = cmd; *p1 == ' ' || *p1 == '\t'; p1++) for (p1 = cmd; *p1 == ' ' || *p1 == '\t'; p1++)
; ;
if (repeat && *p1 == '\0') if (repeat && *p1 == '\0')
return saved_command_line; return get_saved_command_line ();
/* Add command to history if appropriate. Note: lines consisting /* Add command to history if appropriate. Note: lines consisting
solely of comments are also added to the command history. This solely of comments are also added to the command history. This
@ -728,9 +727,8 @@ handle_line_of_input (struct buffer *cmd_line_buffer,
/* Save into global buffer if appropriate. */ /* Save into global buffer if appropriate. */
if (repeat) if (repeat)
{ {
xfree (saved_command_line); save_command_line (cmd);
saved_command_line = xstrdup (cmd); return get_saved_command_line ();
return saved_command_line;
} }
else else
return cmd; return cmd;

View file

@ -499,8 +499,6 @@ captured_main_1 (struct captured_main_args *context)
notice_open_fds (); notice_open_fds ();
saved_command_line = (char *) xstrdup ("");
#ifdef __MINGW32__ #ifdef __MINGW32__
/* Ensure stderr is unbuffered. A Cygwin pty or pipe is implemented /* Ensure stderr is unbuffered. A Cygwin pty or pipe is implemented
as a Windows pipe, and Windows buffers on pipes. */ as a Windows pipe, and Windows buffers on pipes. */

View file

@ -134,8 +134,26 @@ show_confirm (struct ui_file *file, int from_tty,
char *current_directory; char *current_directory;
/* The last command line executed on the console. Used for command /* The last command line executed on the console. Used for command
repetitions. */ repetitions when the user enters an empty line. */
char *saved_command_line;
static char *saved_command_line;
/* If not NULL, the arguments that should be passed if
saved_command_line is repeated. */
static const char *repeat_arguments;
/* The previous last command line executed on the console. Used for command
repetitions when a command wants to relaunch the previously launched
command. We need this as when a command is running, saved_command_line
already contains the line of the currently executing command. */
char *previous_saved_command_line;
/* If not NULL, the arguments that should be passed if the
previous_saved_command_line is repeated. */
static const char *previous_repeat_arguments;
/* Nonzero if the current command is modified by "server ". This /* Nonzero if the current command is modified by "server ". This
affects things like recording into the command history, commands affects things like recording into the command history, commands
@ -521,11 +539,6 @@ maybe_wait_sync_command_done (int was_sync)
wait_sync_command_done (); wait_sync_command_done ();
} }
/* If not NULL, the arguments that should be passed if the current
command is repeated. */
static const char *repeat_arguments;
/* See command.h. */ /* See command.h. */
void void
@ -695,7 +708,7 @@ execute_command_to_string (const char *p, int from_tty,
static int suppress_dont_repeat = 0; static int suppress_dont_repeat = 0;
/* Commands call this if they do not want to be repeated by null lines. */ /* See command.h */
void void
dont_repeat (void) dont_repeat (void)
@ -709,11 +722,27 @@ dont_repeat (void)
thing read from stdin in line and don't want to delete it. Null thing read from stdin in line and don't want to delete it. Null
lines won't repeat here in any case. */ lines won't repeat here in any case. */
if (ui->instream == ui->stdin_stream) if (ui->instream == ui->stdin_stream)
*saved_command_line = 0; {
*saved_command_line = 0;
repeat_arguments = NULL;
}
} }
/* Prevent dont_repeat from working, and return a cleanup that /* See command.h */
restores the previous state. */
void
repeat_previous ()
{
/* Do not repeat this command, as this command is a repeating command. */
dont_repeat ();
/* We cannot free saved_command_line, as this line is being executed,
so swap it with previous_saved_command_line. */
std::swap (previous_saved_command_line, saved_command_line);
std::swap (previous_repeat_arguments, repeat_arguments);
}
/* See command.h. */
scoped_restore_tmpl<int> scoped_restore_tmpl<int>
prevent_dont_repeat (void) prevent_dont_repeat (void)
@ -721,6 +750,26 @@ prevent_dont_repeat (void)
return make_scoped_restore (&suppress_dont_repeat, 1); return make_scoped_restore (&suppress_dont_repeat, 1);
} }
/* See command.h. */
char *
get_saved_command_line ()
{
return saved_command_line;
}
/* See command.h. */
void
save_command_line (const char *cmd)
{
xfree (previous_saved_command_line);
previous_saved_command_line = saved_command_line;
previous_repeat_arguments = repeat_arguments;
saved_command_line = xstrdup (cmd);
repeat_arguments = NULL;
}
/* Read a line from the stream "instream" without command line editing. /* Read a line from the stream "instream" without command line editing.
@ -2179,6 +2228,9 @@ The second argument is the terminal the UI runs on.\n"), &cmdlist);
void void
gdb_init (char *argv0) gdb_init (char *argv0)
{ {
saved_command_line = xstrdup ("");
previous_saved_command_line = xstrdup ("");
if (pre_init_ui_hook) if (pre_init_ui_hook)
pre_init_ui_hook (); pre_init_ui_hook ();

View file

@ -217,7 +217,6 @@ extern void ui_register_input_event_handler (struct ui *ui);
extern void ui_unregister_input_event_handler (struct ui *ui); extern void ui_unregister_input_event_handler (struct ui *ui);
/* From top.c. */ /* From top.c. */
extern char *saved_command_line;
extern int confirm; extern int confirm;
extern int inhibit_gdbinit; extern int inhibit_gdbinit;
extern const char gdbinit[]; extern const char gdbinit[];