--- a/breakpoint.c +++ b/breakpoint.c @@ -301,7 +301,7 @@ struct breakpoint_ops bkpt_breakpoint_op static struct breakpoint_ops bkpt_probe_breakpoint_ops; /* Dynamic printf class type. */ -static struct breakpoint_ops dprintf_breakpoint_ops; +struct breakpoint_ops dprintf_breakpoint_ops; /* The style in which to perform a dynamic printf. This is a user option because different output options have different tradeoffs; --- a/breakpoint.h +++ b/breakpoint.h @@ -1212,6 +1212,7 @@ extern void tbreak_command (char *, int) extern struct breakpoint_ops base_breakpoint_ops; extern struct breakpoint_ops bkpt_breakpoint_ops; extern struct breakpoint_ops tracepoint_breakpoint_ops; +extern struct breakpoint_ops dprintf_breakpoint_ops; extern void initialize_breakpoint_ops (void); --- a/mi/mi-cmd-break.c +++ b/mi/mi-cmd-break.c @@ -30,6 +30,7 @@ #include "observer.h" #include "mi-main.h" #include "mi-cmd-break.h" +#include enum { @@ -84,11 +85,87 @@ setup_breakpoint_reporting (void) } -/* Implements the -break-insert command. - See the MI manual for the list of possible options. */ +static char * +mi_argv_to_format (int format_num, char **argv, int argc) +{ + char *format; + int format_size, i, format_current_size = 0; -void -mi_cmd_break_insert (char *command, char **argv, int argc) + if (format_num >= argc) + error (_("-dprintf-insert: Missing ")); + + /* If all the string need convert to \ddd mode, so * 2. + + 2 for two ". + + 1 for \0. */ + format_size = strlen (argv[format_num]) * 4 + 3; + format = xmalloc (format_size); + + /* Convert ARGV[OIND + 1] to format string and save to FORMAT. */ + *(format + format_current_size) = '\"'; + ++format_current_size; + for (i = 0; i < strlen (argv[format_num]); i++) + { + switch (argv[format_num][i]) + { + case '\\': + strcpy (format + format_current_size, "\\\\"); + break; + case '\a': + strcpy (format + format_current_size, "\\a"); + break; + case '\b': + strcpy (format + format_current_size, "\\b"); + break; + case '\f': + strcpy (format + format_current_size, "\\f"); + break; + case '\n': + strcpy (format + format_current_size, "\\n"); + break; + case '\r': + strcpy (format + format_current_size, "\\r"); + break; + case '\t': + strcpy (format + format_current_size, "\\t"); + break; + case '\v': + strcpy (format + format_current_size, "\\v"); + break; + default: + if (isprint(argv[format_num][i])) + { + *(format + format_current_size) = argv[format_num][i]; + *(format + format_current_size + 1) = '\0'; + } + else + sprintf (format + format_current_size, "\\%o", + argv[format_num][i]); + break; + } + format_current_size += strlen (format + format_current_size); + } + *(format + format_current_size) = '\"'; + ++format_current_size; + *(format + format_current_size) = '\0'; + + /* Apply other argv to FORMAT. */ + for (i = format_num + 1; i < argc; i++) + { + if (2 + strlen (argv[i]) > format_size - format_current_size) + { + format_size = format_current_size + strlen (argv[i]) + 2; + format = xrealloc (format, format_size); + } + *(format + format_current_size) = ','; + strcpy (format + format_current_size + 1, argv[i]); + format_current_size += strlen (format + format_current_size); + } + + return format; +} + +static void +mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc) { char *address = NULL; int hardware = 0; @@ -102,6 +179,7 @@ mi_cmd_break_insert (char *command, char struct cleanup *back_to; enum bptype type_wanted; struct breakpoint_ops *ops; + char *extra_string = NULL; enum opt { @@ -163,35 +241,75 @@ mi_cmd_break_insert (char *command, char } if (oind >= argc) - error (_("-break-insert: Missing ")); - if (oind < argc - 1) - error (_("-break-insert: Garbage following ")); + error (_("-%s-insert: Missing "), + dprintf ? "dprintf" : "break"); address = argv[oind]; + if (dprintf) + { + if (hardware) + error (_("-dprintf-insert: does not support -h")); + + extra_string = mi_argv_to_format (oind + 1, argv, argc); + make_cleanup (xfree, extra_string); + } + else + { + if (oind < argc - 1) + error (_("-break-insert: Garbage following ")); + } /* Now we have what we need, let's insert the breakpoint! */ back_to = setup_breakpoint_reporting (); - /* Note that to request a fast tracepoint, the client uses the - "hardware" flag, although there's nothing of hardware related to - fast tracepoints -- one can implement slow tracepoints with - hardware breakpoints, but fast tracepoints are always software. - "fast" is a misnomer, actually, "jump" would be more appropriate. - A simulator or an emulator could conceivably implement fast - regular non-jump based tracepoints. */ - type_wanted = (tracepoint - ? (hardware ? bp_fast_tracepoint : bp_tracepoint) - : (hardware ? bp_hardware_breakpoint : bp_breakpoint)); - ops = tracepoint ? &tracepoint_breakpoint_ops : &bkpt_breakpoint_ops; + if (tracepoint) + { + /* Note that to request a fast tracepoint, the client uses the + "hardware" flag, although there's nothing of hardware related to + fast tracepoints -- one can implement slow tracepoints with + hardware breakpoints, but fast tracepoints are always software. + "fast" is a misnomer, actually, "jump" would be more appropriate. + A simulator or an emulator could conceivably implement fast + regular non-jump based tracepoints. */ + type_wanted = hardware ? bp_fast_tracepoint : bp_tracepoint; + ops = &tracepoint_breakpoint_ops; + } + else if (dprintf) + { + type_wanted = bp_dprintf; + ops = &dprintf_breakpoint_ops; + } + else + { + type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint; + ops = &bkpt_breakpoint_ops; + } create_breakpoint (get_current_arch (), address, condition, thread, - NULL, + extra_string, 0 /* condition and thread are valid. */, temp_p, type_wanted, ignore_count, pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE, ops, 0, enabled, 0, 0); do_cleanups (back_to); +} + +/* Implements the -break-insert command. + See the MI manual for the list of possible options. */ +void +mi_cmd_break_insert (char *command, char **argv, int argc) +{ + mi_cmd_break_insert_1 (0, command, argv, argc); +} + +/* Implements the -dprintf-insert command. + See the MI manual for the list of possible options. */ + +void +mi_cmd_dprintf_insert (char *command, char **argv, int argc) +{ + mi_cmd_break_insert_1 (1, command, argv, argc); } enum wp_type --- a/mi/mi-cmds.c +++ b/mi/mi-cmds.c @@ -61,6 +61,8 @@ static struct mi_cmd mi_cmds[] = DEF_MI_CMD_CLI ("break-info", "info break", 1), DEF_MI_CMD_MI_1 ("break-insert", mi_cmd_break_insert, &mi_suppress_notification.breakpoint), + DEF_MI_CMD_MI_1 ("dprintf-insert", mi_cmd_dprintf_insert, + &mi_suppress_notification.breakpoint), DEF_MI_CMD_CLI ("break-list", "info break", 0), DEF_MI_CMD_MI_1 ("break-passcount", mi_cmd_break_passcount, &mi_suppress_notification.breakpoint), --- a/mi/mi-cmds.h +++ b/mi/mi-cmds.h @@ -39,6 +39,7 @@ typedef void (mi_cmd_argv_ftype) (char * extern mi_cmd_argv_ftype mi_cmd_ada_task_info; extern mi_cmd_argv_ftype mi_cmd_add_inferior; extern mi_cmd_argv_ftype mi_cmd_break_insert; +extern mi_cmd_argv_ftype mi_cmd_dprintf_insert; extern mi_cmd_argv_ftype mi_cmd_break_commands; extern mi_cmd_argv_ftype mi_cmd_break_passcount; extern mi_cmd_argv_ftype mi_cmd_break_watch;