[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