Unify actions and commands

* defs.h (read_command_lines, read_command_lines_1): New
	parameters validator and closure.
	* tracepoint.h (struct action_line): Remove.
	* breakpoint.h (struct breakpoint): Remove the 'actions'
	field.
	* defs.h (enum command_control_type): New value
	while_stepping_control.
	(struct command_line): Add comments.
	* breakpoint.c (breakoint_is_tracepoint): New.
	(breakpoint_set_commands): For tracepoints,
	verify the commands are permissible.
	(check_tracepoint_commands): New.
	(commands_command): Require that each new line is validated using
	check_tracepoint_command, if we set commands for a tracepoint.
	(create_tracepoint_from_upload): Likewise.
	(print_one_breakpoint_location): Remove the code to print
	actions specifically.
	(tracepoint_save_command): Relay to print_command_lines.
	* cli/cli-script.c (process_next_line): New parameters validator
	and closure. Handle 'while-stepping'. Call validator if not null.
	(read_command_lines, read_command_lines1): Likewise.
	(recurse_read_control_structure): New parameters validator and
	closure. Handle while_stepping_control.
	(print_command_lines): Handle while-stepping.
	(get_command_line, define_command, document_command): Adjust.
	* remote.c (remote_download_tracepoint): Adjust.
	* tracepoint.c (make_cleanup_free_actions, read_actions)
	(free_actions, do_free_actions_cleanup): Remove.
	(trace_actions_command): Use read_command_lines.
	(validate_actionline): Use error in one place.
	(encode_actions_1): New, extracted from...
	(encode_actions): ...this. Also use cleanups for exception
	safety.
	(trace_dump_command): Adjust.
	* mi/mi-cmd-break (mi_cmd_break_commands): Validate commands if
	it's tracepoint.
This commit is contained in:
Vladimir Prus
2010-03-23 21:32:28 +00:00
parent 64e3cf3d4f
commit a7bdde9e63
14 changed files with 377 additions and 344 deletions

View File

@ -178,7 +178,6 @@ static void add_aexpr (struct collection_list *, struct agent_expr *);
static char *mem2hex (gdb_byte *, char *, int);
static void add_register (struct collection_list *collection,
unsigned int regno);
static struct cleanup *make_cleanup_free_actions (struct breakpoint *t);
extern void send_disconnected_tracing_value (int value);
@ -450,9 +449,6 @@ tvariables_info (char *args, int from_tty)
/* ACTIONS functions: */
/* Prototypes for action-parsing utility commands */
static void read_actions (struct breakpoint *);
/* The three functions:
collect_pseudocommand,
while_stepping_pseudocommand, and
@ -491,138 +487,23 @@ static void
trace_actions_command (char *args, int from_tty)
{
struct breakpoint *t;
char tmpbuf[128];
char *end_msg = "End with a line saying just \"end\".";
struct command_line *l;
t = get_tracepoint_by_number (&args, 0, 1);
if (t)
{
sprintf (tmpbuf, "Enter actions for tracepoint %d, one per line.",
t->number);
char *tmpbuf =
xstrprintf ("Enter actions for tracepoint %d, one per line.",
t->number);
struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
if (from_tty)
{
if (deprecated_readline_begin_hook)
(*deprecated_readline_begin_hook) ("%s %s\n", tmpbuf, end_msg);
else if (input_from_terminal_p ())
printf_filtered ("%s\n%s\n", tmpbuf, end_msg);
}
free_actions (t);
t->step_count = 0; /* read_actions may set this */
read_actions (t);
if (deprecated_readline_end_hook)
(*deprecated_readline_end_hook) ();
/* tracepoints_changed () */
l = read_command_lines (tmpbuf, from_tty, 1, check_tracepoint_command, t);
do_cleanups (cleanups);
breakpoint_set_commands (t, l);
}
/* else just return */
}
/* worker function */
static void
read_actions (struct breakpoint *t)
{
char *line;
char *prompt1 = "> ", *prompt2 = " > ";
char *prompt = prompt1;
enum actionline_type linetype;
extern FILE *instream;
struct action_line *next = NULL, *temp;
struct cleanup *old_chain;
/* Control-C quits instantly if typed while in this loop
since it should not wait until the user types a newline. */
immediate_quit++;
/* FIXME: kettenis/20010823: Something is wrong here. In this file
STOP_SIGNAL is never defined. So this code has been left out, at
least for quite a while now. Replacing STOP_SIGNAL with SIGTSTP
leads to compilation failures since the variable job_control
isn't declared. Leave this alone for now. */
#ifdef STOP_SIGNAL
if (job_control)
signal (STOP_SIGNAL, handle_stop_sig);
#endif
old_chain = make_cleanup_free_actions (t);
while (1)
{
/* Make sure that all output has been output. Some machines may
let you get away with leaving out some of the gdb_flush, but
not all. */
wrap_here ("");
gdb_flush (gdb_stdout);
gdb_flush (gdb_stderr);
if (deprecated_readline_hook && instream == NULL)
line = (*deprecated_readline_hook) (prompt);
else if (instream == stdin && ISATTY (instream))
{
line = gdb_readline_wrapper (prompt);
if (line && *line) /* add it to command history */
add_history (line);
}
else
line = gdb_readline (0);
if (!line)
{
line = xstrdup ("end");
printf_filtered ("end\n");
}
linetype = validate_actionline (&line, t);
if (linetype == BADLINE)
continue; /* already warned -- collect another line */
temp = xmalloc (sizeof (struct action_line));
temp->next = NULL;
temp->action = line;
if (next == NULL) /* first action for this tracepoint? */
t->actions = next = temp;
else
{
next->next = temp;
next = temp;
}
if (linetype == STEPPING) /* begin "while-stepping" */
{
if (prompt == prompt2)
{
warning (_("Already processing 'while-stepping'"));
continue;
}
else
prompt = prompt2; /* change prompt for stepping actions */
}
else if (linetype == END)
{
if (prompt == prompt2)
{
prompt = prompt1; /* end of single-stepping actions */
}
else
{ /* end of actions */
if (t->actions->next == NULL)
{
/* An "end" all by itself with no other actions
means this tracepoint has no actions.
Discard empty list. */
free_actions (t);
}
break;
}
}
}
#ifdef STOP_SIGNAL
if (job_control)
signal (STOP_SIGNAL, SIG_DFL);
#endif
immediate_quit--;
discard_cleanups (old_chain);
}
/* worker function */
enum actionline_type
validate_actionline (char **line, struct breakpoint *t)
@ -772,8 +653,7 @@ validate_actionline (char **line, struct breakpoint *t)
if (*p == '\0' ||
(t->step_count = strtol (p, &p, 0)) == 0)
{
warning (_("'%s': bad step-count; command ignored."), *line);
return BADLINE;
error (_("'%s': bad step-count."), *line);
}
return STEPPING;
}
@ -781,39 +661,10 @@ validate_actionline (char **line, struct breakpoint *t)
return END;
else
{
warning (_("'%s' is not a supported tracepoint action."), *line);
return BADLINE;
error (_("'%s' is not a supported tracepoint action."), *line);
}
}
/* worker function */
void
free_actions (struct breakpoint *t)
{
struct action_line *line, *next;
for (line = t->actions; line; line = next)
{
next = line->next;
if (line->action)
xfree (line->action);
xfree (line);
}
t->actions = NULL;
}
static void
do_free_actions_cleanup (void *t)
{
free_actions (t);
}
static struct cleanup *
make_cleanup_free_actions (struct breakpoint *t)
{
return make_cleanup (do_free_actions_cleanup, t);
}
enum {
memrange_absolute = -1
};
@ -1271,70 +1122,31 @@ stringify_collection_list (struct collection_list *list, char *string)
return *str_list;
}
/* Render all actions into gdb protocol. */
/*static*/ void
encode_actions (struct breakpoint *t, struct bp_location *tloc,
char ***tdp_actions, char ***stepping_actions)
static void
encode_actions_1 (struct command_line *action,
struct breakpoint *t,
struct bp_location *tloc,
int frame_reg,
LONGEST frame_offset,
struct collection_list *collect,
struct collection_list *stepping_list)
{
static char tdp_buff[2048], step_buff[2048];
char *action_exp;
struct expression *exp = NULL;
struct action_line *action;
struct command_line *actions;
int i;
struct value *tempval;
struct collection_list *collect;
struct cmd_list_element *cmd;
struct agent_expr *aexpr;
int frame_reg;
LONGEST frame_offset;
char *default_collect_line = NULL;
struct action_line *default_collect_action = NULL;
clear_collection_list (&tracepoint_list);
clear_collection_list (&stepping_list);
collect = &tracepoint_list;
*tdp_actions = NULL;
*stepping_actions = NULL;
gdbarch_virtual_frame_pointer (t->gdbarch,
tloc->address, &frame_reg, &frame_offset);
action = t->actions;
/* If there are default expressions to collect, make up a collect
action and prepend to the action list to encode. Note that since
validation is per-tracepoint (local var "xyz" might be valid for
one tracepoint and not another, etc), we make up the action on
the fly, and don't cache it. */
if (*default_collect)
{
char *line;
enum actionline_type linetype;
default_collect_line = xmalloc (12 + strlen (default_collect));
sprintf (default_collect_line, "collect %s", default_collect);
line = default_collect_line;
linetype = validate_actionline (&line, t);
if (linetype != BADLINE)
{
default_collect_action = xmalloc (sizeof (struct action_line));
default_collect_action->next = t->actions;
default_collect_action->action = line;
action = default_collect_action;
}
}
for (; action; action = action->next)
{
QUIT; /* allow user to bail out with ^C */
action_exp = action->action;
action_exp = action->line;
while (isspace ((int) *action_exp))
action_exp++;
if (*action_exp == '#') /* comment line */
return;
cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
if (cmd == 0)
error (_("Bad action list item: %s"), action_exp);
@ -1505,26 +1317,81 @@ encode_actions (struct breakpoint *t, struct bp_location *tloc,
} /* if */
else if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand))
{
collect = &stepping_list;
}
else if (cmd_cfunc_eq (cmd, end_actions_pseudocommand))
{
if (collect == &stepping_list) /* end stepping actions */
collect = &tracepoint_list;
else
break; /* end tracepoint actions */
/* We check against nested while-stepping when setting
breakpoint action, so no way to run into nested
here. */
gdb_assert (stepping_list);
encode_actions_1 (action->body_list[0], t, tloc, frame_reg, frame_offset,
stepping_list, NULL);
}
else
error (_("Invalid tracepoint command '%s'"), action->line);
} /* for */
}
/* Render all actions into gdb protocol. */
/*static*/ void
encode_actions (struct breakpoint *t, struct bp_location *tloc,
char ***tdp_actions, char ***stepping_actions)
{
static char tdp_buff[2048], step_buff[2048];
char *default_collect_line = NULL;
struct command_line *actions;
struct command_line *default_collect_action = NULL;
int frame_reg;
LONGEST frame_offset;
struct cleanup *back_to;
back_to = make_cleanup (null_cleanup, NULL);
clear_collection_list (&tracepoint_list);
clear_collection_list (&stepping_list);
*tdp_actions = NULL;
*stepping_actions = NULL;
gdbarch_virtual_frame_pointer (t->gdbarch,
t->loc->address, &frame_reg, &frame_offset);
actions = t->commands;
/* If there are default expressions to collect, make up a collect
action and prepend to the action list to encode. Note that since
validation is per-tracepoint (local var "xyz" might be valid for
one tracepoint and not another, etc), we make up the action on
the fly, and don't cache it. */
if (*default_collect)
{
char *line;
enum actionline_type linetype;
default_collect_line = xstrprintf ("collect %s", default_collect);
make_cleanup (xfree, default_collect_line);
line = default_collect_line;
linetype = validate_actionline (&line, t);
if (linetype != BADLINE)
{
default_collect_action = xmalloc (sizeof (struct command_line));
make_cleanup (xfree, default_collect_action);
default_collect_action->next = t->commands;
default_collect_action->line = line;
actions = default_collect_action;
}
}
encode_actions_1 (actions, t, tloc, frame_reg, frame_offset,
&tracepoint_list, &stepping_list);
memrange_sortmerge (&tracepoint_list);
memrange_sortmerge (&stepping_list);
*tdp_actions = stringify_collection_list (&tracepoint_list,
*tdp_actions = stringify_collection_list (&tracepoint_list,
tdp_buff);
*stepping_actions = stringify_collection_list (&stepping_list,
*stepping_actions = stringify_collection_list (&stepping_list,
step_buff);
xfree (default_collect_line);
xfree (default_collect_action);
do_cleanups (back_to);
}
static void
@ -2276,7 +2143,7 @@ trace_dump_command (char *args, int from_tty)
struct regcache *regcache;
struct gdbarch *gdbarch;
struct breakpoint *t;
struct action_line *action;
struct command_line *action;
char *action_exp, *next_comma;
struct cleanup *old_cleanups;
int stepping_actions = 0;
@ -2316,12 +2183,12 @@ trace_dump_command (char *args, int from_tty)
if (loc->address == regcache_read_pc (regcache))
stepping_frame = 0;
for (action = t->actions; action; action = action->next)
for (action = t->commands; action; action = action->next)
{
struct cmd_list_element *cmd;
QUIT; /* allow user to bail out with ^C */
action_exp = action->action;
action_exp = action->line;
while (isspace ((int) *action_exp))
action_exp++;