diff options
author | Vladimir Prus <vladimir@codesourcery.com> | 2010-03-23 21:32:28 +0000 |
---|---|---|
committer | Vladimir Prus <vladimir@codesourcery.com> | 2010-03-23 21:32:28 +0000 |
commit | a7bdde9e633ffde58462e01bdfb0d1ee9a642d7c (patch) | |
tree | 21df3445afaf8f0d2a61166c724029025fbf834c /gdb/breakpoint.c | |
parent | 64e3cf3d4f121e456a09c3998c4aa6d739e61f8a (diff) | |
download | gdb-a7bdde9e633ffde58462e01bdfb0d1ee9a642d7c.zip gdb-a7bdde9e633ffde58462e01bdfb0d1ee9a642d7c.tar.gz gdb-a7bdde9e633ffde58462e01bdfb0d1ee9a642d7c.tar.bz2 |
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.
Diffstat (limited to 'gdb/breakpoint.c')
-rw-r--r-- | gdb/breakpoint.c | 172 |
1 files changed, 120 insertions, 52 deletions
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index b9b3e85..41fe09a 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -692,17 +692,109 @@ condition_command (char *arg, int from_tty) error (_("No breakpoint number %d."), bnum); } -/* Set the command list of B to COMMANDS. */ +/* Check that COMMAND do not contain commands that are suitable + only for tracepoints and not suitable for ordinary breakpoints. + Throw if any such commands is found. +*/ +static void +check_no_tracepoint_commands (struct command_line *commands) +{ + struct command_line *c; + for (c = commands; c; c = c->next) + { + int i; + + if (c->control_type == while_stepping_control) + error (_("The 'while-stepping' command can only be used for tracepoints")); + + for (i = 0; i < c->body_count; ++i) + check_no_tracepoint_commands ((c->body_list)[i]); + + /* Not that command parsing removes leading whitespace and comment + lines and also empty lines. So, we only need to check for + command directly. */ + if (strstr (c->line, "collect ") == c->line) + error (_("The 'collect' command can only be used for tracepoints")); + + if (strstr (c->line, "eval ") == c->line) + error (_("The 'eval' command can only be used for tracepoints")); + } +} + +int +breakpoint_is_tracepoint (const struct breakpoint *b) +{ + switch (b->type) + { + case bp_tracepoint: + case bp_fast_tracepoint: + return 1; + default: + return 0; + + } +} + +/* Set the command list of B to COMMANDS. If breakpoint is tracepoint, + validate that only allowed commands are included. +*/ void breakpoint_set_commands (struct breakpoint *b, struct command_line *commands) { + if (breakpoint_is_tracepoint (b)) + { + /* We need to verify that each top-level element of commands + is valid for tracepoints, that there's at most one while-stepping + element, and that while-stepping's body has valid tracing commands + excluding nested while-stepping. */ + struct command_line *c; + struct command_line *while_stepping = 0; + for (c = commands; c; c = c->next) + { + char *l = c->line; + if (c->control_type == while_stepping_control) + { + if (b->type == bp_fast_tracepoint) + error (_("The 'while-stepping' command cannot be used for fast tracepoint")); + + if (while_stepping) + error (_("The 'while-stepping' command can be used only once")); + else + while_stepping = c; + } + } + if (while_stepping) + { + struct command_line *c2; + + gdb_assert (while_stepping->body_count == 1); + c2 = while_stepping->body_list[0]; + for (; c2; c2 = c2->next) + { + char *l = c2->line; + if (c2->control_type == while_stepping_control) + error (_("The 'while-stepping' command cannot be nested")); + } + } + } + else + { + check_no_tracepoint_commands (commands); + } + free_command_lines (&b->commands); b->commands = commands; breakpoints_changed (); observer_notify_breakpoint_modified (b->number); } +void check_tracepoint_command (char *line, void *closure) +{ + struct breakpoint *b = closure; + validate_actionline (&line, b); +} + static void commands_command (char *arg, int from_tty) { @@ -730,7 +822,12 @@ commands_command (char *arg, int from_tty) char *tmpbuf = xstrprintf ("Type commands for when breakpoint %d is hit, one per line.", bnum); struct cleanup *cleanups = make_cleanup (xfree, tmpbuf); - l = read_command_lines (tmpbuf, from_tty, 1); + + if (breakpoint_is_tracepoint (b)) + l = read_command_lines (tmpbuf, from_tty, 1, + check_tracepoint_command, b); + else + l = read_command_lines (tmpbuf, from_tty, 1, 0, 0); do_cleanups (cleanups); breakpoint_set_commands (b, l); return; @@ -4539,26 +4636,6 @@ print_one_breakpoint_location (struct breakpoint *b, ui_out_text (uiout, " \n"); } - if (!part_of_multiple && b->step_count) - { - annotate_field (11); - ui_out_text (uiout, "\tstep count "); - ui_out_field_int (uiout, "step", b->step_count); - ui_out_text (uiout, " \n"); - } - - if (!part_of_multiple && b->actions) - { - struct action_line *action; - annotate_field (12); - for (action = b->actions; action; action = action->next) - { - ui_out_text (uiout, " A\t"); - ui_out_text (uiout, action->action); - ui_out_text (uiout, "\n"); - } - } - if (ui_out_is_mi_like_p (uiout) && !part_of_multiple) { if (b->addr_string) @@ -10318,12 +10395,11 @@ tracepoint_save_command (char *args, int from_tty) { struct breakpoint *tp; int any_tp = 0; - struct action_line *line; - FILE *fp; - char *i1 = " ", *i2 = " "; - char *indent, *actionline, *pathname; + struct command_line *line; + char *pathname; char tmp[40]; struct cleanup *cleanup; + struct ui_file *fp; if (args == 0 || *args == 0) error (_("Argument required (file name in which to save tracepoints)")); @@ -10342,50 +10418,42 @@ tracepoint_save_command (char *args, int from_tty) pathname = tilde_expand (args); cleanup = make_cleanup (xfree, pathname); - fp = fopen (pathname, "w"); + fp = gdb_fopen (pathname, "w"); if (!fp) error (_("Unable to open file '%s' for saving tracepoints (%s)"), args, safe_strerror (errno)); - make_cleanup_fclose (fp); + make_cleanup_ui_file_delete (fp); ALL_TRACEPOINTS (tp) { if (tp->addr_string) - fprintf (fp, "trace %s\n", tp->addr_string); + fprintf_unfiltered (fp, "trace %s\n", tp->addr_string); else { sprintf_vma (tmp, tp->loc->address); - fprintf (fp, "trace *0x%s\n", tmp); + fprintf_unfiltered (fp, "trace *0x%s\n", tmp); } if (tp->pass_count) - fprintf (fp, " passcount %d\n", tp->pass_count); + fprintf_unfiltered (fp, " passcount %d\n", tp->pass_count); - if (tp->actions) + if (tp->commands) { - fprintf (fp, " actions\n"); - indent = i1; - for (line = tp->actions; line; line = line->next) + volatile struct gdb_exception ex; + + fprintf_unfiltered (fp, " actions\n"); + + ui_out_redirect (uiout, fp); + TRY_CATCH (ex, RETURN_MASK_ERROR) { - struct cmd_list_element *cmd; + print_command_lines (uiout, tp->commands, 2); + } + ui_out_redirect (uiout, NULL); - QUIT; /* allow user to bail out with ^C */ - actionline = line->action; - while (isspace ((int) *actionline)) - actionline++; + if (ex.reason < 0) + throw_exception (ex); - fprintf (fp, "%s%s\n", indent, actionline); - if (*actionline != '#') /* skip for comment lines */ - { - cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1); - if (cmd == 0) - error (_("Bad action list item: %s"), actionline); - if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand)) - indent = i2; - else if (cmd_cfunc_eq (cmd, end_actions_pseudocommand)) - indent = i1; - } - } + fprintf_unfiltered (fp, " end\n"); } } do_cleanups (cleanup); |