(SESSION_serialize_bps): New proc.
(SESSION_recreate_bps): New proc.
(session_load): Recreate breakpoints.
* library/util.tcl (bp_exists): Expect user specification in
breakpoint info.
* library/srctextwin.itb (SrcTextWin::showBPBalloon): Expect user
specification in breakpoint info.
* library/gdbevent.itb (BreakpointEvent::_init): Initialize
_user_specification.
(BreakpointEvent::get): Handle user_specification.
* library/gdbevent.ith (BreakpointEvent): Added
_user_specification field.
* library/bpwin.itb (BpWin::bp_store): Expect user specification
and use it when saving.
(BpWin::bp_type): Expect user specification.
* generic/gdbtk-bp.c (BREAKPOINT_IS_WATCHPOINT): New macro.
(gdb_get_breakpoint_info): Added `user specification' to result.
+2001-06-11 Tom Tromey <tromey@redhat.com>
+
+ * library/session.tcl (session_save): Save breakpoints.
+ (SESSION_serialize_bps): New proc.
+ (SESSION_recreate_bps): New proc.
+ (session_load): Recreate breakpoints.
+ * library/util.tcl (bp_exists): Expect user specification in
+ breakpoint info.
+ * library/srctextwin.itb (SrcTextWin::showBPBalloon): Expect user
+ specification in breakpoint info.
+ * library/gdbevent.itb (BreakpointEvent::_init): Initialize
+ _user_specification.
+ (BreakpointEvent::get): Handle user_specification.
+ * library/gdbevent.ith (BreakpointEvent): Added
+ _user_specification field.
+ * library/bpwin.itb (BpWin::bp_store): Expect user specification
+ and use it when saving.
+ (BpWin::bp_type): Expect user specification.
+ * generic/gdbtk-bp.c (BREAKPOINT_IS_WATCHPOINT): New macro.
+ (gdb_get_breakpoint_info): Added `user specification' to result.
+
2001-06-11 Keith Seitz <keiths@redhat.com>
* generic/gdbtk-stack.c (gdb_stack): Return TCL_ERROR if
|| (bp)->type == bp_read_watchpoint \
|| (bp)->type == bp_access_watchpoint)
+/* Is this breakpoint a watchpoint? */
+#define BREAKPOINT_IS_WATCHPOINT(bp) \
+((bp)->type == bp_watchpoint \
+ || (bp)->type == bp_hardware_watchpoint \
+ || (bp)->type == bp_read_watchpoint \
+ || (bp)->type == bp_access_watchpoint)
+
/*
* These are routines we need from breakpoint.c.
* at some point make these static in breakpoint.c and move GUI code there
* Tcl Result:
* A list with {file, function, line_number, address, type, enabled?,
* disposition, ignore_count, {list_of_commands},
- * condition, thread, hit_count}
+ * condition, thread, hit_count user_specification}
*/
static int
gdb_get_breakpoint_info (ClientData clientData, Tcl_Interp *interp, int objc,
Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
Tcl_NewIntObj (b->hit_count));
+ Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
+ Tcl_NewStringObj (BREAKPOINT_IS_WATCHPOINT (b)
+ ? b->exp_string
+ : b->addr_string, -1));
+
return TCL_OK;
}
foreach breakpoint [gdb_get_breakpoint_list] {
# This is an lassign
foreach {file function line_no address type \
- enable_p disp ignore cmds thread hit_count} \
+ enable_p disp ignore cmds thread hit_count user_spec} \
[gdb_get_breakpoint_info $breakpoint] {
break
}
- if {$file != ""} {
+ if {$user_spec != ""} {
+ set bp_specifier $user_spec
+ } elseif {$file != ""} {
set filename [file tail $file]
set bp_specifier $filename:$line_no
} else {
set bp_specifier *$address
}
+ # FIXME: doesn't handle watchpoints.
if {[string compare $disp "delete"] == 0} {
puts $outH "tbreak $bp_specifier"
} else {
#debug "bp_type $i $bpnum"
set bpinfo [gdb_get_breakpoint_info $bpnum]
lassign $bpinfo file func line pc type enabled disposition \
- ignore_count commands cond thread hit_count
+ ignore_count commands cond thread hit_count user_spec
bp_select $i
switch $disposition {
delete {
condition { return $_condition }
thread { return $_thread }
hit_count { return $_hit_count }
+ user_specification { return $_user_specification }
- default { error "unknown event data \"$what\": should be: action|number|file|function|line|address|type|enabled|disposition|ignore_count|commands|condition|thread|hit_count" }
+ default { error "unknown event data \"$what\": should be: action|number|file|function|line|address|type|enabled|disposition|ignore_count|commands|condition|thread|hit_count|user_specification" }
}
}
set _condition {}
set _thread {}
set _hit_count {}
+ set _user_specification {}
} else {
lassign $bpinfo \
_file \
_commands \
_condition \
_thread \
- _hit_count
+ _hit_count \
+ _user_specification
}
}
# condition .... BP condition
# thread ....... thread in which BP is set (or -1 for all threads)
# hit_count .... number of times BP has been hit
+# user_specification
+# .. text the user initially used to set this breakpoint
class BreakpointEvent {
inherit GDBEvent
private variable _condition {}
private variable _thread {}
private variable _hit_count {}
+ private variable _user_specification {}
private method _init {}
}
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
+# An internal function used when saving sessions. Returns a string
+# that can be used to recreate all pertinent breakpoint state.
+proc SESSION_serialize_bps {} {
+ set result {}
+
+ foreach bp_num [gdb_get_breakpoint_list] {
+ lassign [gdb_get_breakpoint_info $bp_num] file function line_number \
+ address type enabled disposition ignore_count command_list \
+ condition thread hit_count user_specification
+
+ switch -glob -- $type {
+ "breakpoint" -
+ "hw breakpoint" {
+ if {$disposition == "delete"} {
+ set cmd tbreak
+ } else {
+ set cmd break
+ }
+
+ append cmd " "
+ if {$user_specification != ""} {
+ append cmd "$user_specification"
+ } elseif {$file != ""} {
+ # BpWin::bp_store uses file tail here, but I think that is
+ # wrong.
+ append cmd "$file:$line_number"
+ } else {
+ append cmd "*$address"
+ }
+ }
+ "watchpoint" -
+ "hw watchpoint" {
+ set cmd watch
+ if {$user_specification != ""} {
+ append cmd " $user_specification"
+ } else {
+ # There's nothing sensible to do.
+ continue
+ }
+ }
+
+ "catch*" {
+ # FIXME: Don't know what to do.
+ continue
+ }
+
+ default {
+ # Can't serialize anything other than those listed above.
+ continue
+ }
+ }
+
+ lappend result [list $cmd $enabled $condition $command_list]
+ }
+
+ return $result
+}
+
+# An internal function used when loading sessions. It takes a
+# breakpoint string and recreates all the breakpoints.
+proc SESSION_recreate_bps {specs} {
+ foreach spec $specs {
+ lassign $spec create enabled condition commands
+
+ # Create the breakpoint
+ gdb_cmd $create
+
+ # Below we use `\$bpnum'. This means we don't have to figure out
+ # the number of the breakpoint when doing further manipulations.
+
+ if {! $enabled} {
+ gdb_cmd "disable \$bpnum"
+ }
+
+ if {$condition != ""} {
+ gdb_cmd "cond \$bpnum $condition"
+ }
+
+ if {[llength $commands]} {
+ lappend commands end
+ gdb_cmd "commands \$bpnum\n[join $commands \n]"
+ }
+ }
+}
+
#
# This procedure decides what makes up a gdb `session'. Roughly a
# session is whatever the user found useful when debugging a certain
set values(pwd) $gdb_current_directory
set values(target) $gdb_target_name
+ # Breakpoints.
+ set values(breakpoints) [SESSION_serialize_bps]
+
# Recompute list of recent sessions. Trim to no more than 5 sessions.
set recent [concat [list $name] \
[lremove [pref getd gdb/recent-projects] $name]]
set_exe
}
+ if {[info exists values(breakpoints)]} {
+ SESSION_recreate_bps $values(breakpoints)
+ }
+
if {[info exists values(target)]} {
debug "Restoring Target: $values(target)"
set gdb_target_name $values(target)
foreach b $bps {
set bpinfo [gdb_get_breakpoint_info $b]
lassign $bpinfo file func linenum addr type enabled disposition \
- ignore_count commands cond thread hit_count
+ ignore_count commands cond thread hit_count user_specification
if {$thread == "-1"} {set thread "all"}
set file [lindex [file split $file] end]
if {$enabled} {
foreach bpnum $bps {
set bpinfo [gdb_get_breakpoint_info $bpnum]
lassign $bpinfo file func line pc type enabled disposition \
- ignore_count commands cond thread hit_count
+ ignore_count commands cond thread hit_count user_specification
if {$filename == $file && $function == $func && $addr == $pc} {
return $bpnum
}