[m-rev.] for review: print lists on breakpoints

Zoltan Somogyi zs at cs.mu.OZ.AU
Thu Jan 27 16:07:43 AEDT 2005


Allow uses to associate with each breakpoint in mdb a list of print actions
that should be executed automatically when execution arrives at the breakpoint.

A new print list (a list of things to be printed) can be attached to an
existing breakpoint via the new "break_print" command, or it can be attached
to a breakpoint being created via the existing "break" command.

NEWS:
	Mention the new capability.

doc/user_guide.texi:
	Document the new capability.

trace/mercury_trace_spy.[ch]:
	Keep a print list with every breakpoint, and add functions to
	manipulate print lists.

	Convert this module to four space indentation to keep indent levels
	manageable.

trace/mercury_trace.c:
	Conform to the updated interface of the mercury_trace_spy module.

trace/mercury_trace_internal.[ch]:
	When the internal debugger is invoked at an event, whether
	interactively or not, take an extra parameter specifying the
	print list, if any, to be executed.

	Implement the new "break_print" command and the new options of
	the "break" command.

	Conform to the updated interface of the mercury_trace_spy module.

trace/mercury_trace_declarative.c:
	Conform to the updated interface of the mercury_trace_internal module.

tests/debugger/breakpoints.{inp,exp*}:
	Test the new capability.

tests/debugger/completion.exp:
tests/debugger/mdb_command_test.inp:
	Update to reflect the new command.

cvs diff: Diffing .
Index: NEWS
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/NEWS,v
retrieving revision 1.367
diff -u -b -r1.367 NEWS
--- NEWS	25 Jan 2005 06:19:51 -0000	1.367
+++ NEWS	27 Jan 2005 04:58:02 -0000
@@ -56,8 +56,10 @@
 Changes to the Mercury debugger:
 * Users can now limit the output from stack traces.
 * Users can now put breakpoints on unify and compare predicates.
+* Users can now arrange to have the goal and/or some variables printed
+  every time execution arrives at a breakpoint.
 * Users can now save runtime values to files.
-* Ability to tell the declarative debugger to trust entire modules or 
+* Users can now tell the declarative debugger to trust entire modules or 
   individual predicates or functions.
 
 Changes to the compiler back-ends:
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.412
diff -u -b -r1.412 user_guide.texi
--- doc/user_guide.texi	25 Jan 2005 07:10:56 -0000	1.412
+++ doc/user_guide.texi	25 Jan 2005 07:14:01 -0000
@@ -1922,6 +1922,19 @@
 @sp 1
 Neither of these will happen if the break point is disabled.
 @sp 1
+Every break point has a print list.
+Every time execution stops at an event that matches the breakpoint,
+mdb implicitly executes a print command for each element
+in the breakpoint's print list.
+A print list element can be the word @samp{goal},
+which causes the goal to the printed as if by @samp{print goal};
+it can be the word @samp{*},
+which causes all the variables to the printed as if by @samp{print *};
+or it can be the name or number of a variable,
+possibly followed (without white space) by term path,
+which causes the specified variable or part thereof to the printed
+as if the element were given as an argument to the @samp{print} command.
+ at sp 1
 @item strict commands
 @cindex strict debugger commands
 When a debugger command steps over some events
@@ -2887,7 +2900,7 @@
 
 @sp 1
 @table @code
- at item break [-PS] [-E at var{ignore-count}] [-I at var{ignore-count}] @var{filename}:@var{linenumber}
+ at item break [-PS] [-E at var{ignore-count}] [-I at var{ignore-count}] [-n] [-p at var{print-spec}]* @var{filename}:@var{linenumber}
 @kindex break (mdb command)
 Puts a break point on the specified line of the specified source file,
 if there is an event or a call at that position.
@@ -2908,9 +2921,20 @@
 until after @var{ignore-count} occurrences of interface events
 that match the breakpoint.
 @sp 1
-By default, the initial state of the break point is @samp{stop},
-and the ignore count is zero.
- at item break [-AOPSaei] [-E at var{ignore-count}] [-I at var{ignore-count}] @var{proc-spec}
+Each occurrence of the options
+ at samp{-p at var{printspec}} and @samp{--print-list @var{printspec}}
+tells the debugger to include the specified entity
+in the breakpoint's print list.
+ at sp 1
+Normally, if a variable with the given name or number doesn't exist
+when execution reaches the breakpoint, mdb will issue a warning.
+The option @samp{-n} or @samp{--no-warn}, if present, suppresses this warning.
+This can be useful if e.g. the name is the name of an output variable,
+which of course won't be present at call events.
+ at sp 1
+By default, the action of the break point is @samp{stop},
+the ignore count is zero, and the print list is empty.
+ at item break [-AOPSaei] [-E at var{ignore-count}] [-I at var{ignore-count}] [-n] [-p at var{print-spec}]* @var{proc-spec}
 @c <module name> <predicate name> [<arity> [<mode> [<predfunc>]]]
 Puts a break point on the specified procedure.
 @sp 1
@@ -2947,11 +2971,22 @@
 until after @var{ignore-count} occurrences of interface events
 that match the breakpoint.
 @sp 1
+Each occurrence of the options
+ at samp{-p at var{printspec}} and @samp{--print-list @var{printspec}}
+tells the debugger to include the specified entity
+in the breakpoint's print list.
+ at sp 1
+Normally, if a variable with the given name or number doesn't exist
+when execution reaches the breakpoint, mdb will issue a warning.
+The option @samp{-n} or @samp{--no-warn}, if present, suppresses this warning.
+This can be useful if e.g. the name is the name of an output variable,
+which of course won't be present at call events.
+ at sp 1
 By default, the action of the break point is @samp{stop},
 its invocation condition is @samp{interface},
-and the ignore count is zero.
+the ignore count is zero, and the print list is empty.
 @sp 1
- at item break [-PS] [-E at var{ignore-count}] [-I at var{ignore-count}] here
+ at item break [-PS] [-E at var{ignore-count}] [-I at var{ignore-count}] [-n] [-p at var{print-spec}]* here
 Puts a break point on the procedure referred to by the current event,
 with the invocation condition being the event at the current location
 in the procedure body.
@@ -2970,11 +3005,22 @@
 until after @var{ignore-count} occurrences of interface events
 that match the breakpoint.
 @sp 1
-By default, the initial state of the break point is @samp{stop},
-and the ignore count is zero.
+Each occurrence of the options
+ at samp{-p at var{printspec}} and @samp{--print-list @var{printspec}}
+tells the debugger to include the specified entity
+in the breakpoint's print list.
+ at sp 1
+Normally, if a variable with the given name or number doesn't exist
+when execution reaches the breakpoint, mdb will issue a warning.
+The option @samp{-n} or @samp{--no-warn}, if present, suppresses this warning.
+This can be useful if e.g. the name is the name of an output variable,
+which of course won't be present at call events.
+ at sp 1
+By default, the action of the break point is @samp{stop},
+the ignore count is zero, and the print list is empty.
 @sp 1
 @item break info
-Lists the details and status of all break points.
+Lists the details, status and print lists of all break points.
 @sp 1
 @item ignore [-E at var{ignore-count}] [-I at var{ignore-count}] @var{num}
 @sp 1
@@ -3009,6 +3055,27 @@
 the default is to ignore one call event
 that matches the most recently added breakpoint.
 Reports an error if the most recently added breakpoint has since been deleted.
+ at sp 1
+ at item break_print [-fpv] [-e] [-n] @var{num} @var{print-spec}*
+ at sp 1
+Adds the specified print list elements (there may be more than one)
+to the print list of the brakpoint numbered @var{num}.
+ at sp 1
+Normally, if a variable with the given name or number doesn't exist
+when execution reaches the breakpoint, mdb will issue a warning.
+The option @samp{-n} or @samp{--no-warn}, if present, suppresses this warning.
+This can be useful if e.g. the name is the name of an output variable,
+which of course won't be present at call events.
+ at sp 1
+Normally, the specified elements will be added
+at the start of the breakpoint's print list.
+The option @samp{-e} or @samp{--end}, if present,
+causes them to be added at the end.
+ at sp 1
+By default, the the specified elements will be printed with format "flat".
+The options @samp{-f} or @samp{--flat}, @samp{-p} or @samp{--pretty},
+and @samp{-v} or @samp{--verbose}, if given,
+explicitly specify the format to use.
 @sp 1
 @item disable @var{num}
 @kindex disable (mdb command)
cvs diff: Diffing extras
cvs diff: Diffing extras/aditi
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/stream
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
Index: tests/debugger/breakpoints.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/breakpoints.exp,v
retrieving revision 1.12
diff -u -b -r1.12 breakpoints.exp
--- tests/debugger/breakpoints.exp	17 Jan 2005 04:29:28 -0000	1.12
+++ tests/debugger/breakpoints.exp	25 Jan 2005 16:52:57 -0000
@@ -90,16 +90,51 @@
  3: - stop      entry pred breakpoints.qperm/2-0 (nondet)
 mdb> break nodiag
  0: + stop  interface pred breakpoints.nodiag/3-0 (semidet)
+mdb> break_print -v -n 1 HeadVar__1 HeadVar__2
+ 1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
+            HeadVar__1 (verbose, nowarn), HeadVar__2 (verbose, nowarn)
 mdb> continue
       E3:     C3 CALL pred breakpoints.qperm/2-0 (nondet) breakpoints.m:64 (breakpoints.m:61)
+       HeadVar__1             	
+[|]
+1-1
+2-[|]
+  1-2
+  2-[|]
+    1-3
+    2-[|]/2
+
+mdb> break_print 1 none
+ 1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
+mdb> set -p depth 10
+mdb> set -p size 20
+mdb> break_print -p -n 1 HeadVar__1 HeadVar__2
+ 1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
+            HeadVar__1 (pretty, nowarn), HeadVar__2 (pretty, nowarn)
 mdb> continue
       E4:     C3 SWTC pred breakpoints.qperm/2-0 (nondet) s2; breakpoints.m:65
 mdb> finish -N
       E5:     C4 CALL pred breakpoints.qperm/2-0 (nondet) breakpoints.m:64 (breakpoints.m:68)
+       HeadVar__1             	
+[2, 3, 4, 5]
 mdb> finish -n
       E6:     C4 EXIT pred breakpoints.qperm/2-0 (nondet) breakpoints.m:64 (breakpoints.m:68)
+       HeadVar__1             	
+[2, 3, 4, 5]
+       HeadVar__2             	
+[2, 3, 4, 5]
+mdb> break_print 1 none
+ 1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
+mdb> break_print -f -n 1 HeadVar__1
+ 1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
+            HeadVar__1 (flat, nowarn)
+mdb> break_print -f -e -n 1 HeadVar__2
+ 1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
+            HeadVar__1 (flat, nowarn), HeadVar__2 (flat, nowarn)
 mdb> continue
       E7:     C3 EXIT pred breakpoints.qperm/2-0 (nondet) breakpoints.m:64 (breakpoints.m:61)
+       HeadVar__1             	[1, 2, 3, 4, 5]
+       HeadVar__2             	[1, 2, 3, 4, 5]
 mdb> continue
       E8:     C5 CALL pred breakpoints.safe/1-0 (semidet) breakpoints.m:74 (breakpoints.m:62)
 mdb> finish
@@ -187,7 +222,36 @@
  0: + stop  interface func breakpoints.a.testmod.test_in_ab/0-0 (det)
 mdb> break -O b.testmod.test_in_ab
  1: + stop  interface func breakpoints.b.testmod.test_in_ab/0-0 (det)
+mdb> delete *
+ 0: E stop  interface func breakpoints.a.testmod.test_in_ab/0-0 (det)
+ 1: E stop  interface func breakpoints.b.testmod.test_in_ab/0-0 (det)
+mdb> break -O -p goal test_in_a
+ 0: + stop  interface func breakpoints.a.testmod.test_in_a/0-0 (det)
+            goal (flat)
+mdb> break -O -P -p HeadVar__1 test_in_b
+ 1: + print interface func breakpoints.b.testmod.test_in_b/0-0 (det)
+            HeadVar__1 (flat)
+mdb> break info
+ 0: + stop  interface func breakpoints.a.testmod.test_in_a/0-0 (det)
+            goal (flat)
+ 1: + print interface func breakpoints.b.testmod.test_in_b/0-0 (det)
+            HeadVar__1 (flat)
 mdb> continue
 [1, 3, 5, 2, 4]
+     E14:     C9 CALL func breakpoints.a.testmod.test_in_a/0-0 (det) breakpoints.a.testmod.m:10 (breakpoints.m:27)
+test_in_a = '_'
+mdb> break_print 0 none
+ 0: + stop  interface func breakpoints.a.testmod.test_in_a/0-0 (det)
+mdb> break_print 0 *
+ 0: + stop  interface func breakpoints.a.testmod.test_in_a/0-0 (det)
+            all (flat)
+mdb> continue
+     E15:     C9 EXIT func breakpoints.a.testmod.test_in_a/0-0 (det) breakpoints.a.testmod.m:10 (breakpoints.m:27)
+       HeadVar__1             	"a"
+mdb> continue
 "a"
+     E16:    C10 CALL func breakpoints.b.testmod.test_in_b/0-0 (det) breakpoints.b.testmod.m:10 (breakpoints.m:29)
+mdb: there is no variable named HeadVar__1.
+     E17:    C10 EXIT func breakpoints.b.testmod.test_in_b/0-0 (det) breakpoints.b.testmod.m:10 (breakpoints.m:29)
+       HeadVar__1             	"b"
 "b"
Index: tests/debugger/breakpoints.exp2
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/breakpoints.exp2,v
retrieving revision 1.8
diff -u -b -r1.8 breakpoints.exp2
--- tests/debugger/breakpoints.exp2	17 Jan 2005 04:29:28 -0000	1.8
+++ tests/debugger/breakpoints.exp2	25 Jan 2005 19:28:16 -0000
@@ -98,16 +98,51 @@
  3: - stop      entry pred breakpoints.qperm/2-0 (nondet)
 mdb> break nodiag
  0: + stop  interface pred breakpoints.nodiag/3-0 (semidet)
+mdb> break_print -v -n 1 HeadVar__1 HeadVar__2
+ 1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
+            HeadVar__1 (verbose, nowarn), HeadVar__2 (verbose, nowarn)
 mdb> continue
       E3:     C3 CALL pred breakpoints.qperm/2-0 (nondet) breakpoints.m:64 (breakpoints.m:61)
+       HeadVar__1             	
+[|]
+1-1
+2-[|]
+  1-2
+  2-[|]
+    1-3
+    2-[|]/2
+
+mdb> break_print 1 none
+ 1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
+mdb> set -p depth 10
+mdb> set -p size 20
+mdb> break_print -p -n 1 HeadVar__1 HeadVar__2
+ 1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
+            HeadVar__1 (pretty, nowarn), HeadVar__2 (pretty, nowarn)
 mdb> continue
       E4:     C3 SWTC pred breakpoints.qperm/2-0 (nondet) s2; breakpoints.m:65
 mdb> finish -N
       E5:     C4 CALL pred breakpoints.qperm/2-0 (nondet) breakpoints.m:64 (breakpoints.m:68)
+       HeadVar__1             	
+[2, 3, 4, 5]
 mdb> finish -n
       E6:     C4 EXIT pred breakpoints.qperm/2-0 (nondet) breakpoints.m:64 (breakpoints.m:68)
+       HeadVar__1             	
+[2, 3, 4, 5]
+       HeadVar__2             	
+[2, 3, 4, 5]
+mdb> break_print 1 none
+ 1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
+mdb> break_print -f -n 1 HeadVar__1
+ 1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
+            HeadVar__1 (flat, nowarn)
+mdb> break_print -f -e -n 1 HeadVar__2
+ 1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
+            HeadVar__1 (flat, nowarn), HeadVar__2 (flat, nowarn)
 mdb> continue
       E7:     C3 EXIT pred breakpoints.qperm/2-0 (nondet) breakpoints.m:64 (breakpoints.m:61)
+       HeadVar__1             	[1, 2, 3, 4, 5]
+       HeadVar__2             	[1, 2, 3, 4, 5]
 mdb> continue
       E8:     C5 CALL pred breakpoints.safe/1-0 (semidet) breakpoints.m:74 (breakpoints.m:62)
 mdb> finish
@@ -195,7 +230,36 @@
  0: + stop  interface func breakpoints.a.testmod.test_in_ab/0-0 (det)
 mdb> break -O b.testmod.test_in_ab
  1: + stop  interface func breakpoints.b.testmod.test_in_ab/0-0 (det)
+mdb> delete *
+ 0: E stop  interface func breakpoints.a.testmod.test_in_ab/0-0 (det)
+ 1: E stop  interface func breakpoints.b.testmod.test_in_ab/0-0 (det)
+mdb> break -O -p goal test_in_a
+ 0: + stop  interface func breakpoints.a.testmod.test_in_a/0-0 (det)
+            goal (flat)
+mdb> break -O -P -p HeadVar__1 test_in_b
+ 1: + print interface func breakpoints.b.testmod.test_in_b/0-0 (det)
+            HeadVar__1 (flat)
+mdb> break info
+ 0: + stop  interface func breakpoints.a.testmod.test_in_a/0-0 (det)
+            goal (flat)
+ 1: + print interface func breakpoints.b.testmod.test_in_b/0-0 (det)
+            HeadVar__1 (flat)
 mdb> continue
 [1, 3, 5, 2, 4]
+     E14:     C9 CALL func breakpoints.a.testmod.test_in_a/0-0 (det) breakpoints.a.testmod.m:10 (breakpoints.m:27)
+test_in_a = '_'
+mdb> break_print 0 none
+ 0: + stop  interface func breakpoints.a.testmod.test_in_a/0-0 (det)
+mdb> break_print 0 *
+ 0: + stop  interface func breakpoints.a.testmod.test_in_a/0-0 (det)
+            all (flat)
+mdb> continue
+     E15:     C9 EXIT func breakpoints.a.testmod.test_in_a/0-0 (det) breakpoints.a.testmod.m:10 (breakpoints.m:27)
+       HeadVar__1             	"a"
+mdb> continue
 "a"
+     E16:    C10 CALL func breakpoints.b.testmod.test_in_b/0-0 (det) breakpoints.b.testmod.m:10 (breakpoints.m:29)
+mdb: there is no variable named HeadVar__1.
+     E17:    C10 EXIT func breakpoints.b.testmod.test_in_b/0-0 (det) breakpoints.b.testmod.m:10 (breakpoints.m:29)
+       HeadVar__1             	"b"
 "b"
Index: tests/debugger/breakpoints.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/breakpoints.inp,v
retrieving revision 1.7
diff -u -b -r1.7 breakpoints.inp
--- tests/debugger/breakpoints.inp	17 Jan 2005 04:29:28 -0000	1.7
+++ tests/debugger/breakpoints.inp	25 Jan 2005 00:26:51 -0000
@@ -27,10 +27,18 @@
 break info
 disable 3
 break nodiag
+break_print -v -n 1 HeadVar__1 HeadVar__2
 continue
+break_print 1 none
+set -p depth 10
+set -p size 20
+break_print -p -n 1 HeadVar__1 HeadVar__2
 continue
 finish -N
 finish -n
+break_print 1 none
+break_print -f -n 1 HeadVar__1
+break_print -f -e -n 1 HeadVar__2
 continue
 continue
 finish
@@ -60,4 +68,12 @@
 break -O testmod.test_in_ab
 break -O a.testmod.test_in_ab
 break -O b.testmod.test_in_ab
+delete *
+break -O -p goal test_in_a
+break -O -P -p HeadVar__1 test_in_b
+break info
+continue
+break_print 0 none
+break_print 0 *
+continue
 continue
Index: tests/debugger/completion.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/completion.exp,v
retrieving revision 1.24
diff -u -b -r1.24 completion.exp
--- tests/debugger/completion.exp	17 Jan 2005 05:58:07 -0000	1.24
+++ tests/debugger/completion.exp	24 Jan 2005 06:32:47 -0000
@@ -3,38 +3,39 @@
 Command echo enabled.
 mdb> register --quiet
 mdb> 
-?                    excp                 quit
-P                    f                    r
-alias                finish               register
-all_class_decls      flag                 retry
-all_procedures       forward              return
-all_regs             g                    s
-all_type_ctors       gen_stack            save
-b                    goal_paths           save_to_file
-break                goto                 scope
-browse               h                    scroll
-c                    help                 set
-cc_query             histogram_all        source
-class_decl           histogram_exp        stack
-clear_histogram      ignore               stack_default_limit
-consumer             io_query             stack_regs
-context              label_stats          step
-continue             level                subgoal
-current              maxdepth             table
-cut_stack            mindepth             table_io
-d                    mm_stacks            term_size
-dd                   mmc_options          trust
-dd_dd                modules              trusted
-debug_vars           next                 type_ctor
-delete               nondet_stack         unalias
-disable              p                    unhide_events
-document             pneg_stack           untrust
-document_category    print                up
-down                 print_optionals      v
-e                    printlevel           var_details
-echo                 proc_stats           var_name_stats
-enable               procedures           vars
-exception            query                view
+?                    excp                 r
+P                    f                    register
+alias                finish               retry
+all_class_decls      flag                 return
+all_procedures       forward              s
+all_regs             g                    save
+all_type_ctors       gen_stack            save_to_file
+b                    goal_paths           scope
+break                goto                 scroll
+break_print          h                    set
+browse               help                 source
+c                    histogram_all        stack
+cc_query             histogram_exp        stack_default_limit
+class_decl           ignore               stack_regs
+clear_histogram      io_query             step
+consumer             label_stats          subgoal
+context              level                table
+continue             maxdepth             table_io
+current              mindepth             term_size
+cut_stack            mm_stacks            trust
+d                    mmc_options          trusted
+dd                   modules              type_ctor
+dd_dd                next                 unalias
+debug_vars           nondet_stack         unhide_events
+delete               p                    untrust
+disable              pneg_stack           up
+document             print                v
+document_category    print_optionals      var_details
+down                 printlevel           var_name_stats
+e                    proc_stats           vars
+echo                 procedures           view
+enable               query                
+exception            quit                 
 h              help           histogram_all  histogram_exp  
 var_details     var_name_stats  vars            view
 var_details     var_name_stats  vars            
Index: tests/debugger/mdb_command_test.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/mdb_command_test.inp,v
retrieving revision 1.35
diff -u -b -r1.35 mdb_command_test.inp
--- tests/debugger/mdb_command_test.inp	17 Jan 2005 05:58:08 -0000	1.35
+++ tests/debugger/mdb_command_test.inp	25 Jan 2005 19:27:01 -0000
@@ -25,6 +25,7 @@
 save_to_file         xyzzy xyzzy xyzzy xyzzy xyzzy
 break                xyzzy xyzzy xyzzy xyzzy xyzzy
 ignore               xyzzy xyzzy xyzzy xyzzy xyzzy
+break_print          xyzzy xyzzy xyzzy xyzzy xyzzy
 disable              xyzzy xyzzy xyzzy xyzzy xyzzy
 enable               xyzzy xyzzy xyzzy xyzzy xyzzy
 delete               xyzzy xyzzy xyzzy xyzzy xyzzy
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
Index: trace/mercury_trace.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace.c,v
retrieving revision 1.76
diff -u -b -r1.76 mercury_trace.c
--- trace/mercury_trace.c	10 Jan 2005 05:23:53 -0000	1.76
+++ trace/mercury_trace.c	23 Jan 2005 14:47:36 -0000
@@ -69,9 +69,10 @@
 };
 
 MR_Code             *MR_trace_real(const MR_Label_Layout *layout);
-static  MR_Code     *MR_trace_event(MR_Trace_Cmd_Info *cmd, MR_bool interactive,
-                        const MR_Label_Layout *layout, MR_Trace_Port port,
-                        MR_Unsigned seqno, MR_Unsigned depth);
+static  MR_Code     *MR_trace_event(MR_Trace_Cmd_Info *cmd,
+                        MR_bool interactive, const MR_Label_Layout *layout,
+                        MR_Trace_Port port, MR_Unsigned seqno,
+                        MR_Unsigned depth);
 static  MR_bool     MR_in_traced_region(const MR_Proc_Layout *proc_layout,
                         MR_Word *base_sp, MR_Word *base_curfr);
 static  MR_bool     MR_is_io_state(MR_PseudoTypeInfo pti);
@@ -344,7 +345,21 @@
         }
 #endif
 
-        match = MR_event_matches_spy_point(layout, port, &action);
+        {
+            /*
+            ** We ignore the print_list computed here, because we want to
+            ** execute the print list of a matched spy point even if the event
+            ** is the end event of a command. In that case, the code above
+            ** invokes MR_trace_event directly without coming here. We
+            ** therefore invoke MR_event_matches_spy_point in MR_trace_event.
+            ** The invocation here is only to find out if we want to stop.
+            */
+
+            MR_Spy_Print_List   print_list;
+            match = MR_event_matches_spy_point(layout, port, &action,
+                &print_list);
+        }
+
         if (! match) {
             if (MR_trace_ctrl.MR_trace_print_level == MR_PRINT_LEVEL_ALL) {
                 return MR_trace_event(&MR_trace_ctrl, MR_FALSE, layout, port,
@@ -457,7 +472,12 @@
 
         jumpaddr = MR_trace_event_external(cmd, &event_info);
     } else {
-        jumpaddr = MR_trace_event_internal(cmd, interactive, &event_info);
+        MR_Spy_Action       action;         /* ignored */
+        MR_Spy_Print_List   print_list;
+
+        (void) MR_event_matches_spy_point(layout, port, &action, &print_list);
+        jumpaddr = MR_trace_event_internal(cmd, interactive, print_list,
+            &event_info);
     }
 #else
     /*
Index: trace/mercury_trace_declarative.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_declarative.c,v
retrieving revision 1.78
diff -u -b -r1.78 mercury_trace_declarative.c
--- trace/mercury_trace_declarative.c	24 Jan 2005 07:53:38 -0000	1.78
+++ trace/mercury_trace_declarative.c	25 Jan 2005 02:51:08 -0000
@@ -318,7 +318,7 @@
 				(unsigned long) event_info->MR_event_number,
 				(unsigned long) MR_edt_last_event);
 		MR_trace_decl_mode = MR_TRACE_INTERACTIVE;
-		return MR_trace_event_internal(cmd, MR_TRUE, event_info);
+		return MR_trace_event_internal(cmd, MR_TRUE, NULL, event_info);
 	}
 
 	if (!MR_PROC_LAYOUT_HAS_EXEC_TRACE(entry)) {
@@ -1427,7 +1427,7 @@
 		MR_trace_decl_mode = MR_TRACE_INTERACTIVE;
 		MR_debug_enabled = MR_TRUE;
 		MR_update_trace_func_enabled();
-		return MR_trace_event_internal(cmd, MR_TRUE, event_info);
+		return MR_trace_event_internal(cmd, MR_TRUE, NULL, event_info);
 	}
 
 	return jumpaddr;
@@ -1552,7 +1552,7 @@
 		MR_trace_call_depth = event_details->MR_call_depth;
 		MR_trace_event_number = event_details->MR_event_number;
 
-		return MR_trace_event_internal(cmd, MR_TRUE, event_info);
+		return MR_trace_event_internal(cmd, MR_TRUE, NULL, event_info);
 	}
 
 	if (MR_trace_decl_in_dd_dd_mode) {
@@ -1697,7 +1697,7 @@
 		MR_trace_decl_mode = MR_TRACE_INTERACTIVE;
 		MR_debug_enabled = MR_TRUE;
 		MR_update_trace_func_enabled();
-		return MR_trace_event_internal(cmd, MR_TRUE, event_info);
+		return MR_trace_event_internal(cmd, MR_TRUE, NULL, event_info);
 	}
 
 	cmd->MR_trace_cmd = MR_CMD_GOTO;
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.188
diff -u -b -r1.188 mercury_trace_internal.c
--- trace/mercury_trace_internal.c	24 Jan 2005 07:53:38 -0000	1.188
+++ trace/mercury_trace_internal.c	25 Jan 2005 13:57:46 -0000
@@ -431,6 +431,7 @@
 static	MR_TraceCmdFunc	MR_trace_cmd_save_to_file;
 static	MR_TraceCmdFunc	MR_trace_cmd_break;
 static	MR_TraceCmdFunc	MR_trace_cmd_ignore;
+static	MR_TraceCmdFunc	MR_trace_cmd_break_print;
 static	MR_TraceCmdFunc	MR_trace_cmd_enable;
 static	MR_TraceCmdFunc	MR_trace_cmd_disable;
 static	MR_TraceCmdFunc	MR_trace_cmd_delete;
@@ -506,6 +507,9 @@
 			MR_bool detailed, int frame_limit, int line_limit);
 static	void	MR_trace_cmd_nondet_stack_2(MR_Event_Info *event_info,
 			MR_bool detailed, int frame_limit, int line_limit);
+static	MR_Spy_Print_List MR_add_to_print_list_end(MR_Browse_Format format,
+			char *word, MR_bool warn,
+			MR_Spy_Print_List print_list);
 
 static	MR_bool	MR_trace_options_movement_cmd(MR_Trace_Cmd_Info *cmd,
 			char ***words, int *word_count,
@@ -517,6 +521,7 @@
 static	MR_bool	MR_trace_options_when_action_multi_ignore(MR_Spy_When *when,
 			MR_Spy_Action *action, MR_MultiMatch *multi_match,
 			MR_Spy_Ignore_When *ignore_when, int *ignore_count,
+			MR_Spy_Print_List *print_list,
 			char ***words, int *word_count,
 			const char *cat, const char *item);
 static	MR_bool	MR_trace_options_ignore_count(MR_Spy_Ignore_When *ignore_when,
@@ -526,6 +531,9 @@
 			int *word_count, const char *cat, const char *item);
 static	MR_bool	MR_trace_options_ignore(MR_bool *ignore_errors, char ***words,
 			int *word_count, const char *cat, const char *item);
+static	MR_bool	MR_trace_options_break_print(MR_Browse_Format *format,
+			MR_bool *at_start, MR_bool *warn, char ***words,
+			int *word_count, const char *cat, const char *item);
 static	MR_bool	MR_trace_options_detailed(MR_bool *detailed, char ***words,
 			int *word_count, const char *cat, const char *item);
 static	MR_bool	MR_trace_options_stack_trace(MR_bool *detailed,
@@ -566,6 +574,9 @@
 			const char *item);
 static	void	MR_trace_usage(const char *cat, const char *item);
 static	void	MR_trace_do_noop(void);
+static	void	MR_mdb_print_proc_id_and_nl(void *data,
+			const MR_Proc_Layout *entry_layout);
+static	int	MR_trace_var_print_list(MR_Spy_Print_List print_list);
 
 static	const MR_Proc_Layout *
 		MR_find_single_matching_proc(MR_Proc_Spec *spec,
@@ -675,6 +686,10 @@
 static	void	MR_trace_source_from_open_file(FILE *fp);
 static	char	*MR_trace_getline_queue(void);
 static	MR_bool	MR_trace_continue_line(char *ptr, MR_bool *quoted);
+static	MR_Code	*MR_trace_event_internal_report(MR_Trace_Cmd_Info *cmd,
+			MR_Spy_Print_List print_list,
+			MR_Event_Info *event_info);
+
 static	void	MR_insert_line_at_head(const char *line);
 static	void	MR_insert_line_at_tail(const char *line);
 
@@ -691,7 +706,7 @@
 
 MR_Code *
 MR_trace_event_internal(MR_Trace_Cmd_Info *cmd, MR_bool interactive,
-	MR_Event_Info *event_info)
+	MR_Spy_Print_List print_list, MR_Event_Info *event_info)
 {
 	MR_Code			*jumpaddr;
 	char			*line;
@@ -700,7 +715,8 @@
 	const char		*prompt;
 
 	if (! interactive) {
-		return MR_trace_event_internal_report(cmd, event_info);
+		return MR_trace_event_internal_report(cmd, print_list,
+			event_info);
 	}
 
 	if (MR_trace_decl_mode != MR_TRACE_INTERACTIVE) {
@@ -740,6 +756,8 @@
 		event_info->MR_saved_regs, event_info->MR_trace_port,
 		MR_print_optionals);
 
+	(void) MR_trace_var_print_list(print_list);
+
 	/* by default, return where we came from */
 	jumpaddr = NULL;
 
@@ -1384,6 +1402,72 @@
 	MR_print_proc_id_and_nl(fp, entry_layout);
 }
 
+static int
+MR_trace_var_print_list(MR_Spy_Print_List print_list)
+{
+	MR_Spy_Print	node;
+	const char	*problem;
+	char		*after_problem;
+	int		count;
+
+	count = 0;
+	for (; print_list != NULL; print_list = print_list->pl_next) {
+		count++;
+		node = print_list->pl_cur;
+		after_problem = NULL;
+
+		switch (node->p_what) {
+			case MR_SPY_PRINT_ALL:
+				problem = MR_trace_browse_all(MR_mdb_out,
+					MR_trace_browse_internal,
+					node->p_format);
+				break;
+
+			case MR_SPY_PRINT_GOAL:
+				problem = MR_trace_browse_one_goal(MR_mdb_out,
+					MR_trace_browse_goal_internal,
+					MR_BROWSE_CALLER_PRINT,
+					node->p_format);
+				break;
+
+			case MR_SPY_PRINT_ONE:
+				problem = MR_trace_parse_browse_one(MR_mdb_out,
+					MR_TRUE, node->p_name,
+					MR_trace_browse_internal,
+					MR_BROWSE_CALLER_PRINT, node->p_format,
+					MR_FALSE);
+				if (problem != NULL && MR_streq(problem,
+					"there is no such variable"))
+				{
+					if (node->p_warn) {
+						problem = "there is no "
+							"variable named";
+						after_problem = node->p_name;
+					} else {
+						problem = NULL;
+					}
+				}
+
+				break;
+
+			default:
+				MR_fatal_error("invalid node->p_what");
+				break;
+		}
+
+		if (problem != NULL) {
+			fflush(MR_mdb_out);
+			fprintf(MR_mdb_err, "mdb: %s", problem);
+			if (after_problem != NULL) {
+				fprintf(MR_mdb_err, " %s", after_problem);
+			}
+			fprintf(MR_mdb_err, ".\n");
+		}
+	}
+
+	return count;
+}
+
 /* Options to pass to mmc when compiling queries. */
 static char *MR_mmc_options = NULL;
 
@@ -2436,6 +2520,7 @@
 	MR_MultiMatch		multi_match;
 	MR_Spy_Ignore_When	ignore_when;
 	int			ignore_count;
+	MR_Spy_Print_List	print_list;
 	const char		*file;
 	int			line;
 	int			breakline;
@@ -2450,7 +2535,7 @@
 		count = 0;
 		for (i = 0; i < MR_spy_point_next; i++) {
 			if (MR_spy_points[i]->spy_exists) {
-				MR_print_spy_point(MR_mdb_out, i);
+				MR_print_spy_point(MR_mdb_out, i, MR_TRUE);
 				count++;
 			}
 		}
@@ -2472,8 +2557,9 @@
 	*/
 	ignore_when = MR_SPY_DONT_IGNORE;
 	ignore_count = 0;
+	print_list = NULL;
 	if (! MR_trace_options_when_action_multi_ignore(&when, &action,
-		&multi_match, &ignore_when, &ignore_count,
+		&multi_match, &ignore_when, &ignore_count, &print_list,
 		&words, &word_count, "breakpoint", "break"))
 	{
 		; /* the usage message has already been printed */
@@ -2501,7 +2587,7 @@
 		MR_register_all_modules_and_procs(MR_mdb_out, MR_TRUE);
 		slot = MR_add_proc_spy_point(MR_SPY_SPECIFIC, action,
 				ignore_when, ignore_count,
-				layout->MR_sll_entry, layout,
+				layout->MR_sll_entry, layout, print_list,
 				&problem);
 		MR_maybe_print_spy_point(slot, problem);
 	} else if (word_count == 2 && MR_parse_proc_spec(words[1], &spec)) {
@@ -2517,7 +2603,7 @@
 		} else if (matches.match_proc_next == 1) {
 			slot = MR_add_proc_spy_point(when, action,
 				ignore_when, ignore_count,
-				matches.match_procs[0], NULL,
+				matches.match_procs[0], NULL, print_list,
 				&problem);
 			MR_maybe_print_spy_point(slot, problem);
 		} else if (multi_match == MR_MULTIMATCH_ALL) {
@@ -2528,7 +2614,7 @@
 					when, action,
 					ignore_when, ignore_count,
 					matches.match_procs[i], NULL,
-					&problem);
+					print_list, &problem);
 				MR_maybe_print_spy_point(slot,
 					problem);
 			}
@@ -2570,7 +2656,7 @@
 						ignore_when,
 						ignore_count,
 						matches.match_procs[i],
-						NULL, &problem);
+						NULL, print_list, &problem);
 					MR_maybe_print_spy_point(
 						slot, problem);
 				}
@@ -2585,7 +2671,7 @@
 						ignore_when,
 						ignore_count,
 						matches.match_procs[i],
-						NULL, &problem);
+						NULL, print_list, &problem);
 					MR_maybe_print_spy_point(
 						slot, problem);
 				} else {
@@ -2604,7 +2690,7 @@
 		int	slot;
 
 		slot = MR_add_line_spy_point(action, ignore_when,
-			ignore_count, file, line, &problem);
+			ignore_count, file, line, print_list, &problem);
 		MR_maybe_print_spy_point(slot, problem);
 	} else if (word_count == 2 &&
 		MR_trace_is_natural_number(words[1], &breakline))
@@ -2614,7 +2700,7 @@
 		if (MR_find_context(layout, &file, &line)) {
 			slot = MR_add_line_spy_point(action,
 				ignore_when, ignore_count,
-				file, breakline, &problem);
+				file, breakline, print_list, &problem);
 			MR_maybe_print_spy_point(slot, problem);
 		} else {
 			MR_fatal_error("cannot find current filename");
@@ -2697,6 +2783,97 @@
 }
 
 static MR_Next
+MR_trace_cmd_break_print(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+	MR_Event_Info *event_info, MR_Event_Details *event_details,
+	MR_Code **jumpaddr)
+{
+	int			n;
+	int			i;
+	MR_Browse_Format	format;
+	MR_bool			at_start;
+	MR_bool			warn;
+	MR_Spy_Print_List	print_list;
+
+	if (! MR_trace_options_break_print(&format, &at_start, &warn,
+		&words, &word_count, "breakpoint", "break_print"))
+	{
+		; /* the usage message has already been printed */
+	} else if (word_count > 2 && MR_trace_is_natural_number(words[1], &n))
+	{
+		if (word_count == 3 && MR_streq(words[2], "none")) {
+			MR_clear_spy_point_print_list(n);
+			MR_print_spy_point(MR_mdb_out, n, MR_TRUE);
+		} else if (0 <= n && n < MR_spy_point_next
+			&& MR_spy_points[n]->spy_exists)
+		{
+			print_list = NULL;
+			for (i = 2; i < word_count; i++) {
+				print_list = MR_add_to_print_list_end(format,
+					words[i], warn, print_list);
+			}
+
+			if (at_start) {
+				MR_add_spy_point_print_list_start(n,
+					print_list);
+			} else {
+				MR_add_spy_point_print_list_end(n,
+					print_list);
+			}
+
+			MR_print_spy_point(MR_mdb_out, n, MR_TRUE);
+		} else {
+			fflush(MR_mdb_out);
+			fprintf(MR_mdb_err, "mdb: break point #%d "
+				"does not exist.\n",
+				n);
+		}
+	} else {
+		MR_trace_usage("breakpoint", "break_print");
+	}
+
+	return KEEP_INTERACTING;
+}
+
+static MR_Spy_Print_List
+MR_add_to_print_list_end(MR_Browse_Format format, char *word, MR_bool warn,
+	MR_Spy_Print_List print_list)
+{
+	MR_Spy_Print_List	list;
+	MR_Spy_Print_List	new_list;
+	MR_Spy_Print		new_node;
+
+	new_node = MR_malloc(sizeof(struct MR_Spy_Print_Struct));
+	new_node->p_format = format;
+	new_node->p_warn = warn;
+	if (MR_streq(word, "*")) {
+		new_node->p_what = MR_SPY_PRINT_ALL;
+		new_node->p_name = NULL;
+	} else if (MR_streq(word, "goal")) {
+		new_node->p_what = MR_SPY_PRINT_GOAL;
+		new_node->p_name = NULL;
+	} else {
+		new_node->p_what = MR_SPY_PRINT_ONE;
+		new_node->p_name = MR_copy_string(word);
+	}
+
+	new_list = MR_malloc(sizeof(struct MR_Spy_Print_List_Struct));
+	new_list->pl_cur = new_node;
+	new_list->pl_next = NULL;
+
+	list = print_list;
+	if (list == NULL) {
+		return new_list;
+	}
+
+	while (list->pl_next != NULL) {
+		list = list->pl_next;
+	}
+
+	list->pl_next = new_list;
+	return print_list;
+}
+
+static MR_Next
 MR_trace_cmd_enable(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
 	MR_Event_Info *event_info, MR_Event_Details *event_details,
 	MR_Code **jumpaddr)
@@ -2708,7 +2885,7 @@
 			&& MR_spy_points[n]->spy_exists)
 		{
 			MR_spy_points[n]->spy_enabled = MR_TRUE;
-			MR_print_spy_point(MR_mdb_out, n);
+			MR_print_spy_point(MR_mdb_out, n, MR_FALSE);
 		} else {
 			fflush(MR_mdb_out);
 			fprintf(MR_mdb_err, "mdb: break point #%d "
@@ -2723,7 +2900,7 @@
 		for (i = 0; i < MR_spy_point_next; i++) {
 			if (MR_spy_points[i]->spy_exists) {
 				MR_spy_points[i]->spy_enabled = MR_TRUE;
-				MR_print_spy_point(MR_mdb_out, i);
+				MR_print_spy_point(MR_mdb_out, i, MR_FALSE);
 				count++;
 			}
 		}
@@ -2741,7 +2918,7 @@
 			MR_spy_points[MR_most_recent_spy_point]
 				->spy_enabled = MR_TRUE;
 			MR_print_spy_point(MR_mdb_out,
-				MR_most_recent_spy_point);
+				MR_most_recent_spy_point, MR_FALSE);
 		} else {
 			fflush(MR_mdb_out);
 			fprintf(MR_mdb_err, "mdb: there is no "
@@ -2766,7 +2943,7 @@
 			&& MR_spy_points[n]->spy_exists)
 		{
 			MR_spy_points[n]->spy_enabled = MR_FALSE;
-			MR_print_spy_point(MR_mdb_out, n);
+			MR_print_spy_point(MR_mdb_out, n, MR_FALSE);
 		} else {
 			fflush(MR_mdb_out);
 			fprintf(MR_mdb_err, "mdb: break point #%d "
@@ -2782,7 +2959,7 @@
 			if (MR_spy_points[i]->spy_exists) {
 				MR_spy_points[i]->spy_enabled =
 					MR_FALSE;
-				MR_print_spy_point(MR_mdb_out, i);
+				MR_print_spy_point(MR_mdb_out, i, MR_FALSE);
 				count++;
 			}
 		}
@@ -2801,7 +2978,7 @@
 			MR_spy_points[MR_most_recent_spy_point]
 				->spy_enabled = MR_FALSE;
 			MR_print_spy_point(MR_mdb_out,
-				MR_most_recent_spy_point);
+				MR_most_recent_spy_point, MR_FALSE);
 		} else {
 			fflush(MR_mdb_out);
 			fprintf(MR_mdb_err, "There is no "
@@ -2826,7 +3003,7 @@
 			&& MR_spy_points[n]->spy_exists)
 		{
 			MR_spy_points[n]->spy_exists = MR_FALSE;
-			MR_print_spy_point(MR_mdb_out, n);
+			MR_print_spy_point(MR_mdb_out, n, MR_FALSE);
 			MR_delete_spy_point(n);
 		} else {
 			fflush(MR_mdb_out);
@@ -2842,7 +3019,7 @@
 		for (i = 0; i < MR_spy_point_next; i++) {
 			if (MR_spy_points[i]->spy_exists) {
 				MR_spy_points[i]->spy_exists = MR_FALSE;
-				MR_print_spy_point(MR_mdb_out, i);
+				MR_print_spy_point(MR_mdb_out, i, MR_FALSE);
 				MR_delete_spy_point(i);
 				count++;
 			}
@@ -2863,7 +3040,7 @@
 
 			slot = MR_most_recent_spy_point;
 			MR_spy_points[slot]-> spy_exists = MR_FALSE;
-			MR_print_spy_point(MR_mdb_out, slot);
+			MR_print_spy_point(MR_mdb_out, slot, MR_FALSE);
 			MR_delete_spy_point(slot);
 		} else {
 			fflush(MR_mdb_out);
@@ -5796,7 +5973,7 @@
 		fflush(MR_mdb_out);
 		fprintf(MR_mdb_err, "mdb: %s.\n", problem);
 	} else {
-		MR_print_spy_point(MR_mdb_out, slot);
+		MR_print_spy_point(MR_mdb_out, slot, MR_TRUE);
 	}
 }
 
@@ -6086,6 +6263,8 @@
 	{ "interface",		MR_no_argument,		NULL,	'i' },
 	{ "ignore-entry",	MR_required_argument,	NULL,	'E' },
 	{ "ignore-interface",	MR_required_argument,	NULL,	'I' },
+	{ "print-list",		MR_no_argument,		NULL,	'p' },
+	{ "no-warn",		MR_no_argument,		NULL,	'n' },
 	{ "print",		MR_no_argument,		NULL,	'P' },
 	{ "stop",		MR_no_argument,		NULL,	'S' },
 	{ "select-all",		MR_no_argument,		NULL,	'A' },
@@ -6097,12 +6276,17 @@
 MR_trace_options_when_action_multi_ignore(MR_Spy_When *when,
 	MR_Spy_Action *action, MR_MultiMatch *multi_match,
 	MR_Spy_Ignore_When*ignore_when, int *ignore_count,
+	MR_Spy_Print_List *print_list,
 	char ***words, int *word_count, const char *cat, const char *item)
 {
 	int	c;
+	MR_Spy_Print 		node;
+	MR_Spy_Print_List 	list;
+	MR_bool			warn;
 
+	warn = MR_TRUE;
 	MR_optind = 0;
-	while ((c = MR_getopt_long(*word_count, *words, "AE:I:OPSaei",
+	while ((c = MR_getopt_long(*word_count, *words, "AE:I:OPSaeinp:",
 		MR_trace_when_action_multi_ignore_opts, NULL)) != EOF)
 	{
 		switch (c) {
@@ -6119,6 +6303,16 @@
 				*when = MR_SPY_INTERFACE;
 				break;
 
+			case 'n':
+				warn = MR_FALSE;
+				break;
+
+			case 'p':
+				*print_list = MR_add_to_print_list_end(
+					MR_BROWSE_FORMAT_FLAT, MR_optarg,
+					warn, *print_list);
+				break;
+
 			case 'E':
 				if (! MR_trace_is_natural_number(MR_optarg,
 					ignore_count))
@@ -6217,6 +6411,68 @@
 	return MR_TRUE;
 }
 
+static struct MR_option MR_trace_break_print_opts[] = 
+{
+	{ "end",	MR_no_argument,	NULL,	'e' },
+	{ "no-warn",	MR_no_argument,	NULL,	'n' },
+	{ "flat",	MR_no_argument,	NULL,	'f' },
+	{ "raw-pretty",	MR_no_argument,	NULL,	'r' },
+	{ "verbose",	MR_no_argument,	NULL,	'v' },
+	{ "pretty",	MR_no_argument,	NULL,	'p' },
+	{ NULL,		MR_no_argument,	NULL,	0 }
+};
+
+static MR_bool
+MR_trace_options_break_print(MR_Browse_Format *format, MR_bool *at_start,
+	MR_bool *warn, char ***words, int *word_count, const char *cat,
+	const char *item)
+{
+	int	c;
+
+	*format = MR_BROWSE_FORMAT_FLAT;
+	*at_start = MR_TRUE;
+	*warn = MR_TRUE;
+	MR_optind = 0;
+	while ((c = MR_getopt_long(*word_count, *words, "enfrvp",
+		MR_trace_break_print_opts, NULL)) != EOF)
+	{
+		switch (c) {
+
+			case 'e':
+				*at_start = MR_FALSE;
+				break;
+
+			case 'n':
+				*warn = MR_FALSE;
+				break;
+
+			case 'f':
+				*format = MR_BROWSE_FORMAT_FLAT;
+				break;
+
+			case 'r':
+				*format = MR_BROWSE_FORMAT_RAW_PRETTY;
+				break;
+
+			case 'v':
+				*format = MR_BROWSE_FORMAT_VERBOSE;
+				break;
+
+			case 'p':
+				*format = MR_BROWSE_FORMAT_PRETTY;
+				break;
+
+			default:
+				MR_trace_usage(cat, item);
+				return MR_FALSE;
+		}
+	}
+
+	*words = *words + MR_optind - 1;
+	*word_count = *word_count - MR_optind + 1;
+	return MR_TRUE;
+}
+
 static struct MR_option MR_trace_detailed_opts[] =
 {
 	{ "detailed",	MR_no_argument,	NULL,	'd' },
@@ -7359,15 +7615,23 @@
 	return (*quoted || escaped);
 }
 
-MR_Code *
+static MR_Code *
 MR_trace_event_internal_report(MR_Trace_Cmd_Info *cmd,
-	MR_Event_Info *event_info)
+	MR_Spy_Print_List print_list, MR_Event_Info *event_info)
 {
 	char	*buf;
 	int	i;
+	int			len;
+	MR_Spy_Print_List	list;
+
+	list = print_list;
+	len = 0;
+	for (; list != NULL; list = list->pl_next) {
+		len++;
+	}
 
 	/* We try to leave one line for the prompt itself. */
-	if (MR_scroll_control && MR_scroll_next >= MR_scroll_limit - 1) {
+	if (MR_scroll_control && MR_scroll_next + len >= MR_scroll_limit - 1) {
 	try_again:
 		buf = MR_trace_getline("--more-- ", MR_mdb_in, MR_mdb_out);
 		if (buf != NULL) {
@@ -7395,7 +7659,7 @@
 						MR_free(buf);
 						return MR_trace_event_internal(
 								cmd, MR_TRUE,
-								event_info);
+							NULL, event_info);
 
 					default:
 						fflush(MR_mdb_out);
@@ -7416,6 +7680,13 @@
 	MR_trace_event_print_internal_report(event_info);
 	MR_scroll_next++;
 
+	if (print_list != NULL) {
+		MR_trace_init_point_vars(event_info->MR_event_sll,
+			event_info->MR_saved_regs, event_info->MR_trace_port,
+			MR_print_optionals);
+		MR_scroll_next += MR_trace_var_print_list(print_list);
+	}
+
 	return NULL;
 }
 
@@ -7617,6 +7888,8 @@
 		MR_trace_break_cmd_args, MR_trace_breakpoint_completer },
 	{ "breakpoint", "ignore", MR_trace_cmd_ignore,
 		MR_trace_ignore_cmd_args, MR_trace_null_completer },
+	{ "breakpoint", "break_print", MR_trace_cmd_break_print,
+		NULL, MR_trace_null_completer },
 	{ "breakpoint", "enable", MR_trace_cmd_enable,
 		NULL, MR_trace_null_completer },
 	{ "breakpoint", "disable", MR_trace_cmd_disable,
Index: trace/mercury_trace_internal.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_internal.h,v
retrieving revision 1.18
diff -u -b -r1.18 mercury_trace_internal.h
--- trace/mercury_trace_internal.h	24 Jan 2005 07:53:39 -0000	1.18
+++ trace/mercury_trace_internal.h	25 Jan 2005 02:51:09 -0000
@@ -11,6 +11,7 @@
 #include "mercury_trace.h"	/* for MR_Event_Info, etc. */
 #include "mercury_std.h"	/* for MR_bool */
 #include "mercury_trace_completion.h"	/* for MR_Make_Completer */
+#include "mercury_trace_spy.h"	/* for MR_Spy_Print_List */
 
 #include <stdio.h>		/* for FILE */
 
@@ -36,10 +37,7 @@
 extern	MR_Trace_Mode	MR_trace_decl_mode;
 
 extern	MR_Code	*MR_trace_event_internal(MR_Trace_Cmd_Info *cmd,
-			MR_bool interactive, MR_Event_Info *event_info);
-
-
-extern	MR_Code	*MR_trace_event_internal_report(MR_Trace_Cmd_Info *cmd,
+			MR_bool interactive, MR_Spy_Print_List print_list,
 			MR_Event_Info *event_info);
 
 /*
Index: trace/mercury_trace_spy.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_spy.c,v
retrieving revision 1.21
diff -u -b -r1.21 mercury_trace_spy.c
--- trace/mercury_trace_spy.c	24 Oct 2002 16:30:44 -0000	1.21
+++ trace/mercury_trace_spy.c	25 Jan 2005 13:59:12 -0000
@@ -1,4 +1,7 @@
 /*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
 ** Copyright (C) 1998-2002 The University of Melbourne.
 ** This file may only be copied under the terms of the GNU Library General
 ** Public License - see the file COPYING.LIB in the Mercury distribution.
@@ -93,12 +96,15 @@
 
 /**************************************************************************/
 
-static	int	MR_compare_addr(const void *address1, const void *address2);
+static  int         MR_compare_addr(const void *address1,
+                        const void *address2);
 static	int	MR_search_spy_table_for_proc(const MR_Proc_Layout *entry);
-static	int	MR_search_spy_table_for_label(const MR_Label_Layout *label);
-static	void	MR_add_line_spy_point_callback(const MR_Label_Layout *label,
-			int spy_point_num);
+static  int         MR_search_spy_table_for_label(
+                        const MR_Label_Layout *label);
+static  void        MR_add_line_spy_point_callback(
+                        const MR_Label_Layout *label, int spy_point_num);
 static	int	MR_compare_spied_labels(const void *, const void *);
+static  void        MR_delete_spy_print_list(MR_Spy_Print_List print_list);
 static	void	MR_update_enabled_action(MR_Spy_Point *point,
 			MR_Trace_Port port, MR_Spy_Action *action_ptr,
 			MR_bool *enabled_ptr);
@@ -171,7 +177,8 @@
 
 MR_bool
 MR_event_matches_spy_point(const MR_Label_Layout *layout,
-	MR_Trace_Port port, MR_Spy_Action *action_ptr)
+    MR_Trace_Port port, MR_Spy_Action *action_ptr,
+    MR_Spy_Print_List *print_list)
 {
 	int			slot;
 	MR_bool			enabled;
@@ -184,40 +191,41 @@
 
 	enabled = MR_FALSE;
 	action = MR_SPY_PRINT;
+    *print_list = NULL;
 
 	if (MR_spied_label_next > 0) {
 		slot = MR_search_spy_table_for_label(layout);
 		if (slot >= 0) {
-			point = MR_spy_points[
-				MR_spied_labels[slot].spy_point_num];
+            point = MR_spy_points[MR_spied_labels[slot].spy_point_num];
 			if (point->spy_when != MR_SPY_LINENO) {
-				MR_fatal_error("non-lineno spy point in "
-					"spied labels array");
+                MR_fatal_error("non-lineno spy point in spied labels array");
 			}
 
-			MR_update_enabled_action(point, port,
-				&action, &enabled);
+            MR_update_enabled_action(point, port, &action, &enabled);
+            if (*print_list == NULL) {
+                *print_list = point->spy_print_list;
+            }
 		}
 
 		if (MR_port_is_interface(port)) {
 			MR_restore_transient_registers();
 			base_sp = MR_sp;
 			base_curfr = MR_curfr;
-			parent = MR_find_nth_ancestor(layout, 1,
-				&base_sp, &base_curfr, &problem);
+            parent = MR_find_nth_ancestor(layout, 1, &base_sp, &base_curfr,
+                &problem);
 			if (parent != NULL && 0 <=
 				(slot = MR_search_spy_table_for_label(parent)))
 			{
-				point = MR_spy_points[MR_spied_labels[slot].
-					spy_point_num];
+                point = MR_spy_points[MR_spied_labels[slot].spy_point_num];
 				if (point->spy_when != MR_SPY_LINENO) {
-					MR_fatal_error("non-lineno "
-						"spy point in "
+                    MR_fatal_error("non-lineno spy point in "
 						"spied labels array");
 				}
 
-				MR_update_enabled_action(point, port,
-					&action, &enabled);
+                MR_update_enabled_action(point, port, &action, &enabled);
+                if (*print_list == NULL) {
+                    *print_list = point->spy_print_list;
+                }
 			}
 		}
 	}
@@ -230,16 +238,19 @@
 			switch (point->spy_when) {
 
 				case MR_SPY_ALL:
-					MR_update_enabled_action(point,
-						port, &action,
-						&enabled);
+                    MR_update_enabled_action(point, port, &action, &enabled);
+                    if (*print_list == NULL) {
+                        *print_list = point->spy_print_list;
+                    }
 				break;
 
 				case MR_SPY_ENTRY:
 					if (MR_port_is_entry(port)) {
-						MR_update_enabled_action(point,
-							port, &action,
+                        MR_update_enabled_action(point, port, &action,
 							&enabled);
+                        if (*print_list == NULL) {
+                            *print_list = point->spy_print_list;
+                        }
 					} else {
 						continue;
 					}
@@ -248,9 +259,11 @@
 
 				case MR_SPY_INTERFACE:
 					if (MR_port_is_interface(port)) {
-						MR_update_enabled_action(point,
-							port, &action,
+                        MR_update_enabled_action(point, port, &action,
 							&enabled);
+                        if (*print_list == NULL) {
+                            *print_list = point->spy_print_list;
+                        }
 					} else {
 						continue;
 					}
@@ -259,9 +272,11 @@
 
 				case MR_SPY_SPECIFIC:
 					if (layout == point->spy_label) {
-						MR_update_enabled_action(point,
-							port, &action,
+                        MR_update_enabled_action(point, port, &action,
 							&enabled);
+                        if (*print_list == NULL) {
+                            *print_list = point->spy_print_list;
+                        }
 					} else {
 						continue;
 					}
@@ -269,8 +284,7 @@
 					break;
 
 				case MR_SPY_LINENO:
-					MR_fatal_error("lineno spy point in "
-						"spied procs array");
+                    MR_fatal_error("lineno spy point in spied procs array");
 
 				default:
 					MR_fatal_error("bad spy point when in "
@@ -329,6 +343,7 @@
 MR_add_proc_spy_point(MR_Spy_When when, MR_Spy_Action action,
 	MR_Spy_Ignore_When ignore_when, int ignore_count,
 	const MR_Proc_Layout *entry, const MR_Label_Layout *label,
+    MR_Spy_Print_List print_list,
 	const char **problem)
 {
 	MR_Spy_Point	*point;
@@ -344,8 +359,7 @@
 			MR_INIT_SPIED_PROCS);
 		MR_prepare_insert_into_sorted(MR_spied_procs,
 			MR_spied_proc_next, proc_slot,
-			MR_compare_addr(MR_spied_procs[proc_slot].spy_proc,
-				entry));
+            MR_compare_addr(MR_spied_procs[proc_slot].spy_proc, entry));
 		MR_spied_procs[proc_slot].spy_proc = entry;
 		MR_spied_procs[proc_slot].spy_points = NULL;
 	}
@@ -358,6 +372,7 @@
 	point->spy_action  = action;
 	point->spy_ignore_when  = ignore_when;
 	point->spy_ignore_count = ignore_count;
+    point->spy_print_list   = print_list;
 	point->spy_proc    = entry;
 	point->spy_label   = label;
 	point->spy_next    = MR_spied_procs[proc_slot].spy_points;
@@ -370,8 +385,7 @@
 		}
 	}
 
-	MR_ensure_room_for_next(MR_spy_point, MR_Spy_Point *,
-		MR_INIT_SPY_POINTS);
+    MR_ensure_room_for_next(MR_spy_point, MR_Spy_Point *, MR_INIT_SPY_POINTS);
 	point_slot = MR_spy_point_next;
 	MR_spy_points[point_slot] = point;
 	MR_spy_point_next++;
@@ -387,7 +401,7 @@
 int
 MR_add_line_spy_point(MR_Spy_Action action, MR_Spy_Ignore_When ignore_when,
 	int ignore_count, const char *orig_filename, int linenumber,
-	const char **problem)
+    MR_Spy_Print_List print_list, const char **problem)
 {
 	MR_Spy_Point	*point;
 	int		point_slot;
@@ -418,12 +432,10 @@
 		/* there were no matching labels */
 #ifdef	MR_HAVE_A_SNPRINTF
 		snprintf(MR_error_msg_buf, MR_ERROR_MSG_BUF_SIZE,
-			"there is no event at %s:%d",
-			filename, linenumber);
+            "there is no event at %s:%d", filename, linenumber);
 #else
 		/* not absolutely safe, but the risk of overflow is minimal */
-		sprintf(MR_error_msg_buf,
-			"there is no event at %s:%d",
+        sprintf(MR_error_msg_buf, "there is no event at %s:%d",
 			filename, linenumber);
 		if (strlen(MR_error_msg_buf) >= MR_ERROR_MSG_BUF_SIZE) {
 			MR_fatal_error("MR_add_line_spy_point: buf overflow");
@@ -448,6 +460,7 @@
 	point->spy_action     = action;
 	point->spy_ignore_when  = ignore_when;
 	point->spy_ignore_count = ignore_count;
+    point->spy_print_list = print_list;
 	point->spy_filename   = filename;
 	point->spy_linenumber = linenumber;
 
@@ -485,6 +498,53 @@
 		- (MR_Integer) label2->spy_label);
 }
 
+void
+MR_add_spy_point_print_list_start(int point_slot, MR_Spy_Print_List print_list)
+{
+    MR_Spy_Print_List   list;
+
+    list = print_list;
+    if (list == NULL) {
+        return;
+    }
+
+    /* find the last node in print_list */
+    while (list->pl_next != NULL) {
+        list = list->pl_next;
+    }
+
+    /* add the existing spy_print_list at the end of print_list */
+    list->pl_next = MR_spy_points[point_slot]->spy_print_list;
+    MR_spy_points[point_slot]->spy_print_list = print_list;
+}
+
+void
+MR_add_spy_point_print_list_end(int point_slot, MR_Spy_Print_List print_list)
+{
+    MR_Spy_Print_List   list;
+
+    list = MR_spy_points[point_slot]->spy_print_list;
+    if (list == NULL) {
+        MR_spy_points[point_slot]->spy_print_list = print_list;
+        return;
+    }
+
+    /* find the last node in print_list */
+    while (list->pl_next != NULL) {
+        list = list->pl_next;
+    }
+
+    /* add the print_list at the end of the existing spy_print_list */
+    list->pl_next = print_list;
+}
+
+void
+MR_clear_spy_point_print_list(int point_slot)
+{
+    MR_delete_spy_print_list(MR_spy_points[point_slot]->spy_print_list);
+    MR_spy_points[point_slot]->spy_print_list = NULL;
+}
+
 const char *
 MR_ignore_spy_point(int point_slot, MR_Spy_Ignore_When ignore_when,
 	int ignore_count)
@@ -510,6 +570,23 @@
 	return NULL;
 }
 
+static void
+MR_delete_spy_print_list(MR_Spy_Print_List print_list)
+{
+    if (print_list == NULL) {
+        return;
+    }
+
+    MR_delete_spy_print_list(print_list->pl_next);
+
+    if (print_list->pl_cur->p_name != NULL) {
+        MR_free(print_list->pl_cur->p_name);
+    }
+
+    MR_free(print_list->pl_cur);
+    MR_free(print_list);
+}
+
 void
 MR_delete_spy_point(int point_table_slot)
 {
@@ -526,6 +603,8 @@
 		MR_most_recent_spy_point = -1;
 	}
 
+    MR_delete_spy_print_list(point->spy_print_list);
+
 	if (point->spy_when == MR_SPY_LINENO) {
 		/* Release the storage acquired by MR_copy_string. */
 		MR_free(point->spy_filename);
@@ -536,9 +615,7 @@
 
 		label_slot = 0;
 		for (i = 0; i < MR_spied_label_next; i++) {
-			if (MR_spied_labels[i].spy_point_num !=
-				point_table_slot)
-			{
+            if (MR_spied_labels[i].spy_point_num != point_table_slot) {
 				MR_spied_labels[label_slot].spy_label =
 					MR_spied_labels[i].spy_label;
 				MR_spied_labels[label_slot].spy_point_num =
@@ -556,8 +633,7 @@
 
 		proc_table_slot = MR_search_spy_table_for_proc(point->spy_proc);
 		if (proc_table_slot < 0) {
-			MR_fatal_error("deleted spy point "
-				"was not indexed by proc addr");
+            MR_fatal_error("deleted spy point was not indexed by proc addr");
 		}
 
 		cur_addr = &MR_spied_procs[proc_table_slot].spy_points;
@@ -568,8 +644,7 @@
 		}
 
 		if (cur == NULL) {
-			MR_fatal_error("deleted spy point "
-				"was not on proc index list");
+            MR_fatal_error("deleted spy point was not on proc index list");
 		}
 
 		*cur_addr = point->spy_next;
@@ -577,7 +652,7 @@
 }
 
 void
-MR_print_spy_point(FILE *fp, int spy_point_num)
+MR_print_spy_point(FILE *fp, int spy_point_num, MR_bool verbose)
 {
 	MR_Spy_Point	*point;
 
@@ -590,8 +665,7 @@
 		MR_spy_action_string(point->spy_action),
 		MR_spy_when_names[point->spy_when]);
 	if (point->spy_when == MR_SPY_LINENO) {
-		fprintf(fp, "%s:%d",
-			point->spy_filename, point->spy_linenumber);
+        fprintf(fp, "%s:%d", point->spy_filename, point->spy_linenumber);
 	} else {
 		MR_print_proc_id(fp, point->spy_proc);
 	}
@@ -606,6 +680,73 @@
 	} else {
 		fprintf(fp, "\n");
 	}
+
+    if (verbose && point->spy_print_list != NULL) {
+        MR_Spy_Print_List   list;
+        MR_Spy_Print        node;
+
+        fprintf(fp, "%12s", "");
+        for (list = point->spy_print_list; list != NULL; list = list->pl_next)
+        {
+            node = list->pl_cur;
+            switch (node->p_what) {
+                case MR_SPY_PRINT_GOAL:
+                    fprintf(fp, "goal");
+                    break;
+
+                case MR_SPY_PRINT_ALL:
+                    fprintf(fp, "all");
+                    break;
+
+                case MR_SPY_PRINT_ONE:
+                    fprintf(fp, "%s", node->p_name);
+                    break;
+
+                default:
+                    MR_fatal_error("invalid node->p_name");
+                    break;
+            }
+
+            fprintf(fp, " (");
+            switch (node->p_format) {
+                case MR_BROWSE_FORMAT_FLAT:
+                    fprintf(fp, "flat");
+                    break;
+
+                case MR_BROWSE_FORMAT_RAW_PRETTY:
+                    fprintf(fp, "raw pretty");
+                    break;
+
+                case MR_BROWSE_FORMAT_PRETTY:
+                    fprintf(fp, "pretty");
+                    break;
+
+                case MR_BROWSE_FORMAT_VERBOSE:
+                    fprintf(fp, "verbose");
+                    break;
+
+                case MR_BROWSE_DEFAULT_FORMAT:
+                    fprintf(fp, "default");
+                    break;
+
+                default:
+                    MR_fatal_error("invalid node->p_format");
+                    break;
+            }
+
+            if (! node->p_warn) {
+                fprintf(fp, ", nowarn");
+            }
+
+            fprintf(fp, ")");
+
+            if (list->pl_next == NULL) {
+                fprintf(fp, "\n");
+            } else {
+                fprintf(fp, ", ");
+            }
+        }
+    }
 }
 
 static const char *
@@ -694,17 +835,20 @@
 				break;
 
 			case MR_SPY_SPECIFIC:
-				fprintf(err_fp, "mdb: cannot save "
-					"breakpoint on specific "
-					"internal label\n");
+                fprintf(err_fp, "mdb: cannot save breakpoint on "
+                    "specific internal label\n");
 				break;
 
 			default:
-				fprintf(err_fp, "mdb: internal error: "
-					"unknown spy when\n");
+                fprintf(err_fp, "mdb: internal error: unknown spy when\n");
 				return MR_TRUE;
 		}
 
+        if (point->spy_print_list != NULL) {
+            /* XXX */
+            fprintf(fp, "\n");
+        }
+
 		if (!point->spy_enabled) {
 			fprintf(fp, "disable\n");
 		}
Index: trace/mercury_trace_spy.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_spy.h,v
retrieving revision 1.9
diff -u -b -r1.9 mercury_trace_spy.h
--- trace/mercury_trace_spy.h	18 Feb 2002 07:01:31 -0000	1.9
+++ trace/mercury_trace_spy.h	24 Jan 2005 14:07:21 -0000
@@ -16,6 +16,7 @@
 
 #include "mercury_stack_layout.h"	/* for MR_Proc_Layout etc */
 #include "mercury_trace_base.h"		/* for MR_Trace_Port etc  */
+#include "mercury_trace_browse.h"	/* for MR_Browse_Format */
 
 typedef enum {
 	MR_SPY_PRINT, MR_SPY_STOP
@@ -41,6 +42,27 @@
 
 extern	const char	*MR_spy_when_names[];
 
+typedef	struct MR_Spy_Print_Struct	*MR_Spy_Print;
+typedef	struct MR_Spy_Print_List_Struct	*MR_Spy_Print_List;
+
+typedef enum {
+	MR_SPY_PRINT_GOAL,
+	MR_SPY_PRINT_ALL,
+	MR_SPY_PRINT_ONE,
+} MR_Spy_Print_What;
+
+struct MR_Spy_Print_Struct {
+	MR_Browse_Format	p_format;
+	MR_Spy_Print_What	p_what;
+	char			*p_name;	/* if MR_SPY_PRINT_ONE */
+	MR_bool			p_warn;
+};
+
+struct MR_Spy_Print_List_Struct {
+	MR_Spy_Print		pl_cur;
+	MR_Spy_Print_List	pl_next;
+};
+
 typedef struct MR_Spy_Point_Struct MR_Spy_Point;
 
 struct MR_Spy_Point_Struct {
@@ -50,6 +72,7 @@
 	MR_Spy_Action		spy_action;
 	MR_Spy_Ignore_When	spy_ignore_when;
 	int			spy_ignore_count;
+	MR_Spy_Print_List	spy_print_list;
 	const MR_Proc_Layout	*spy_proc;      /* if not LINENO */
 	const MR_Label_Layout	*spy_label;	/* if SPECIFIC */
 	char			*spy_filename;  /* if LINENO */
@@ -70,13 +93,15 @@
 
 /*
 ** Check whether the event described by the given label layout and port
-** matches any spy points. If yes, return MR_TRUE and set *action to say what
-** action should be executed for the spy point.
+** matches any spy points. If yes, return MR_TRUE, set *action to say what
+** action should be executed for the spy point, and set print_list to the
+** variable print list of the first matching spy point.
 */
 
 extern	MR_bool		MR_event_matches_spy_point(const MR_Label_Layout
 				*layout, MR_Trace_Port port,
-				MR_Spy_Action *action);
+				MR_Spy_Action *action,
+				MR_Spy_Print_List *print_list);
 
 /*
 ** Add a new spy point on a procedure (as opposed to on a line number)
@@ -90,6 +115,7 @@
 				int ignore_count,
 				const MR_Proc_Layout *entry,
 				const MR_Label_Layout *label,
+				MR_Spy_Print_List print_list,
 				const char **problem);
 
 /*
@@ -102,9 +128,26 @@
 				MR_Spy_Ignore_When ignore_when,
 				int ignore_count,
 				const char *filename, int linenumber,
+				MR_Spy_Print_List print_list,
 				const char **problem);
 
 /*
+** Add the given set of things to be printed to the spy point's list,
+** at either the start or the end of the existing list.
+*/
+
+extern	void 		MR_add_spy_point_print_list_start(int point_slot,
+				MR_Spy_Print_List print_list);
+extern	void 		MR_add_spy_point_print_list_end(int point_slot,
+				MR_Spy_Print_List print_list);
+
+/*
+** Empty the set of things to be printed at the spy point.
+*/
+
+extern	void		MR_clear_spy_point_print_list(int point_slot);
+
+/*
 ** Apply the given ignore specification to the given spy point.
 ** If the ignore specification is not appropriate for the spy point,
 ** return a non-NULL problem report.
@@ -125,7 +168,7 @@
 ** read to the given file.
 */
 
-extern	void		MR_print_spy_point(FILE *fp, int i);
+extern	void		MR_print_spy_point(FILE *fp, int i, MR_bool verbose);
 
 /*
 ** Print the set of current spy points (including those that are currently
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list