[m-rev.] for review: mdb ignore counts

Zoltan Somogyi zs at cs.mu.OZ.AU
Fri Aug 3 15:04:15 AEST 2001


For review by anyone.

Associate optional ignore counts with breakpoints.

trace/mercury_trace_spy.[ch]:
	Add a mechanism for ignoring break points until execution has gone
	through a given number of events matching the breakpoint; these events
	may be required to be of a given port type (call events or interface
	events).

trace/mercury_trace_internal.c:
	Add options to the break command to allow the ignore type and count to
	be set when a breakpoint is created.

	Add a new command, ignore, to allow the ignore type and count to be set
	when the breakpoint already exists.

doc/user_guide.texi:
	Document the ignore command and the new options of the break command.

tests/debugger/mdb_command_test.inp:
	Test the ignore command's documentation.

tests/debugger/breakpoints.{inp,exp}:
	Extend this test case to test ignore counts.

Zoltan.

cvs diff: Diffing .
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/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.268
diff -u -b -r1.268 user_guide.texi
--- doc/user_guide.texi	2001/08/01 15:46:34	1.268
+++ doc/user_guide.texi	2001/08/02 03:07:44
@@ -2390,7 +2390,7 @@
 @cindex Breakpoints
 @sp 1
 @table @code
- at item break [-PS] @var{filename}:@var{linenumber}
+ at item break [-PS] [-E at var{IC}] [-I at var{IC}] @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.
@@ -2400,8 +2400,16 @@
 The options @samp{-P} or @samp{--print}, and @samp{-S} or @samp{--stop}
 specify the action to be taken at the break point.
 @sp 1
-By default, the initial state of the break point is @samp{stop}.
- at item break [-AOPSaei] @var{proc-spec}
+The option @samp{-E at var{IC}} tells the debugger
+to ignore the breakpoint until after @var{IC} occurrences of a call event
+that matches the breakpoint.
+The option @samp{-I at var{IC}} tells the debugger
+to ignore the breakpoint until after @var{IC} occurrences of interface events
+that match the breakpoint.
+ at 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{IC}] [-I at var{IC}] @var{proc-spec}
 @c <module name> <predicate name> [<arity> [<mode> [<predfunc>]]]
 Puts a break point on the specified procedure.
 @sp 1
@@ -2422,21 +2430,63 @@
 @samp{-e} or @samp{--entry}, and @samp{-i} or @samp{--interface}
 specify the invocation conditions of the break point.
 @sp 1
+The option @samp{-E at var{IC}} tells the debugger
+to ignore the breakpoint until after @var{IC} occurrences of a call event
+that matches the breakpoint.
+The option @samp{-I at var{IC}} tells the debugger
+to ignore the breakpoint until after @var{IC} occurrences of interface events
+that match the breakpoint.
+ at sp 1
 By default, the action of the break point is @samp{stop},
-and its invocation condition is @samp{interface}.
+its invocation condition is @samp{interface},
+and the ignore count is zero.
 @sp 1
- at item break [-PS] here
+ at item break [-PS] [-E at var{IC}] [-I at var{IC}] 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.
 @sp 1
 The options @samp{-P} or @samp{--print}, and @samp{-S} or @samp{--stop}
 specify the action to be taken at the break point.
+ at sp 1
+The option @samp{-E at var{IC}} tells the debugger
+to ignore the breakpoint until after @var{IC} occurrences of a call event
+that matches the breakpoint.
+The option @samp{-I at var{IC}} tells the debugger
+to ignore the breakpoint until after @var{IC} occurrences of interface events
+that match the breakpoint.
 @sp 1
-By default, the initial state of the break point is @samp{stop}.
+By default, the initial state of the break point is @samp{stop},
+and the ignore count is zero.
 @sp 1
 @item break info
 Lists the details and status of all break points.
+ at sp 1
+ at item ignore [-E at var{IC}] [-I at var{IC}] @var{num}
+ at sp 1
+The option @samp{-E at var{IC}} tells the debugger
+to ignore the breakpoint until after @var{IC} occurrences of a call event
+that matches the breakpoint with the specified number.
+The option @samp{-I at var{IC}} tells the debugger
+to ignore the breakpoint until after @var{IC} occurrences of interface events
+that match the breakpoint with the specified number.
+If neither option is given,
+the default is to ignore one call event
+that matches the breakpoint with the specified number.
+Reports an error if there is no break point with the specified number.
+ at sp 1
+ at item ignore [-E at var{IC}] [-I at var{IC}]
+ at sp 1
+The option @samp{-E at var{IC}} tells the debugger
+to ignore the breakpoint until after @var{IC} occurrences of a call event
+that matches the most recently added breakpoint.
+The option @samp{-I at var{IC}} tells the debugger
+to ignore the breakpoint until after @var{IC} occurrences of interface events
+that match the most recently added breakpoint.
+If neither option is given,
+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.
 @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/graphics
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/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/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
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 java
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/mercury1/repository/tests/debugger/breakpoints.exp,v
retrieving revision 1.4
diff -u -b -r1.4 breakpoints.exp
--- tests/debugger/breakpoints.exp	2000/08/25 09:53:35	1.4
+++ tests/debugger/breakpoints.exp	2001/08/03 04:57:51
@@ -78,5 +78,21 @@
 There are no break points.
 mdb> delete *
 There are no break points.
+mdb> break -i -I3 qperm
+ 0: + stop  interface pred breakpoints:qperm/2-0 (nondet)
+            (ignore next 3 interface events)
+mdb> continue
+      50:     11  6 REDO pred breakpoints:qperm/2-0 (nondet) breakpoints.m:50 (breakpoints.m:54)
+mdb> print *
+       HeadVar__1             	[4, 5]
+mdb> ignore -E4 0
+ 0: + stop  interface pred breakpoints:qperm/2-0 (nondet)
+            (ignore next 4 call events)
+mdb> continue
+     123:     32  8 CALL pred breakpoints:qperm/2-0 (nondet) breakpoints.m:50 (breakpoints.m:54)
+mdb> print *
+       HeadVar__1             	[]
+mdb> delete *
+ 0: E stop  interface pred breakpoints:qperm/2-0 (nondet)
 mdb> continue
 [1, 3, 5, 2, 4]
Index: tests/debugger/breakpoints.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/breakpoints.inp,v
retrieving revision 1.2
diff -u -b -r1.2 breakpoints.inp
--- tests/debugger/breakpoints.inp	2000/08/25 09:53:35	1.2
+++ tests/debugger/breakpoints.inp	2001/08/03 04:40:12
@@ -28,4 +28,11 @@
 delete *
 break info
 delete *
+break -i -I3 qperm
+continue
+print *
+ignore -E4 0
+continue
+print *
+delete *
 continue
Index: tests/debugger/mdb_command_test.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/mdb_command_test.inp,v
retrieving revision 1.14
diff -u -b -r1.14 mdb_command_test.inp
--- tests/debugger/mdb_command_test.inp	2001/01/18 03:01:56	1.14
+++ tests/debugger/mdb_command_test.inp	2001/08/03 04:41:38
@@ -22,6 +22,7 @@
 current              xyzzy xyzzy xyzzy xyzzy xyzzy
 set                  xyzzy xyzzy xyzzy xyzzy xyzzy
 break                xyzzy xyzzy xyzzy xyzzy xyzzy
+ignore               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/structure_reuse
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/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_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.105
diff -u -b -r1.105 mercury_trace_internal.c
--- trace/mercury_trace_internal.c	2001/05/31 06:00:25	1.105
+++ trace/mercury_trace_internal.c	2001/08/02 14:11:57
@@ -136,6 +136,24 @@
 	"Contexts are printed on the next line.",
 };
 
+static	MR_Spy_When		MR_default_breakpoint_scope = MR_SPY_INTERFACE;
+
+static const char	*MR_scope_set_msg[] = {
+	"The default scope of `break' commands is now all matching events.",
+	"The default scope of `break' commands is now all matching interface events.",
+	"The default scope of `break' commands is now all matching entry events.",
+	"MDB INTERNAL ERROR: scope set to MR_SPY_SPECIFIC",
+	"MDB INTERNAL ERROR: scope set to MR_SPY_LINENO",
+};
+
+static const char	*MR_scope_report_msg[] = {
+	"The default scope of `break' commands is all matching events.",
+	"The default scope of `break' commands is all matching interface events.",
+	"The default scope of `break' commands is all matching entry events.",
+	"MDB INTERNAL ERROR: scope set to MR_SPY_SPECIFIC",
+	"MDB INTERNAL ERROR: scope set to MR_SPY_LINENO",
+};
+
 #ifdef	MR_USE_DECLARATIVE_DEBUGGER
 
 MR_Trace_Mode MR_trace_decl_mode = MR_TRACE_INTERACTIVE;
@@ -156,16 +174,21 @@
 static	MR_Next	MR_trace_handle_cmd(char **words, int word_count,
 			MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
 			MR_Event_Details *event_details, MR_Code **jumpaddr);
+static	void	MR_maybe_print_spy_point(int slot, const char *problem);
 static	void	MR_print_unsigned_var(FILE *fp, const char *var,
 			MR_Unsigned value);
 static	bool	MR_parse_source_locn(char *word, const char **file, int *line);
 static	bool	MR_trace_options_strict_print(MR_Trace_Cmd_Info *cmd,
 			char ***words, int *word_count,
 			const char *cat, const char *item);
-static	bool	MR_trace_options_when_action_multi(MR_Spy_When *when,
+static	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,
 			char ***words, int *word_count,
 			const char *cat, const char *item);
+static	bool	MR_trace_options_ignore_count(MR_Spy_Ignore_When *ignore_when,
+			int *ignore_count, char ***words, int *word_count,
+			const char *cat, const char *item);
 static	bool	MR_trace_options_quiet(bool *verbose, char ***words,
 			int *word_count, const char *cat, const char *item);
 static	bool	MR_trace_options_ignore(bool *ignore_errors, char ***words,
@@ -1117,9 +1140,12 @@
 		MR_Spy_When	when;
 		MR_Spy_Action	action;
 		MR_MultiMatch	multi_match;
+		MR_Spy_Ignore_When	ignore_when;
+		int			ignore_count;
 		const char	*file;
 		int		line;
 		int		breakline;
+		const char		*problem;
 
 		if (word_count == 2 && streq(words[1], "info")) {
 			int	i;
@@ -1141,21 +1167,45 @@
 			return KEEP_INTERACTING;
 		}
 
-		when = MR_SPY_INTERFACE;
+		when = MR_default_breakpoint_scope;
 		action = MR_SPY_STOP;
 		multi_match = MR_MULTIMATCH_ASK;
-		if (! MR_trace_options_when_action_multi(&when, &action,
-				&multi_match, &words, &word_count,
-				"breakpoint", "break"))
+		/* The value of ignore_when doesn't matter */
+		/* while ignore_count contains zero. */
+		ignore_when = MR_SPY_DONT_IGNORE;
+		ignore_count = 0;
+		if (! MR_trace_options_when_action_multi_ignore(&when, &action,
+				&multi_match, &ignore_when, &ignore_count,
+				&words, &word_count, "breakpoint", "break"))
 		{
 			; /* the usage message has already been printed */
 		} else if (word_count == 2 && streq(words[1], "here")) {
 			int	slot;
+			MR_Trace_Port	port;
+
+			port = event_info->MR_trace_port;
+			if (ignore_count > 0 &&
+				ignore_when == MR_SPY_IGNORE_ENTRY &&
+				! MR_port_is_entry(port))
+			{
+				fprintf(MR_mdb_out, "That breakpoint "
+					"would never become enabled.\n");
+				return KEEP_INTERACTING;
+			} else if (ignore_count > 0 &&
+				ignore_when == MR_SPY_IGNORE_INTERFACE &&
+				! MR_port_is_interface(port))
+			{
+				fprintf(MR_mdb_out, "That breakpoint "
+					"would never become enabled.\n");
+				return KEEP_INTERACTING;
+			}
 
 			MR_register_all_modules_and_procs(MR_mdb_out, TRUE);
 			slot = MR_add_proc_spy_point(MR_SPY_SPECIFIC, action,
-					layout->MR_sll_entry, layout);
-			MR_print_spy_point(MR_mdb_out, slot);
+					ignore_when, ignore_count,
+					layout->MR_sll_entry, layout,
+					&problem);
+			MR_maybe_print_spy_point(slot, problem);
 		} else if (word_count == 2 &&
 				MR_parse_proc_spec(words[1], &spec))
 		{
@@ -1170,17 +1220,21 @@
 					"mdb: there is no such procedure.\n");
 			} else if (matches.match_proc_next == 1) {
 				slot = MR_add_proc_spy_point(when, action,
-					matches.match_procs[0], NULL);
-				MR_print_spy_point(MR_mdb_out, slot);
+					ignore_when, ignore_count,
+					matches.match_procs[0], NULL,
+					&problem);
+				MR_maybe_print_spy_point(slot, problem);
 			} else if (multi_match == MR_MULTIMATCH_ALL) {
 				int	i;
 
 				for (i = 0; i < matches.match_proc_next; i++) {
 					slot = MR_add_proc_spy_point(
 						when, action,
-						matches.match_procs[i],
-						NULL);
-					MR_print_spy_point(MR_mdb_out, slot);
+						ignore_when, ignore_count,
+						matches.match_procs[i], NULL,
+						&problem);
+					MR_maybe_print_spy_point(slot,
+						problem);
 				}
 			} else {
 				char	buf[80];
@@ -1218,10 +1272,12 @@
 					{
 						slot = MR_add_proc_spy_point(
 							when, action,
+							ignore_when,
+							ignore_count,
 							matches.match_procs[i],
-							NULL);
-						MR_print_spy_point(MR_mdb_out,
-							slot);
+							NULL, &problem);
+						MR_maybe_print_spy_point(
+							slot, problem);
 					}
 
 					MR_free(line2);
@@ -1231,10 +1287,12 @@
 					{
 						slot = MR_add_proc_spy_point(
 							when, action,
+							ignore_when,
+							ignore_count,
 							matches.match_procs[i],
-							NULL);
-						MR_print_spy_point(MR_mdb_out,
-							slot);
+							NULL, &problem);
+						MR_maybe_print_spy_point(
+							slot, problem);
 					} else {
 						fprintf(MR_mdb_out,
 							"no such match\n");
@@ -1250,37 +1308,86 @@
 		{
 			int	slot;
 
-			slot = MR_add_line_spy_point(action, file, line);
-			if (slot >= 0) {
-				MR_print_spy_point(MR_mdb_out, slot);
-			} else {
-				fflush(MR_mdb_out);
-				fprintf(MR_mdb_err,
-					"mdb: there is no event at %s:%d.\n",
-					file, line);
-			}
+			slot = MR_add_line_spy_point(action, ignore_when,
+				ignore_count, file, line, &problem);
+			MR_maybe_print_spy_point(slot, problem);
 		} else if (word_count == 2 &&
 				MR_trace_is_number(words[1], &breakline))
 		{
 			int	slot;
 
 			if (MR_find_context(layout, &file, &line)) {
-				slot = MR_add_line_spy_point(action, file,
-					breakline);
-				if (slot >= 0) {
-					MR_print_spy_point(MR_mdb_out, slot);
+				slot = MR_add_line_spy_point(action,
+					ignore_when, ignore_count,
+					file, breakline, &problem);
+				MR_maybe_print_spy_point(slot, problem);
 				} else {
+				MR_fatal_error("cannot find current filename");
+			}
+		} else {
+			MR_trace_usage("breakpoint", "break");
+		}
+	} else if (streq(words[0], "ignore")) {
+		int			n;
+		MR_Spy_Ignore_When	ignore_when;
+		int			ignore_count;
+		const char		*problem;
+
+		ignore_when = MR_SPY_IGNORE_ENTRY;
+		ignore_count = 1;
+		if (! MR_trace_options_ignore_count(&ignore_when, &ignore_count,
+				&words, &word_count, "breakpoint", "ignore"))
+		{
+			; /* the usage message has already been printed */
+		} else if (word_count == 2 && MR_trace_is_number(words[1], &n))
+		{
+			if (0 <= n && n < MR_spy_point_next
+					&& MR_spy_points[n]->spy_exists)
+			{
+				problem = MR_ignore_spy_point(n, ignore_when,
+					ignore_count);
+				MR_maybe_print_spy_point(n, problem);
+			} else {
 					fflush(MR_mdb_out);
+				fprintf(MR_mdb_err, "mdb: break point #%d "
+					"does not exist.\n",
+					n);
+			}
+		} else if (word_count == 2 && streq(words[1], "*")) {
+			int	i;
+			int	count;
+
+			count = 0;
+			for (i = 0; i < MR_spy_point_next; i++) {
+				if (MR_spy_points[i]->spy_exists) {
+					problem = MR_ignore_spy_point(n,
+						ignore_when, ignore_count);
+					MR_maybe_print_spy_point(n, problem);
+					count++;
+				}
+			}
+
+			if (count == 0) {
 					fprintf(MR_mdb_err,
-						"mdb: there is no event "
-						"at %s:%d.\n",
-						file, breakline);
+					"There are no break points.\n");
 				}
+		} else if (word_count == 1) {
+			if (0 <= MR_most_recent_spy_point
+				&& MR_most_recent_spy_point < MR_spy_point_next
+				&& MR_spy_points[MR_most_recent_spy_point]->
+					spy_exists)
+			{
+				n = MR_most_recent_spy_point;
+				problem = MR_ignore_spy_point(n, ignore_when,
+					ignore_count);
+				MR_maybe_print_spy_point(n, problem);
 			} else {
-				MR_fatal_error("cannot find current filename");
+				fflush(MR_mdb_out);
+				fprintf(MR_mdb_err, "mdb: there is no "
+					"most recent break point.\n");
 			}
 		} else {
-			MR_trace_usage("breakpoint", "break");
+			MR_trace_usage("breakpoint", "ignore");
 		}
 	} else if (streq(words[0], "enable")) {
 		int	n;
@@ -1618,6 +1725,41 @@
 		} else {
 			MR_trace_usage("parameter", "context");
 		}
+	} else if (streq(words[0], "scope")) {
+		if (word_count == 2) {
+			if (streq(words[1], "all")) {
+				MR_default_breakpoint_scope = MR_SPY_ALL;
+			} else if (streq(words[1], "interface")) {
+				MR_default_breakpoint_scope = MR_SPY_INTERFACE;
+			} else if (streq(words[1], "entry")) {
+				MR_default_breakpoint_scope = MR_SPY_ENTRY;
+			} else {
+				MR_trace_usage("parameter", "scope");
+				return KEEP_INTERACTING;
+			}
+
+			if (MR_trace_internal_interacting) {
+				fprintf(MR_mdb_out, "%s\n",
+					MR_scope_set_msg[
+						MR_default_breakpoint_scope]);
+			}
+		} else if (word_count == 1) {
+			switch (MR_default_breakpoint_scope) {
+			case MR_SPY_ALL:
+			case MR_SPY_INTERFACE:
+			case MR_SPY_ENTRY:
+				fprintf(MR_mdb_out, "%s\n",
+					MR_scope_report_msg[
+						MR_default_breakpoint_scope]);
+				break;
+
+			default:
+				MR_fatal_error(
+					"invalid MR_default_breakpoint_scope");
+			}
+		} else {
+			MR_trace_usage("parameter", "scope");
+		}
 	} else if (streq(words[0], "echo")) {
 		if (word_count == 2) {
 			if (streq(words[1], "off")) {
@@ -2018,6 +2160,24 @@
 			MR_trace_print_all_aliases(fp, TRUE);
 			found_error = MR_save_spy_points(fp, MR_mdb_err);
 
+			switch (MR_default_breakpoint_scope) {
+				case MR_SPY_ALL:
+					fprintf(fp, "scope all\n");
+					break;
+
+				case MR_SPY_INTERFACE:
+					fprintf(fp, "scope interface\n");
+					break;
+
+				case MR_SPY_ENTRY:
+					fprintf(fp, "scope entry\n");
+					break;
+
+				default:
+					MR_fatal_error("save cmd: "
+						"invalid default scope");
+			}
+
 			if (found_error) {
 				fflush(MR_mdb_out);
 				fprintf(MR_mdb_err, "mdb: could not save "
@@ -2127,6 +2287,17 @@
 }
 
 static void
+MR_maybe_print_spy_point(int slot, const char *problem)
+{
+	if (slot < 0) {
+		fflush(MR_mdb_out);
+		fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+	} else {
+		MR_print_spy_point(MR_mdb_out, slot);
+	}
+}
+
+static void
 MR_print_unsigned_var(FILE *fp, const char *var, MR_Unsigned value)
 {
 	fprintf(fp, "%s = %" MR_INTEGER_LENGTH_MODIFIER "u\n", var, value);
@@ -2156,12 +2327,12 @@
 
 static struct MR_option MR_trace_strict_print_opts[] =
 {
-	{ "all",	FALSE,	NULL,	'a' },
-	{ "none",	FALSE,	NULL,	'n' },
-	{ "some",	FALSE,	NULL,	's' },
-	{ "nostrict",	FALSE,	NULL,	'N' },
-	{ "strict",	FALSE,	NULL,	'S' },
-	{ NULL,		FALSE,	NULL,	0 }
+	{ "all",	MR_no_argument,	NULL,	'a' },
+	{ "none",	MR_no_argument,	NULL,	'n' },
+	{ "some",	MR_no_argument,	NULL,	's' },
+	{ "nostrict",	MR_no_argument,	NULL,	'N' },
+	{ "strict",	MR_no_argument,	NULL,	'S' },
+	{ NULL,		MR_no_argument,	NULL,	0 }
 };
 
 static bool
@@ -2207,28 +2378,31 @@
 	return TRUE;
 }
 
-static struct MR_option MR_trace_when_action_multi_opts[] =
+static struct MR_option MR_trace_when_action_multi_ignore_opts[] =
 {
-	{ "all",	FALSE,	NULL,	'a' },
-	{ "entry",	FALSE,	NULL,	'e' },
-	{ "interface",	FALSE,	NULL,	'i' },
-	{ "print",	FALSE,	NULL,	'P' },
-	{ "stop",	FALSE,	NULL,	'S' },
-	{ "select-all",	FALSE,	NULL,	'A' },
-	{ "select-one",	FALSE,	NULL,	'O' },
-	{ NULL,		FALSE,	NULL,	0 }
+	{ "all",		MR_no_argument,		NULL,	'a' },
+	{ "entry",		MR_no_argument,		NULL,	'e' },
+	{ "interface",		MR_no_argument,		NULL,	'i' },
+	{ "ignore-entry",	MR_required_argument,	NULL,	'E' },
+	{ "ignore-interface",	MR_required_argument,	NULL,	'I' },
+	{ "print",		MR_no_argument,		NULL,	'P' },
+	{ "stop",		MR_no_argument,		NULL,	'S' },
+	{ "select-all",		MR_no_argument,		NULL,	'A' },
+	{ "select-one",		MR_no_argument,		NULL,	'O' },
+	{ NULL,			MR_no_argument,		NULL,	0 }
 };
 
 static bool
-MR_trace_options_when_action_multi(MR_Spy_When *when, MR_Spy_Action *action,
-	MR_MultiMatch *multi_match, char ***words, int *word_count,
-	const char *cat, const char *item)
+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,
+	char ***words, int *word_count, const char *cat, const char *item)
 {
 	int	c;
 
 	MR_optind = 0;
-	while ((c = MR_getopt_long(*word_count, *words, "AOPSaei",
-			MR_trace_when_action_multi_opts, NULL)) != EOF)
+	while ((c = MR_getopt_long(*word_count, *words, "AE:I:OPSaei",
+			MR_trace_when_action_multi_ignore_opts, NULL)) != EOF)
 	{
 		switch (c) {
 
@@ -2244,6 +2418,24 @@
 				*when = MR_SPY_INTERFACE;
 				break;
 
+			case 'E':
+				if (sscanf(MR_optarg, "%d", ignore_count) != 1)
+				{
+					MR_trace_usage(cat, item);
+					return FALSE;
+				}
+				*ignore_when = MR_SPY_IGNORE_ENTRY;
+				break;
+
+			case 'I':
+				if (sscanf(MR_optarg, "%d", ignore_count) != 1)
+				{
+					MR_trace_usage(cat, item);
+					return FALSE;
+				}
+				*ignore_when = MR_SPY_IGNORE_INTERFACE;
+				break;
+
 			case 'A':
 				*multi_match = MR_MULTIMATCH_ALL;
 				break;
@@ -2271,10 +2463,59 @@
 	return TRUE;
 }
 
+static struct MR_option MR_trace_ignore_count_opts[] =
+{
+	{ "ignore-entry",	MR_required_argument,	NULL,	'E' },
+	{ "ignore-interface",	MR_required_argument,	NULL,	'I' },
+	{ NULL,			MR_no_argument,		NULL,	0 }
+};
+
+static bool
+MR_trace_options_ignore_count(MR_Spy_Ignore_When*ignore_when,
+	int *ignore_count, char ***words, int *word_count,
+	const char *cat, const char *item)
+{
+	int	c;
+
+	MR_optind = 0;
+	while ((c = MR_getopt_long(*word_count, *words, "E:I:",
+			MR_trace_ignore_count_opts, NULL)) != EOF)
+	{
+		switch (c) {
+
+			case 'E':
+				if (sscanf(MR_optarg, "%d", ignore_count) != 1)
+				{
+					MR_trace_usage(cat, item);
+					return FALSE;
+				}
+				*ignore_when = MR_SPY_IGNORE_ENTRY;
+				break;
+
+			case 'I':
+				if (sscanf(MR_optarg, "%d", ignore_count) != 1)
+				{
+					MR_trace_usage(cat, item);
+					return FALSE;
+				}
+				*ignore_when = MR_SPY_IGNORE_INTERFACE;
+				break;
+
+			default:
+				MR_trace_usage(cat, item);
+				return FALSE;
+		}
+	}
+
+	*words = *words + MR_optind - 1;
+	*word_count = *word_count - MR_optind + 1;
+	return TRUE;
+}
+
 static struct MR_option MR_trace_detailed_opts[] =
 {
-	{ "detailed",	FALSE,	NULL,	'd' },
-	{ NULL,		FALSE,	NULL,	0 }
+	{ "detailed",	MR_no_argument,	NULL,	'd' },
+	{ NULL,		MR_no_argument,	NULL,	0 }
 };
 
 static bool
@@ -2337,9 +2578,9 @@
 
 static struct MR_option MR_trace_quiet_opts[] =
 {
-	{ "quiet",	FALSE,	NULL,	'q' },
-	{ "verbose",	FALSE,	NULL,	'v' },
-	{ NULL,		FALSE,	NULL,	0 }
+	{ "quiet",	MR_no_argument,	NULL,	'q' },
+	{ "verbose",	MR_no_argument,	NULL,	'v' },
+	{ NULL,		MR_no_argument,	NULL,	0 }
 };
 
 static bool
@@ -2375,8 +2616,8 @@
 
 static struct MR_option MR_trace_ignore_opts[] =
 {
-	{ "ignore-errors",	FALSE,	NULL,	'i' },
-	{ NULL,			FALSE,	NULL,	0 }
+	{ "ignore-errors",	MR_no_argument,	NULL,	'i' },
+	{ NULL,			MR_no_argument,	NULL,	0 }
 };
 
 static bool
@@ -2408,11 +2649,11 @@
 
 static struct MR_option MR_trace_format_opts[] = 
 {
-	{ "flat",	FALSE,	NULL,	'f' },
-	{ "raw_pretty",	FALSE,	NULL,	'r' },
-	{ "verbose",	FALSE,	NULL,	'v' },
-	{ "pretty",	FALSE,	NULL,	'p' },
-	{ NULL,		FALSE,	NULL,	0 }
+	{ "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 bool
@@ -2457,14 +2698,14 @@
 
 static struct MR_option MR_trace_param_set_opts[] = 
 {
-	{ "flat",	FALSE,	NULL,	'f' },
-	{ "raw_pretty",	FALSE,	NULL,	'r' },
-	{ "verbose",	FALSE,	NULL,	'v' },
-	{ "pretty",	FALSE,	NULL,	'p' },	
-	{ "print",	FALSE,	NULL,	'P' },
-	{ "browse",	FALSE,	NULL,	'B' },
-	{ "print-all",	FALSE,	NULL,	'A' },
-	{ NULL,		FALSE,	NULL,	0 }
+	{ "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' },	
+	{ "print",	MR_no_argument,	NULL,	'P' },
+	{ "browse",	MR_no_argument,	NULL,	'B' },
+	{ "print-all",	MR_no_argument,	NULL,	'A' },
+	{ NULL,		MR_no_argument,	NULL,	0 }
 };
 
 static bool
@@ -3084,6 +3325,7 @@
 	{ "browsing", "current" },
 	{ "browsing", "set" },
 	{ "breakpoint", "break" },
+	{ "breakpoint", "ignore" },
 	{ "breakpoint", "enable" },
 	{ "breakpoint", "disable" },
 	{ "breakpoint", "delete" },
@@ -3095,6 +3337,7 @@
 	{ "parameter", "echo" },
 	{ "parameter", "scroll" },
 	{ "parameter", "context" },
+	{ "parameter", "scope" },
 	{ "parameter", "alias" },
 	{ "parameter", "unalias" },
 	{ "help", "document_category" },
Index: trace/mercury_trace_spy.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_spy.c,v
retrieving revision 1.17
diff -u -b -r1.17 mercury_trace_spy.c
--- trace/mercury_trace_spy.c	2001/01/18 01:19:16	1.17
+++ trace/mercury_trace_spy.c	2001/08/03 04:53:51
@@ -92,6 +92,10 @@
 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_update_enabled_action(MR_Spy_Point *point,
+			MR_Trace_Port port, MR_Spy_Action *action_ptr,
+			bool *enabled_ptr);
+static	const char *MR_ignore_when_to_string(MR_Spy_Ignore_When ignore_when);
 
 /*
 ** Compare two addresses, and return an integer which is <0, 0, or >0
@@ -179,17 +183,13 @@
 		if (slot >= 0) {
 			point = MR_spy_points[
 				MR_spied_labels[slot].spy_point_num];
-			if (point->spy_enabled) {
 				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");
 				}
 
-				enabled = TRUE;
-				action = max(action,
-					point->spy_action);
-			}
+			MR_update_enabled_action(point, port,
+				&action, &enabled);
 		}
 
 		if (MR_port_is_interface(port)) {
@@ -203,42 +203,36 @@
 			{
 				point = MR_spy_points[MR_spied_labels[slot].
 					spy_point_num];
-				if (point->spy_enabled) {
 					if (point->spy_when != MR_SPY_LINENO) {
 						MR_fatal_error("non-lineno "
 							"spy point in "
 							"spied labels array");
 					}
 
-					enabled = TRUE;
-					action = max(action,
-						point->spy_action);
+				MR_update_enabled_action(point, port,
+					&action, &enabled);
 				}
 			}
 		}
-	}
 
 	slot = MR_search_spy_table_for_proc(layout->MR_sll_entry);
 	if (slot >= 0) {
 		for (point = MR_spied_procs[slot].spy_points; point != NULL;
-				point = point->spy_next) {
-			if (! point->spy_enabled) {
-				continue;
-			}
-
+				point = point->spy_next)
+		{
 			switch (point->spy_when) {
 
 				case MR_SPY_ALL:
-					enabled = TRUE;
-					action = max(action,
-						point->spy_action);
+					MR_update_enabled_action(point,
+						port, &action,
+						&enabled);
 				break;
 
 				case MR_SPY_ENTRY:
 					if (MR_port_is_entry(port)) {
-						enabled = TRUE;
-						action = max(action,
-							point->spy_action);
+						MR_update_enabled_action(point,
+							port, &action,
+							&enabled);
 					} else {
 						continue;
 					}
@@ -247,9 +241,9 @@
 
 				case MR_SPY_INTERFACE:
 					if (MR_port_is_interface(port)) {
-						enabled = TRUE;
-						action = max(action,
-							point->spy_action);
+						MR_update_enabled_action(point,
+							port, &action,
+							&enabled);
 					} else {
 						continue;
 					}
@@ -258,9 +252,9 @@
 
 				case MR_SPY_SPECIFIC:
 					if (layout == point->spy_label) {
-						enabled = TRUE;
-						action = max(action,
-							point->spy_action);
+						MR_update_enabled_action(point,
+							port, &action,
+							&enabled);
 					} else {
 						continue;
 					}
@@ -286,15 +280,57 @@
 	}
 }
 
+static void
+MR_update_enabled_action(MR_Spy_Point *point, MR_Trace_Port port,
+	MR_Spy_Action *action_ptr, bool *enabled_ptr)
+{
+	if (point->spy_enabled) {
+		if (point->spy_ignore_count == 0) {
+			*enabled_ptr = TRUE;
+			*action_ptr = max(*action_ptr, point->spy_action);
+		}
+
+		if (point->spy_ignore_count > 0) {
+			switch (point->spy_ignore_when) {
+			case MR_SPY_DONT_IGNORE:
+				break;
+
+			case MR_SPY_IGNORE_ENTRY:
+				if (port == MR_PORT_CALL) {
+					--point->spy_ignore_count;
+				}
+				break;
+
+			case MR_SPY_IGNORE_INTERFACE:
+				if (MR_port_is_interface(port)) {
+					--point->spy_ignore_count;
+				}
+				break;
+
+			default:
+				MR_fatal_error("MR_update_enabled_action: "
+					"invalid ignore_when");
+			}
+		}
+	}
+}
+
+static const char *incompatible =
+	"Ignore count is not compatible with break point specification";
+
 int
 MR_add_proc_spy_point(MR_Spy_When when, MR_Spy_Action action,
-	const MR_Proc_Layout *entry, const MR_Label_Layout *label)
+	MR_Spy_Ignore_When ignore_when, int ignore_count,
+	const MR_Proc_Layout *entry, const MR_Label_Layout *label,
+	const char **problem)
 {
 	MR_Spy_Point	*point;
 	int		point_slot;
 	int		proc_slot;
 	int		i;
 
+	*problem = NULL;
+
 	proc_slot = MR_search_spy_table_for_proc(entry);
 	if (proc_slot < 0) {
 		MR_ensure_room_for_next(MR_spied_proc, MR_Spied_Proc,
@@ -313,6 +349,8 @@
 	point->spy_exists  = TRUE;
 	point->spy_enabled = TRUE;
 	point->spy_action  = action;
+	point->spy_ignore_when  = ignore_when;
+	point->spy_ignore_count = ignore_count;
 	point->spy_proc    = entry;
 	point->spy_label   = label;
 	point->spy_next    = MR_spied_procs[proc_slot].spy_points;
@@ -336,14 +374,21 @@
 }
 
 int
-MR_add_line_spy_point(MR_Spy_Action action,
-	const char *orig_filename, int linenumber)
+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_Point	*point;
 	int		point_slot;
 	int		old_size, new_size;
 	char 		*filename;
 
+	*problem = NULL;
+	if (ignore_when != MR_SPY_DONT_IGNORE) {
+		*problem = incompatible;
+		return -1;
+	}
+
 	/*
 	** The original filename string may have come from a buffer
 	** or other volatile storage.
@@ -360,6 +405,11 @@
 
 	if (new_size == old_size) {
 		/* there were no matching labels */
+		char	buf[1024];	/* this should be big enough ... */
+
+		snprintf(buf, 1024, "there is no event at %s:%d",
+			filename, linenumber);
+		*problem = buf;
 		return -1;
 	}
 
@@ -376,6 +426,8 @@
 	point->spy_exists     = TRUE;
 	point->spy_enabled    = TRUE;
 	point->spy_action     = action;
+	point->spy_ignore_when  = ignore_when;
+	point->spy_ignore_count = ignore_count;
 	point->spy_filename   = filename;
 	point->spy_linenumber = linenumber;
 
@@ -413,6 +465,31 @@
 		- (MR_Integer) label2->spy_label);
 }
 
+const char *
+MR_ignore_spy_point(int point_slot, MR_Spy_Ignore_When ignore_when,
+	int ignore_count)
+{
+	switch (MR_spy_points[point_slot]->spy_when) {
+		case MR_SPY_ENTRY:
+		case MR_SPY_INTERFACE:
+		case MR_SPY_ALL:
+			break;
+
+		case MR_SPY_SPECIFIC:
+		case MR_SPY_LINENO:
+			return incompatible;
+			break;
+
+		default:
+			MR_fatal_error("MR_add_proc_spy_point: bad when");
+			break;
+	}
+
+	MR_spy_points[point_slot]->spy_ignore_when  = ignore_when;
+	MR_spy_points[point_slot]->spy_ignore_count = ignore_count;
+	return NULL;
+}
+
 void
 MR_delete_spy_point(int point_table_slot)
 {
@@ -493,14 +570,39 @@
 		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\n",
+		fprintf(fp, "%s:%d",
 			point->spy_filename, point->spy_linenumber);
 	} else {
 		MR_print_proc_id(fp, point->spy_proc);
+	}
+
+	if (point->spy_ignore_count > 1) {
+		fprintf(fp, "\n%12s(ignore next %d %s events)\n",
+			"", point->spy_ignore_count,
+			MR_ignore_when_to_string(point->spy_ignore_when));
+	} else if (point->spy_ignore_count > 0) {
+		fprintf(fp, "\n%12s(ignore next %s event)\n",
+			"", MR_ignore_when_to_string(point->spy_ignore_when));
+	} else {
 		fprintf(fp, "\n");
 	}
 }
 
+static const char *
+MR_ignore_when_to_string(MR_Spy_Ignore_When ignore_when)
+{
+	switch (ignore_when) {
+		case MR_SPY_IGNORE_ENTRY:
+			return "call";
+
+		case MR_SPY_IGNORE_INTERFACE:
+			return "interface";
+
+		default:
+			MR_fatal_error("MR_ignore_when_to_string: invalid ignore_when");
+	}
+}
+
 bool
 MR_save_spy_points(FILE *fp, FILE *err_fp)
 {
@@ -527,6 +629,24 @@
 				fprintf(err_fp, "internal error: "
 					"unknown spy action\n");
 				return TRUE;
+		}
+
+		if (point->spy_ignore_count > 0) {
+			switch (point->spy_ignore_when) {
+				case MR_SPY_IGNORE_INTERFACE:
+					fprintf(fp, " -I%d",
+						point->spy_ignore_count);
+					break;
+
+				case MR_SPY_IGNORE_ENTRY:
+					fprintf(fp, " -E%d",
+						point->spy_ignore_count);
+					break;
+
+				default:
+					MR_fatal_error("MR_save_spy_points: "
+						"invalid ignore_when");
+			}
 		}
 
 		switch (point->spy_when) {
Index: trace/mercury_trace_spy.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_spy.h,v
retrieving revision 1.7
diff -u -b -r1.7 mercury_trace_spy.h
--- trace/mercury_trace_spy.h	2001/02/13 08:28:27	1.7
+++ trace/mercury_trace_spy.h	2001/08/02 14:16:05
@@ -33,6 +33,12 @@
 	MR_SPY_LINENO
 } MR_Spy_When;
 
+typedef enum {
+	MR_SPY_DONT_IGNORE,
+	MR_SPY_IGNORE_INTERFACE,
+	MR_SPY_IGNORE_ENTRY
+} MR_Spy_Ignore_When;
+
 extern	const char	*MR_spy_when_names[];
 
 typedef struct MR_Spy_Point_Struct MR_Spy_Point;
@@ -42,6 +48,8 @@
 	bool			spy_enabled;
 	MR_Spy_When		spy_when;
 	MR_Spy_Action		spy_action;
+	MR_Spy_Ignore_When	spy_ignore_when;
+	int			spy_ignore_count;
 	const MR_Proc_Layout	*spy_proc;      /* if not LINENO */
 	const MR_Label_Layout	*spy_label;	/* if SPECIFIC */
 	char			*spy_filename;  /* if LINENO */
@@ -72,21 +80,39 @@
 
 /*
 ** Add a new spy point on a procedure (as opposed to on a line number)
-** to the table.
+** to the table. If this cannot be done, return a negative number and set
+** *problem to point to an error message.
 */
 
 extern	int		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);
+				const MR_Label_Layout *label,
+				const char **problem);
 
 /*
 ** Add a new spy point on a line number (as opposed to on a procedure)
-** to the table.
+** to the table. If this cannot be done, return a negative number and set
+** *problem to point to an error message.
 */
 
 extern	int		MR_add_line_spy_point(MR_Spy_Action action,
-				const char *filename, int linenumber);
+				MR_Spy_Ignore_When ignore_when,
+				int ignore_count,
+				const char *filename, int linenumber,
+				const char **problem);
+
+/*
+** 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.
+*/
+
+extern	const char 	*MR_ignore_spy_point(int point_slot,
+				MR_Spy_Ignore_When ignore_when,
+				int ignore_count);
 
 /*
 ** Delete a spy point from the table.
cvs diff: Diffing util
--------------------------------------------------------------------------
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