From a7bdde9e633ffde58462e01bdfb0d1ee9a642d7c Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Tue, 23 Mar 2010 21:32:28 +0000 Subject: 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. --- gdb/tracepoint.c | 313 ++++++++++++++++--------------------------------------- 1 file changed, 90 insertions(+), 223 deletions(-) (limited to 'gdb/tracepoint.c') diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 8af3a9b..dc52ead 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -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,139 +487,24 @@ 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); - - 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); - } + char *tmpbuf = + xstrprintf ("Enter actions for tracepoint %d, one per line.", + t->number); + struct cleanup *cleanups = make_cleanup (xfree, tmpbuf); - 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,37 +661,8 @@ validate_actionline (char **line, struct breakpoint *t) return END; else { - warning (_("'%s' is not a supported tracepoint action."), *line); - return BADLINE; - } -} - -/* 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); + error (_("'%s' is not a supported tracepoint action."), *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 { @@ -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; + /* 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 if (cmd_cfunc_eq (cmd, end_actions_pseudocommand)) + 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) { - if (collect == &stepping_list) /* end stepping actions */ - collect = &tracepoint_list; - else - break; /* end tracepoint actions */ + 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; } - } /* for */ + } + 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++; -- cgit v1.1