[m-rev.] for review: conditional breakpoints
Zoltan Somogyi
zs at cs.mu.OZ.AU
Mon Jan 31 12:34:00 AEDT 2005
This is for both branches.
Zoltan.
Implement a new mdb command, "condition", which associates a condition with
an existing breakpoint. The condition is a match between a variable live at
the breakpoint, or a part thereof, and a term provided as part of the condition
command. If execution arrives at the breakpoint but the match doesn't have the
required outcome, execution will continue without stopping.
NEWS:
Mention the new capability.
doc/user_guide.texi:
Document the new capability.
runtime/mercury_trace_term.[ch]:
This new module has facilities for converting strings to a structured
representation of terms. The debugger uses this representation for the
term being matched.
runtime/Mmakefile:
Add the new module to the list of modules in the runtime library.
browser/cterm.m:
This new module tests whether a value in the program being debugged
matches a term represented by the data structure defiend in
mercury_trace_term.
browser/mdb.m:
Include the new module in the browser library.
trace/mercury_trace_spy.[ch]:
Change the code that checks for breakpoints to check breakpoints'
conditions.
Fix an old bug: set the number of the most recent breakpoint
even when reusing an existing slot.
trace/mercury_trace_vars.c:
Change the code that checks for breakpoints to also evaluate the
condition, if any.
Provide the facilities required to implement conditions. Besides
exporting some previously private functions, this involved breaking up
two existing functions into two pieces each, because condition checking
wanted to reuse only parts of them.
Modify the implementation of the functions manipulating breakpoints
to handle the new parts of spy point structures.
Modify the way we delete spy point structures to make doubly sure
that we don't free memory twice; it is now MR_delete_spy_point that
sets te spy_exists field to FALSE, after checking it.
Give more meaningful names to some variables.
trace/mercury_trace_internal.[ch]:
Implement the condition command.
Conform to the changes in mercury_trace_vars.c
When the condition of a breakpoint cannot be evaluated, print an error
message.
Extend the command parser to support double quotes, since this is now
needed to allow strings in terms in the condition command.
Flush any error messages resulting from an mdb command immediately
after the command. This was useful in debugging the change.
tests/debugger/cond.{m,inp,exp*}:
Add this new test case to test the new capability.
tests/debugger/Mmakefile:
Include the new test case in the list of test cases.
tests/debugger/completion.exp:
tests/debugger/mdb_command_test.inp:
Update to reflect the new command.
tests/debugger/cmd_quote.exp:
Update the error message.
cvs diff: Diffing .
Index: NEWS
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/NEWS,v
retrieving revision 1.370
diff -u -b -r1.370 NEWS
--- NEWS 27 Jan 2005 06:17:31 -0000 1.370
+++ NEWS 31 Jan 2005 01:12:48 -0000
@@ -54,10 +54,12 @@
* Shared libraries now work on Mac OS X.
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 arrange to associate a condition with a breakpoint.
+ Execution won't stop at the breakpoint if the condition is false.
+* Users can now limit the output from stack traces.
+* Users can now put breakpoints on unify and compare predicates.
* Users can now save runtime values to files.
* Users can now tell the declarative debugger to trust entire modules or
individual predicates or functions.
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
Index: browser/cterm.m
===================================================================
RCS file: browser/cterm.m
diff -N browser/cterm.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ browser/cterm.m 30 Jan 2005 17:32:52 -0000
@@ -0,0 +1,138 @@
+%---------------------------------------------------------------------------%
+% Copyright (C) 2005 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.
+%---------------------------------------------------------------------------%
+
+:- module mdb.cterm.
+
+:- interface.
+
+:- import_module bool.
+
+:- type cterm.
+:- type cargs.
+
+ % Succeed if and only if the given term matches the given cterm.
+ %
+:- pred match_with_cterm(T::in, cterm::in, bool::out) is cc_multi.
+
+ % Implement deconstruct for cterms.
+ %
+:- pred cterm_deconstruct(cterm::in, string::out, cargs::out) is det.
+
+ % Decompose a list of arguments into the first element and the rest.
+ % Fail if the list is empty.
+ %
+:- pred cterm_head_tail(cargs::in, cterm::out, cargs::out) is semidet.
+
+:- implementation.
+
+:- import_module list.
+:- import_module deconstruct.
+:- import_module std_util.
+
+:- pragma foreign_decl(c, "
+#include ""mercury_trace_term.h""
+").
+
+:- pragma foreign_type(c, cterm, "MR_CTerm", [can_pass_as_mercury_type]).
+:- pragma foreign_type(c, cargs, "MR_CArgs", [can_pass_as_mercury_type]).
+
+:- pragma export(match_with_cterm(in, in, out), "ML_BROWSE_match_with_cterm").
+
+% Uncomment these and the unsafe_perform_ios below to debug match_with_cterm
+% and its callers in the trace directory.
+% :- import_module io, unsafe.
+% :- pragma promise_pure(match_with_cterm/3).
+
+match_with_cterm(Term, CTerm, Match) :-
+ deconstruct(Term, include_details_cc, TermFunctor, _, TermArgs),
+ cterm_deconstruct(CTerm, CTermFunctor, CTermArgs),
+ % impure unsafe_perform_io(io__write_string("comparing <")),
+ % impure unsafe_perform_io(io__write_string(TermFunctor)),
+ % impure unsafe_perform_io(io__write_string("> to <")),
+ % impure unsafe_perform_io(io__write_string(CTermFunctor)),
+ % impure unsafe_perform_io(io__write_string(">\n")),
+ ( TermFunctor = CTermFunctor ->
+ match_with_cterms(TermArgs, CTermArgs, Match)
+ ; CTermFunctor = "_" ->
+ Match = yes
+ ;
+ Match = no
+ ).
+
+:- pred match_with_cterms(list(univ)::in, cargs::in, bool::out) is cc_multi.
+
+match_with_cterms(UnivArgs, CArgs, Match) :-
+ ( cterm_head_tail(CArgs, CHead, CTail) ->
+ ( UnivArgs = [UnivHead | UnivTail] ->
+ Head = univ_value(UnivHead),
+ match_with_cterm(Head, CHead, MatchHead),
+ (
+ MatchHead = no,
+ Match = no
+ ;
+ MatchHead = yes,
+ match_with_cterms(UnivTail, CTail, Match)
+ )
+ ;
+ Match = no
+ )
+ ;
+ ( UnivArgs = [] ->
+ Match = yes
+ ;
+ Match = no
+ )
+ ).
+
+:- pragma foreign_proc(c,
+ cterm_deconstruct(Term::in, Functor::out, Args::out),
+ [will_not_call_mercury, promise_pure],
+"
+ if (Term == NULL) {
+ MR_fatal_error(""cterm_deconstruct: NULL term"");
+ }
+
+ Functor = Term->term_functor;
+ Args = Term->term_args;
+").
+
+:- pragma foreign_proc(c,
+ cterm_head_tail(Args::in, Head::out, Tail::out),
+ [will_not_call_mercury, promise_pure],
+"
+ if (Args == NULL) {
+ SUCCESS_INDICATOR = MR_FALSE;
+ } else {
+ Head = Args->args_head;
+ Tail = Args->args_tail;
+ SUCCESS_INDICATOR = MR_TRUE;
+ }
+").
+
+:- pragma foreign_proc(c,
+ cterm_deconstruct(Term::in, Functor::out, Args::out),
+ [will_not_call_mercury, promise_pure],
+"
+ if (Term == NULL) {
+ MR_fatal_error(""cterm_deconstruct: NULL term"");
+ }
+
+ Functor = Term->term_functor;
+ Args = Term->term_args;
+").
+
+:- pragma foreign_proc(c,
+ cterm_head_tail(Args::in, Head::out, Tail::out),
+ [will_not_call_mercury, promise_pure],
+"
+ if (Args == NULL) {
+ SUCCESS_INDICATOR = MR_FALSE;
+ } else {
+ Head = Args->args_head;
+ Tail = Args->args_tail;
+ SUCCESS_INDICATOR = MR_TRUE;
+ }
+").
Index: browser/mdb.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/browser/mdb.m,v
retrieving revision 1.17
diff -u -b -r1.17 mdb.m
--- browser/mdb.m 24 Jan 2005 07:41:04 -0000 1.17
+++ browser/mdb.m 29 Jan 2005 10:34:14 -0000
@@ -18,6 +18,7 @@
:- include_module browser_info.
:- include_module browser_term.
:- include_module collect_lib.
+:- include_module cterm.
:- include_module debugger_interface.
:- include_module declarative_debugger.
:- include_module declarative_execution.
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.414
diff -u -b -r1.414 user_guide.texi
--- doc/user_guide.texi 28 Jan 2005 02:59:10 -0000 1.414
+++ doc/user_guide.texi 31 Jan 2005 01:15:10 -0000
@@ -3022,8 +3022,43 @@
@item break info
Lists the details, status and print lists of all break points.
@sp 1
- at item ignore [-E at var{ignore-count}] [-I at var{ignore-count}] @var{num}
+ at item condition [-n at var{break-num}] [-p] [-v] @var{varname}[@var{pathspec}] @var{op} @var{term}
+ at kindex condition (mdb command)
+Attaches a condition to the most recent breakpoint,
+or, if the @samp{n} or @samp{break-num} is given;
+execution won't stop at the breakpoint if the condition is false.
+ at sp 1
+The condition is a match between a variable live at the breakpoint,
+or a part thereof, and @var{term}.
+It is ok for @var{term} to contain spaces.
+The term from the program to be matched
+is specified by @var{varname};
+if it is followed by @var{pathspec} (without a space),
+it specifies that the match is to be
+against the specified part of @var{varname}.
+ at sp 1
+There are two values allowed for @var{op}.
+If @var{op} is @samp{=}, the condition is true
+if the term specified by @var{printspec} matches @var{term}.
+If @var{op} is @samp{!=}, the condition is true
+if the term specified by @var{printspec} doesn't match @var{term}.
+ at var{term} may contain integers and strings,
+but floats and characters aren't supported (yet),
+and neither is any special syntax for lists, operators, etc.
+ at var{term} also may not contain variables, with one exception:
+any occurrence of @samp{_} in @var{term} matches any term.
+ at sp 1
+If execution reaches a breakpoint and the condition cannot be evaluated,
+execution will normally stop at that breakpoint with a message to that effect.
+If the @samp{-p} or @samp{--dont-require-path} option is given,
+execution won't stop at breakpoints at which
+the specified part of the specified variable doesn't exist.
+If the @samp{-v} or @samp{--dont-require-var} option is given,
+execution won't stop at breakpoints at which
+the specified variable itself doesn't exist.
@sp 1
+ at item ignore [-E at var{ignore-count}] [-I at var{ignore-count}] @var{num}
+ at kindex ignore (mdb command)
The options @samp{-E at var{ignore-count}}
and @samp{--ignore-entry @var{ignore-count}}
tell the debugger to ignore the breakpoint
@@ -3040,7 +3075,6 @@
Reports an error if there is no break point with the specified number.
@sp 1
@item ignore [-E at var{ignore-count}] [-I at var{ignore-count}]
- at sp 1
The options @samp{-E at var{ignore-count}}
and @samp{--ignore-entry @var{ignore-count}}
tell the debugger to ignore the breakpoint
@@ -3057,7 +3091,7 @@
Reports an error if the most recently added breakpoint has since been deleted.
@sp 1
@item break_print [-fpv] [-e] [-n] @var{num} @var{print-spec}*
- at sp 1
+ at kindex break_print (mdb command)
Adds the specified print list elements (there may be more than one)
to the print list of the breakpoint numbered @var{num}.
@sp 1
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 mdbcomp
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
Index: runtime/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/Mmakefile,v
retrieving revision 1.117
diff -u -b -r1.117 Mmakefile
--- runtime/Mmakefile 28 Jan 2005 07:11:55 -0000 1.117
+++ runtime/Mmakefile 29 Jan 2005 10:20:32 -0000
@@ -91,6 +91,7 @@
mercury_thread.h \
mercury_timing.h \
mercury_trace_base.h \
+ mercury_trace_term.h \
mercury_trail.h \
mercury_typeclass_info.h \
mercury_type_desc.h \
@@ -182,6 +183,7 @@
mercury_thread.c \
mercury_timing.c \
mercury_trace_base.c \
+ mercury_trace_term.c \
mercury_trail.c \
mercury_type_desc.c \
mercury_type_info.c \
Index: runtime/mercury_trace_term.c
===================================================================
RCS file: runtime/mercury_trace_term.c
diff -N runtime/mercury_trace_term.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ runtime/mercury_trace_term.c 30 Jan 2005 15:47:29 -0000
@@ -0,0 +1,175 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 2005 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.
+*/
+
+/*
+** This file contains code to manage terms, for conditional breakpoints.
+**
+** Author: Zoltan Somogyi.
+*/
+
+#include "mercury_imp.h"
+#include "mercury_trace_term.h"
+#include <stdlib.h>
+
+static MR_CArgs MR_create_cargs(char *str, char **rest);
+static void MR_delete_cargs(MR_CArgs args);
+
+/**************************************************************************/
+
+MR_CTerm
+MR_create_cterm(char *str, char **rest)
+{
+ MR_CTerm term;
+ MR_CArgs args;
+ int i;
+
+ /*
+ ** We don't have to worry about skipping white space, because there
+ ** won't be any, except inside strings.
+ */
+
+ if (str[0] == '"') {
+ i = 1;
+ while (str[i] != '\0' && str[i] != '"') {
+ i++;
+ }
+
+ if (str[i] == '"') {
+ term = MR_malloc(sizeof(struct MR_CTerm_Struct));
+ term->term_functor = &str[0];
+ term->term_args = NULL;
+ *rest = &str[i + 1];
+ return term;
+ }
+
+ return NULL;
+ }
+
+ if (! MR_isalnumunder(str[0]) || MR_isupper(str[0])) {
+ return NULL;
+ }
+
+ i = 0;
+ while (MR_isalnumunder(str[i])) {
+ i++;
+ }
+
+ term = MR_malloc(sizeof(struct MR_CTerm_Struct));
+
+ if ((str[i] == '\0') || str[i] == ',' || str[i] == ')') {
+ term->term_functor = str;
+ term->term_args = NULL;
+ *rest = &str[i];
+ return term;
+ } else if (str[i] == '(') {
+ str[i] = '\0';
+ term->term_functor = str;
+ args = MR_create_cargs(&str[i + 1], rest);
+ if (args == NULL) {
+ MR_free(term);
+ return NULL;
+ }
+
+ term->term_args = args;
+ return term;
+ }
+
+ MR_free(term);
+ return NULL;
+}
+
+static MR_CArgs
+MR_create_cargs(char *str, char **rest)
+{
+ char *more;
+ MR_CTerm term;
+ MR_CArgs args;
+ MR_CArgs tail;
+ int i;
+
+ term = MR_create_cterm(str, &more);
+ if (term == NULL) {
+ return NULL;
+ }
+
+ args = MR_malloc(sizeof(struct MR_CArgs_Struct));
+ args->args_head = term;
+
+ if (more[0] == ')') {
+ more[0] = '\0'; /* to terminate the just previous functor, if any */
+ args->args_tail = NULL;
+ *rest = &more[1];
+ return args;
+ } else if (more[0] == ',') {
+ more[0] = '\0'; /* to terminate the just previous functor, if any */
+ i = 1;
+ while (more[i] != '\0' && MR_isspace(more[i])) {
+ i++;
+ }
+
+ if (more[i] == '\0') {
+ MR_free(args);
+ return NULL;
+ }
+
+ tail = MR_create_cargs(more + i, rest);
+ if (tail == NULL) {
+ MR_free(args);
+ return NULL;
+ }
+
+ args->args_tail = tail;
+ return args;
+ }
+
+ MR_free(args);
+ return NULL;
+}
+
+void
+MR_print_cterm(FILE *fp, MR_CTerm term)
+{
+ MR_CArgs args;
+ int i;
+
+ fprintf(fp, "%s", term->term_functor);
+ if (term->term_args != NULL) {
+ fprintf(fp, "(");
+ i = 0;
+ args = term->term_args;
+ while (args != NULL) {
+ if (i > 0) {
+ fprintf(fp, ", ");
+ }
+ MR_print_cterm(fp, args->args_head);
+ args = args->args_tail;
+ i++;
+ }
+ fprintf(fp, ")");
+ }
+}
+
+void
+MR_delete_cterm(MR_CTerm term)
+{
+ if (term != NULL) {
+ MR_delete_cargs(term->term_args);
+ MR_free(term);
+ }
+}
+
+static void
+MR_delete_cargs(MR_CArgs args)
+{
+ if (args != NULL) {
+ MR_delete_cargs(args->args_tail);
+ MR_delete_cterm(args->args_head);
+ MR_free(args);
+ }
+}
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/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/Mmakefile,v
retrieving revision 1.108
diff -u -b -r1.108 Mmakefile
--- tests/debugger/Mmakefile 9 Dec 2004 01:03:19 -0000 1.108
+++ tests/debugger/Mmakefile 30 Jan 2005 10:55:41 -0000
@@ -20,6 +20,7 @@
browse_pretty \
class_decl \
cmd_quote \
+ cond \
debugger_regs \
exception_cmd \
exception_value \
@@ -245,6 +246,9 @@
cmd_quote.out: cmd_quote cmd_quote.inp
$(MDB) ./cmd_quote < cmd_quote.inp 2>&1 | \
sed 's/io.m:[0-9]*/io.m:NNNN/g' > cmd_quote.out 2>&1
+
+cond.out: cond cond.inp
+ $(MDB) ./cond < cond.inp 2>&1 > cond.out 2>&1
# Set up readline to make it easier to use completion non-interactively.
completion.out: completion completion.inp
Index: tests/debugger/cmd_quote.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/cmd_quote.exp,v
retrieving revision 1.3
diff -u -b -r1.3 cmd_quote.exp
--- tests/debugger/cmd_quote.exp 26 Jan 2004 21:17:35 -0000 1.3
+++ tests/debugger/cmd_quote.exp 30 Jan 2005 19:36:57 -0000
@@ -39,5 +39,5 @@
mdb> '\ \\\''
Unknown command ` \''. Give the command `help' for help.
mdb> '
-> unmatched quote.
+> unmatched single quote.
mdb> mdb: are you sure you want to quit?
Index: tests/debugger/completion.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/completion.exp,v
retrieving revision 1.25
diff -u -b -r1.25 completion.exp
--- tests/debugger/completion.exp 27 Jan 2005 06:17:37 -0000 1.25
+++ tests/debugger/completion.exp 30 Jan 2005 19:39:28 -0000
@@ -3,21 +3,22 @@
Command echo enabled.
mdb> register --quiet
mdb>
-? 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
+? exception quit
+P excp r
+alias f register
+all_class_decls finish retry
+all_procedures flag return
+all_regs forward s
+all_type_ctors g save
+b gen_stack save_to_file
+break goal_paths scope
+break_print goto scroll
+browse h set
+c help source
+cc_query histogram_all stack
+class_decl histogram_exp stack_default_limit
+clear_histogram ignore stack_regs
+condition io_query step
consumer label_stats subgoal
context level table
continue maxdepth table_io
@@ -35,7 +36,6 @@
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/cond.exp
===================================================================
RCS file: tests/debugger/cond.exp
diff -N tests/debugger/cond.exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/debugger/cond.exp 30 Jan 2005 19:37:03 -0000
@@ -0,0 +1,89 @@
+ 1: 1 1 CALL pred cond.main/2-0 (det) cond.m:13
+mdb> echo on
+Command echo enabled.
+mdb> context none
+Contexts will not be printed.
+mdb> break p
+Registering debuggable procedures... done.
+There is one debuggable module, with 5 procedures.
+ 0: + stop interface pred cond.p/2-0 (det)
+mdb> condition X = yes(_)
+ 0: + stop interface pred cond.p/2-0 (det)
+ X = yes(_)
+mdb> continue
+ 6: 4 3 CALL pred cond.p/2-0 (det)
+mdb> print
+p(yes(2), _)
+mdb> delete *
+ 0: E stop interface pred cond.p/2-0 (det)
+ X = yes(_)
+mdb> finish 1
+[no, yes(3), yes(4)]
+ 12: 2 2 EXIT pred cond.test_maybe/2-0 (det)
+mdb> break p
+ 0: + stop interface pred cond.p/2-0 (det)
+mdb> condition X = yes(3)
+ 0: + stop interface pred cond.p/2-0 (det)
+ X = yes(3)
+mdb> continue
+ 20: 9 3 CALL pred cond.p/2-0 (det)
+mdb> print
+p(yes(3), _)
+mdb> delete *
+ 0: E stop interface pred cond.p/2-0 (det)
+ X = yes(3)
+mdb> finish 1
+[no, yes(3), yes(4)]
+ 23: 6 2 EXIT pred cond.test_maybe/2-0 (det)
+mdb> break p
+ 0: + stop interface pred cond.p/2-0 (det)
+mdb> condition -v Y = yes( 3)
+ 0: + stop interface pred cond.p/2-0 (det)
+ -v -p Y = yes(3)
+mdb> continue
+ 30: 12 3 EXIT pred cond.p/2-0 (det)
+mdb> print
+p(yes(2), yes(3))
+mdb> delete *
+ 0: E stop interface pred cond.p/2-0 (det)
+ -v -p Y = yes(3)
+mdb> finish 1
+[no, yes(3), yes(4)]
+ 34: 10 2 EXIT pred cond.test_maybe/2-0 (det)
+mdb> break p
+ 0: + stop interface pred cond.p/2-0 (det)
+mdb> condition -v Y^1 != 3
+ 0: + stop interface pred cond.p/2-0 (det)
+ -v -p Y ^1 != 3
+mdb> continue
+ 44: 17 3 EXIT pred cond.p/2-0 (det)
+mdb> print
+p(yes(3), yes(4))
+mdb> delete *
+ 0: E stop interface pred cond.p/2-0 (det)
+ -v -p Y ^1 != 3
+mdb> finish 1
+[no, yes(3), yes(4)]
+ 45: 14 2 EXIT pred cond.test_maybe/2-0 (det)
+mdb> break q
+ 0: + stop interface pred cond.q/2-0 (det)
+mdb> condition -v Y != "abc "
+ 0: + stop interface pred cond.q/2-0 (det)
+ -v -p Y != "abc "
+mdb> continue
+ 50: 19 3 EXIT pred cond.q/2-0 (det)
+mdb> print
+q("abc", "xabcx")
+mdb> continue
+xabcx
+ 56: 20 3 EXIT pred cond.q/2-0 (det)
+mdb> print
+q("def", "ydefy")
+mdb> delete *
+ 0: E stop interface pred cond.q/2-0 (det)
+ -v -p Y != "abc "
+mdb> finish 1
+ydefy
+else
+ 63: 18 2 EXIT pred cond.test_string/2-0 (det)
+mdb> continue
Index: tests/debugger/cond.inp
===================================================================
RCS file: tests/debugger/cond.inp
diff -N tests/debugger/cond.inp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/debugger/cond.inp 30 Jan 2005 17:32:05 -0000
@@ -0,0 +1,35 @@
+echo on
+context none
+break p
+condition X = yes(_)
+continue
+print
+delete *
+finish 1
+break p
+condition X = yes(3)
+continue
+print
+delete *
+finish 1
+break p
+condition -v Y = yes( 3)
+continue
+print
+delete *
+finish 1
+break p
+condition -v Y^1 != 3
+continue
+print
+delete *
+finish 1
+break q
+condition -v Y != "abc "
+continue
+print
+continue
+print
+delete *
+finish 1
+continue
Index: tests/debugger/cond.m
===================================================================
RCS file: tests/debugger/cond.m
diff -N tests/debugger/cond.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/debugger/cond.m 30 Jan 2005 14:59:40 -0000
@@ -0,0 +1,62 @@
+:- module cond.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module list, int, std_util.
+
+main(!IO) :-
+ test_maybe(!IO),
+ test_maybe(!IO),
+ test_maybe(!IO),
+ test_maybe(!IO),
+ test_string(!IO).
+
+:- pred test_maybe(io::di, io::uo) is det.
+
+test_maybe(!IO) :-
+ p(no, A),
+ p(yes(2), B),
+ p(yes(3), C),
+ io__write([A, B, C], !IO),
+ io__nl(!IO).
+
+:- pred test_string(io::di, io::uo) is det.
+
+test_string(!IO) :-
+ q("abc", A),
+ io__write_string(A, !IO),
+ io__nl(!IO),
+ q("def", B),
+ io__write_string(B, !IO),
+ io__nl(!IO),
+ q("ghi", C),
+ io__write_string(C, !IO),
+ io__nl(!IO).
+
+:- pred p(maybe(int)::in, maybe(int)::out) is det.
+
+p(X, Y) :-
+ (
+ X = no,
+ Y = no
+ ;
+ X = yes(Z),
+ Y = yes(Z + 1)
+ ).
+
+:- pred q(string::in, string::out) is det.
+
+q(X, Y) :-
+ ( X = "abc" ->
+ Y = "xabcx"
+ ; X = "def" ->
+ Y = "ydefy"
+ ;
+ Y = "else"
+ ).
Index: tests/debugger/mdb_command_test.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/mdb_command_test.inp,v
retrieving revision 1.38
diff -u -b -r1.38 mdb_command_test.inp
--- tests/debugger/mdb_command_test.inp 28 Jan 2005 01:13:32 -0000 1.38
+++ tests/debugger/mdb_command_test.inp 30 Jan 2005 19:35:53 -0000
@@ -24,6 +24,7 @@
view xyzzy xyzzy xyzzy xyzzy xyzzy
save_to_file xyzzy xyzzy xyzzy xyzzy xyzzy
break xyzzy xyzzy xyzzy xyzzy xyzzy
+condition xyzzy xyzzy xyzzy xyzzy xyzzy
ignore xyzzy xyzzy xyzzy xyzzy xyzzy
break_print xyzzy xyzzy xyzzy xyzzy xyzzy
disable 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_internal.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.190
diff -u -b -r1.190 mercury_trace_internal.c
--- trace/mercury_trace_internal.c 28 Jan 2005 02:47:43 -0000 1.190
+++ trace/mercury_trace_internal.c 30 Jan 2005 18:13:48 -0000
@@ -74,8 +74,9 @@
#endif
/* Special characters used in mdb commands. */
-#define MR_MDB_QUOTE_CHAR '\''
-#define MR_MDB_ESCAPE_CHAR '\\'
+#define DOUBLE_QUOTE_CHAR '"'
+#define SINGLE_QUOTE_CHAR '\''
+#define ESCAPE_CHAR '\\'
/* The initial size of arrays of words. */
#define MR_INIT_WORD_COUNT 20
@@ -433,6 +434,7 @@
static MR_TraceCmdFunc MR_trace_cmd_view;
static MR_TraceCmdFunc MR_trace_cmd_save_to_file;
static MR_TraceCmdFunc MR_trace_cmd_break;
+static MR_TraceCmdFunc MR_trace_cmd_condition;
static MR_TraceCmdFunc MR_trace_cmd_ignore;
static MR_TraceCmdFunc MR_trace_cmd_break_print;
static MR_TraceCmdFunc MR_trace_cmd_enable;
@@ -528,6 +530,10 @@
MR_Spy_Print_List *print_list,
char ***words, int *word_count,
const char *cat, const char *item);
+static MR_bool MR_trace_options_condition(int *break_num,
+ MR_bool *require_var, MR_bool *require_path,
+ 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,
int *ignore_count, char ***words, int *word_count,
@@ -693,7 +699,8 @@
MR_bool ignore_errors);
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_bool MR_trace_continue_line(char *ptr, MR_bool *single_quoted,
+ MR_bool *double_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);
@@ -744,6 +751,12 @@
MR_trace_internal_ensure_init();
+ if (MR_spy_point_cond_problem != NULL) {
+ fprintf(MR_mdb_err, "mdb: couldn't evaluate break point condition.\n");
+ fprintf(MR_mdb_err, "%s\n", MR_spy_point_cond_problem);
+ MR_spy_point_cond_problem = NULL;
+ }
+
MR_trace_event_print_internal_report(event_info);
MR_trace_maybe_sync_source_window(event_info, MR_FALSE);
@@ -772,6 +785,7 @@
line = MR_trace_get_command("mdb> ", MR_mdb_in, MR_mdb_out);
res = MR_trace_debug_cmd(line, cmd, event_info, &event_details,
&jumpaddr);
+ fflush(MR_mdb_err);
} while (res == KEEP_INTERACTING);
cmd->MR_trace_must_check = (! cmd->MR_trace_strict) ||
@@ -2638,6 +2652,119 @@
}
static MR_Next
+MR_trace_cmd_condition(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+ MR_Event_Info *event_info, MR_Event_Details *event_details,
+ MR_Code **jumpaddr)
+{
+ int break_num;
+ MR_bool require_var;
+ MR_bool require_path;
+ int i;
+ const char *problem;
+ MR_CTerm term;
+ MR_Spy_Test test;
+ char *what_str;
+ char *term_str;
+ int len;
+ char *rest;
+ MR_Spy_Cond *cond;
+ MR_Var_Spec var_spec;
+ char *path;
+
+ break_num = MR_most_recent_spy_point;
+ require_var = MR_TRUE;
+ require_path = MR_TRUE;
+ if (! MR_trace_options_condition(&break_num, &require_var, &require_path,
+ &words, &word_count, "breakpoint", "condition"))
+ {
+ /* the usage message has already been printed */
+ return KEEP_INTERACTING;
+ } else if (word_count < 4) {
+ MR_trace_usage("breakpoint", "condition");
+ return KEEP_INTERACTING;
+ }
+
+ if (break_num < 0) {
+ fprintf(MR_mdb_err, "There is no breakpoint.\n");
+ return KEEP_INTERACTING;
+ }
+
+ if (! (0 <= break_num && break_num < MR_spy_point_next)) {
+ fprintf(MR_mdb_err, "There is no breakpoint %d.\n", break_num);
+ return KEEP_INTERACTING;
+ }
+
+ if (! MR_spy_points[break_num]->spy_exists) {
+ fprintf(MR_mdb_err, "Breakpoint %d has been deleted.\n", break_num);
+ return KEEP_INTERACTING;
+ }
+
+ cond = MR_malloc(sizeof(MR_Spy_Cond));
+
+ what_str = MR_malloc(strlen(words[1]) + 1);
+ strcpy(what_str, words[1]);
+
+ problem = MR_trace_parse_var_path(what_str, &var_spec, &path);
+ if (problem != NULL) {
+ fprintf(MR_mdb_err, "mdb: %s: %s.\n", what_str, problem);
+ return KEEP_INTERACTING;
+ }
+
+ if (MR_streq(words[2], "=") || MR_streq(words[2], "==")) {
+ test = MR_SPY_TEST_EQUAL;
+ } else if (MR_streq(words[2], "!=")) {
+ test = MR_SPY_TEST_NOT_EQUAL;
+ } else {
+ fprintf(MR_mdb_err, "invalid condition: should be = or !=\n");
+ return KEEP_INTERACTING;
+ }
+
+ len = 0;
+ for (i = 3; i < word_count; i++) {
+ len += strlen(words[i]);
+ }
+
+ term_str = MR_malloc(len + 1);
+ len = 0;
+ for (i = 3; i < word_count; i++) {
+ strcpy(term_str + len, words[i]);
+ len += strlen(words[i]);
+ }
+
+ term = MR_create_cterm(term_str, &rest);
+ if (term == NULL) {
+ fprintf(MR_mdb_out, "syntax error in term\n");
+ return KEEP_INTERACTING;
+ }
+
+ if (*rest != '\0') {
+ fprintf(MR_mdb_out, "syntax error after term\n");
+ return KEEP_INTERACTING;
+ }
+
+ if (MR_spy_points[break_num]->spy_cond != NULL) {
+ MR_delete_cterm(MR_spy_points[break_num]->spy_cond->cond_term);
+ MR_free(MR_spy_points[break_num]->spy_cond->cond_what_string);
+ MR_free(MR_spy_points[break_num]->spy_cond->cond_term_string);
+ MR_free(MR_spy_points[break_num]->spy_cond);
+ }
+
+ cond->cond_var_spec = var_spec;
+ cond->cond_path = path;
+ cond->cond_test = test;
+ cond->cond_term = term;
+ cond->cond_term_string = term_str;
+ cond->cond_what_string = what_str;
+ cond->cond_require_var = require_var;
+ cond->cond_require_path = require_path;
+
+ MR_spy_points[break_num]->spy_cond = cond;
+
+ MR_print_spy_point(MR_mdb_out, break_num, MR_TRUE);
+ return KEEP_INTERACTING;
+}
+
+static MR_Next
MR_trace_cmd_ignore(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
MR_Event_Info *event_info, MR_Event_Details *event_details,
MR_Code **jumpaddr)
@@ -2894,6 +3021,7 @@
if (0 <= n && n < MR_spy_point_next && MR_spy_points[n]->spy_exists) {
MR_spy_points[n]->spy_exists = MR_FALSE;
MR_print_spy_point(MR_mdb_out, n, MR_FALSE);
+ MR_spy_points[n]->spy_exists = MR_TRUE;
MR_delete_spy_point(n);
} else {
fflush(MR_mdb_out);
@@ -2908,6 +3036,7 @@
if (MR_spy_points[i]->spy_exists) {
MR_spy_points[i]->spy_exists = MR_FALSE;
MR_print_spy_point(MR_mdb_out, i, MR_FALSE);
+ MR_spy_points[i]->spy_exists = MR_TRUE;
MR_delete_spy_point(i);
count++;
}
@@ -2925,8 +3054,9 @@
int slot;
slot = MR_most_recent_spy_point;
- MR_spy_points[slot]-> spy_exists = MR_FALSE;
+ MR_spy_points[slot]->spy_exists = MR_FALSE;
MR_print_spy_point(MR_mdb_out, slot, MR_FALSE);
+ MR_spy_points[slot]->spy_exists = MR_TRUE;
MR_delete_spy_point(slot);
} else {
fflush(MR_mdb_out);
@@ -6085,6 +6215,61 @@
return MR_TRUE;
}
+static struct MR_option MR_trace_condition_opts[] =
+{
+ { "break-num", MR_required_argument, NULL, 'n' },
+ { "dont-require-var", MR_no_argument, NULL, 'v' },
+ { "dont-require-path", MR_no_argument, NULL, 'p' },
+ { NULL, MR_no_argument, NULL, 0 }
+};
+
+static MR_bool
+MR_trace_options_condition(int *break_num, MR_bool *require_var,
+ MR_bool *require_path, char ***words, int *word_count,
+ const char *cat, const char *item)
+{
+ int c;
+ int n;
+
+ MR_optind = 0;
+ while ((c = MR_getopt_long(*word_count, *words, "n:vp",
+ MR_trace_condition_opts, NULL)) != EOF)
+ {
+ switch (c) {
+
+ case 'n':
+ if (! MR_trace_is_natural_number(MR_optarg, &n)) {
+ MR_trace_usage(cat, item);
+ return MR_FALSE;
+ }
+ *break_num = n;
+ break;
+
+ case 'p':
+ *require_path = MR_FALSE;
+ break;
+
+ case 'v':
+ /*
+ ** If a variable is missing, then the path inside
+ ** is missing as well.
+ */
+
+ *require_path = MR_FALSE;
+ *require_var = MR_FALSE;
+ 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_ignore_count_opts[] =
{
{ "ignore-entry", MR_required_argument, NULL, 'E' },
@@ -7015,20 +7200,28 @@
MR_trace_break_off_one_word(char *line, int char_pos, int *new_char_pos_ptr)
{
int lag = 0;
- MR_bool quoted = MR_FALSE;
+ MR_bool single_quoted = MR_FALSE;
+ MR_bool double_quoted = MR_FALSE;
MR_bool another = MR_FALSE;
while (line[char_pos] != '\0') {
- if (! quoted && MR_isspace(line[char_pos])) {
+ if (! single_quoted && ! double_quoted && MR_isspace(line[char_pos])) {
another = MR_TRUE;
break;
}
- if (line[char_pos] == MR_MDB_QUOTE_CHAR) {
+
+ if (! double_quoted && line[char_pos] == SINGLE_QUOTE_CHAR) {
lag++;
char_pos++;
- quoted = !quoted;
+ single_quoted = ! single_quoted;
+ } else if (! single_quoted && line[char_pos] == DOUBLE_QUOTE_CHAR) {
+ if (lag != 0) {
+ line[char_pos - lag] = line[char_pos];
+ }
+ char_pos++;
+ double_quoted = ! double_quoted;
} else {
- if (line[char_pos] == MR_MDB_ESCAPE_CHAR) {
+ if (line[char_pos] == ESCAPE_CHAR) {
lag++;
char_pos++;
if (line[char_pos] == '\0') {
@@ -7036,15 +7229,19 @@
}
}
- if (lag) {
+ if (lag != 0) {
line[char_pos - lag] = line[char_pos];
}
char_pos++;
}
}
- if (quoted) {
- return "unmatched quote";
+ if (single_quoted) {
+ return "unmatched single quote";
+ }
+
+ if (double_quoted) {
+ return "unmatched double quote";
}
line[char_pos - lag] = '\0';
@@ -7140,7 +7337,8 @@
char *ptr;
char *cmd_chars;
int cmd_char_max;
- MR_bool quoted;
+ MR_bool single_quoted;
+ MR_bool double_quoted;
int len, extra_len;
line = MR_trace_getline(prompt, mdb_in, mdb_out);
@@ -7159,8 +7357,9 @@
ptr = line;
cmd_chars = line;
cmd_char_max = len + 1;
- quoted = MR_FALSE;
- while (MR_trace_continue_line(ptr, "ed)) {
+ single_quoted = MR_FALSE;
+ double_quoted = MR_FALSE;
+ while (MR_trace_continue_line(ptr, &single_quoted, &double_quoted)) {
/*
** We were inside quotes when the end of the line was
** reached, or the newline was escaped, so input continues
@@ -7295,7 +7494,8 @@
*/
static MR_bool
-MR_trace_continue_line(char *ptr, MR_bool *quoted)
+MR_trace_continue_line(char *ptr, MR_bool *single_quoted,
+ MR_bool *double_quoted)
{
MR_bool escaped = MR_FALSE;
@@ -7303,11 +7503,13 @@
if (escaped) {
/* do nothing special */
escaped = MR_FALSE;
- } else if (*ptr == MR_MDB_ESCAPE_CHAR) {
+ } else if (*ptr == ESCAPE_CHAR) {
escaped = MR_TRUE;
- } else if (*ptr == MR_MDB_QUOTE_CHAR) {
- *quoted = !(*quoted);
- } else if (!(*quoted) && *ptr == ';') {
+ } else if (! (*double_quoted) && *ptr == SINGLE_QUOTE_CHAR) {
+ *single_quoted = ! (*single_quoted);
+ } else if (! (*single_quoted) && *ptr == DOUBLE_QUOTE_CHAR) {
+ *double_quoted = ! (*double_quoted);
+ } else if (! (*single_quoted) && ! (*double_quoted) && *ptr == ';') {
/*
** The line contains at least two commands.
** Return only the first command now; put the
@@ -7328,7 +7530,7 @@
*(ptr - 1) = ' ';
}
- return (*quoted || escaped);
+ return (*single_quoted || *double_quoted || escaped);
}
static MR_Code *
@@ -7591,6 +7793,8 @@
{ "breakpoint", "break", MR_trace_cmd_break,
MR_trace_break_cmd_args, MR_trace_breakpoint_completer },
+ { "breakpoint", "condition", MR_trace_cmd_condition,
+ NULL, MR_trace_null_completer },
{ "breakpoint", "ignore", MR_trace_cmd_ignore,
MR_trace_ignore_cmd_args, MR_trace_null_completer },
{ "breakpoint", "break_print", MR_trace_cmd_break_print,
Index: trace/mercury_trace_spy.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_spy.c,v
retrieving revision 1.23
diff -u -b -r1.23 mercury_trace_spy.c
--- trace/mercury_trace_spy.c 28 Jan 2005 02:46:44 -0000 1.23
+++ trace/mercury_trace_spy.c 30 Jan 2005 17:33:23 -0000
@@ -16,11 +16,16 @@
#include "mercury_imp.h"
#include "mercury_array_macros.h"
+#include "mercury_layout_util.h"
#include "mercury_trace_base.h"
#include "mercury_trace.h"
#include "mercury_trace_spy.h"
#include "mercury_trace_tables.h"
+#include "mercury_trace_util.h"
+#include "mercury_trace_vars.h"
+
+#include "mdb.cterm.mh"
#include <stdlib.h>
@@ -102,6 +107,8 @@
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 MR_bool MR_spy_cond_is_true(MR_Spy_Point *point,
+ 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 *);
@@ -202,11 +209,13 @@
MR_fatal_error("non-lineno spy point in spied labels array");
}
+ if (MR_spy_cond_is_true(point, layout)) {
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();
@@ -223,6 +232,7 @@
"spied labels array");
}
+ if (MR_spy_cond_is_true(point, layout)) {
MR_update_enabled_action(point, port, &action, &enabled);
if (*print_list == NULL) {
*print_list = point->spy_print_list;
@@ -230,6 +240,7 @@
}
}
}
+ }
slot = MR_search_spy_table_for_proc(layout->MR_sll_entry);
if (slot >= 0) {
@@ -239,19 +250,24 @@
switch (point->spy_when) {
case MR_SPY_ALL:
- MR_update_enabled_action(point, port, &action, &enabled);
+ if (MR_spy_cond_is_true(point, layout)) {
+ 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)) {
+ if (MR_spy_cond_is_true(point, layout)) {
MR_update_enabled_action(point, port, &action,
&enabled);
if (*print_list == NULL) {
*print_list = point->spy_print_list;
}
+ }
} else {
continue;
}
@@ -260,11 +276,13 @@
case MR_SPY_INTERFACE:
if (MR_port_is_interface(port)) {
+ if (MR_spy_cond_is_true(point, layout)) {
MR_update_enabled_action(point, port, &action,
&enabled);
if (*print_list == NULL) {
*print_list = point->spy_print_list;
}
+ }
} else {
continue;
}
@@ -273,11 +291,13 @@
case MR_SPY_SPECIFIC:
if (layout == point->spy_label) {
+ if (MR_spy_cond_is_true(point, layout)) {
MR_update_enabled_action(point, port, &action,
&enabled);
if (*print_list == NULL) {
*print_list = point->spy_print_list;
}
+ }
} else {
continue;
}
@@ -338,6 +358,129 @@
}
}
+const char *MR_spy_point_cond_problem = NULL;
+
+static MR_bool
+MR_spy_cond_is_true(MR_Spy_Point *point, const MR_Label_Layout *label_layout)
+{
+ int max_mr_num;
+ MR_Word saved_regs[MR_MAX_FAKE_REG];
+ MR_Var_Spec var_spec;
+ char *path;
+ const char *problem;
+ char *bad_path;
+ MR_TypeInfo type_info;
+ MR_Word value;
+ MR_Word *value_ptr;
+ MR_TypeInfo sub_type_info;
+ MR_Word *sub_value_ptr;
+ MR_Word match;
+ MR_bool saved_trace_func_enabled;
+ MR_bool retval;
+ MR_Spy_Cond *cond;
+
+ if (point->spy_cond == NULL) {
+ return MR_TRUE;
+ }
+
+ MR_restore_transient_registers();
+
+ cond = point->spy_cond;
+
+ /*
+ ** From this point, returning should be done by setting both
+ ** MR_spy_point_cond_problem and retval, and goto end.
+ */
+
+ MR_spy_point_cond_problem = "internal error in MR_spy_cond_is_true";
+ retval = MR_TRUE;
+
+ MR_compute_max_mr_num(max_mr_num, label_layout);
+ /* This also saves the regs in MR_fake_regs. */
+ MR_copy_regs_to_saved_regs(max_mr_num, saved_regs);
+ MR_trace_init_point_vars(label_layout, saved_regs,
+ (MR_Trace_Port) label_layout->MR_sll_port, MR_FALSE);
+
+ problem = MR_lookup_unambiguous_var_spec(cond->cond_var_spec,
+ &type_info, &value);
+ if (problem != NULL) {
+ if (cond->cond_require_var) {
+ MR_spy_point_cond_problem = problem;
+ retval = MR_TRUE;
+ } else {
+ MR_spy_point_cond_problem = NULL;
+ retval = MR_FALSE;
+ }
+
+ goto end;
+ }
+
+ value_ptr = &value;
+ bad_path = MR_select_specified_subterm(cond->cond_path,
+ type_info, value_ptr, &sub_type_info, &sub_value_ptr);
+
+ if (bad_path != NULL) {
+ if (cond->cond_require_var) {
+ MR_spy_point_cond_problem = MR_trace_bad_path(bad_path);
+ retval = MR_TRUE;
+ } else {
+ MR_spy_point_cond_problem = NULL;
+ retval = MR_FALSE;
+ }
+ goto end;
+ }
+
+#ifdef MR_DEBUG_SPY_COND
+ MR_print_cterm(stdout, cond->cond_term);
+ fprintf(stdout, ": ");
+#endif
+
+ saved_trace_func_enabled = MR_trace_func_enabled;
+ MR_trace_func_enabled = MR_FALSE;
+ MR_TRACE_CALL_MERCURY(
+ ML_BROWSE_match_with_cterm((MR_Word) sub_type_info, *sub_value_ptr,
+ cond->cond_term, &match);
+ );
+ MR_trace_func_enabled = saved_trace_func_enabled;
+
+#ifdef MR_DEBUG_SPY_COND
+ fprintf(stdout, "%d\n", match);
+#endif
+
+ switch (cond->cond_test) {
+ case MR_SPY_TEST_EQUAL:
+ MR_spy_point_cond_problem = NULL;
+ if (match != 0) {
+ retval = MR_TRUE;
+ goto end;
+ } else {
+ retval = MR_FALSE;
+ goto end;
+ }
+ break;
+
+ case MR_SPY_TEST_NOT_EQUAL:
+ MR_spy_point_cond_problem = NULL;
+ if (match != 0) {
+ retval = MR_FALSE;
+ goto end;
+ } else {
+ retval = MR_TRUE;
+ goto end;
+ }
+ break;
+
+ default:
+ MR_fatal_error("MR_spy_cond_is_true: invalid spy_cond_test");
+ break;
+ }
+
+end:
+ MR_copy_saved_regs_to_regs(max_mr_num, saved_regs);
+ MR_save_transient_registers();
+ return retval;
+}
+
static const char *incompatible =
"Ignore count is not compatible with break point specification";
@@ -373,6 +516,7 @@
point->spy_action = action;
point->spy_ignore_when = ignore_when;
point->spy_ignore_count = ignore_count;
+ point->spy_cond = NULL;
point->spy_print_list = print_list;
point->spy_proc = entry;
point->spy_label = label;
@@ -381,6 +525,7 @@
for (i = 0; i < MR_spy_point_next; i++) {
if (! MR_spy_points[i]->spy_exists) {
+ MR_most_recent_spy_point = i;
MR_spy_points[i] = point;
return i;
}
@@ -462,6 +607,7 @@
point->spy_action = action;
point->spy_ignore_when = ignore_when;
point->spy_ignore_count = ignore_count;
+ point->spy_cond = NULL;
point->spy_print_list = print_list;
point->spy_filename = filename;
point->spy_linenumber = linenumber;
@@ -604,7 +750,25 @@
MR_most_recent_spy_point = -1;
}
+ if (! MR_spy_points[point_table_slot]->spy_exists) {
+ return;
+ }
+
+ MR_spy_points[point_table_slot]->spy_exists = MR_FALSE;
+
MR_delete_spy_print_list(point->spy_print_list);
+ /* in case it gets deleted again */
+ point->spy_print_list = NULL;
+
+ if (point->spy_cond != NULL) {
+ MR_delete_cterm(point->spy_cond->cond_term);
+ MR_free(point->spy_cond->cond_what_string);
+ MR_free(point->spy_cond->cond_term_string);
+ MR_free(point->spy_cond);
+
+ /* in case it gets deleted again */
+ point->spy_cond = NULL;
+ }
if (point->spy_when == MR_SPY_LINENO) {
/* Release the storage acquired by MR_copy_string. */
@@ -656,6 +820,7 @@
MR_print_spy_point(FILE *fp, int spy_point_num, MR_bool verbose)
{
MR_Spy_Point *point;
+ MR_Spy_Cond *cond;
point = MR_spy_points[spy_point_num];
fprintf(fp, "%2d: %1s %-5s %9s ",
@@ -679,6 +844,55 @@
fprintf(fp, "\n%12s(ignore next %s event)\n",
"", MR_ignore_when_to_string(point->spy_ignore_when));
} else {
+ fprintf(fp, "\n");
+ }
+
+ if (point->spy_cond != NULL) {
+ cond = point->spy_cond;
+
+ fprintf(fp, "%12s", "");
+
+ if (! cond->cond_require_var) {
+ fprintf(fp, "-v ");
+ }
+
+ if (! cond->cond_require_path) {
+ fprintf(fp, "-p ");
+ }
+
+ switch (cond->cond_var_spec.MR_var_spec_kind) {
+ case MR_VAR_SPEC_NUMBER:
+ fprintf(fp, "%d", cond->cond_var_spec.MR_var_spec_number);
+ break;
+
+ case MR_VAR_SPEC_NAME:
+ fprintf(fp, "%s", cond->cond_var_spec.MR_var_spec_name);
+ break;
+
+ default:
+ MR_fatal_error("MR_print_spy_point: invalid cond_what");
+ break;
+ }
+
+ if (cond->cond_path != NULL) {
+ fprintf(fp, " ^%s", cond->cond_path);
+ }
+
+ switch (cond->cond_test) {
+ case MR_SPY_TEST_EQUAL:
+ fprintf(fp, " = ");
+ break;
+
+ case MR_SPY_TEST_NOT_EQUAL:
+ fprintf(fp, " != ");
+ break;
+
+ default:
+ MR_fatal_error("MR_print_spy_point: invalid cond_test");
+ break;
+ }
+
+ MR_print_cterm(fp, cond->cond_term);
fprintf(fp, "\n");
}
Index: trace/mercury_trace_spy.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_spy.h,v
retrieving revision 1.10
diff -u -b -r1.10 mercury_trace_spy.h
--- trace/mercury_trace_spy.h 27 Jan 2005 06:17:41 -0000 1.10
+++ trace/mercury_trace_spy.h 30 Jan 2005 16:25:20 -0000
@@ -15,8 +15,10 @@
#define MERCURY_TRACE_SPY_H
#include "mercury_stack_layout.h" /* for MR_Proc_Layout etc */
+#include "mercury_trace_term.h" /* for MR_CTerm */
#include "mercury_trace_base.h" /* for MR_Trace_Port etc */
#include "mercury_trace_browse.h" /* for MR_Browse_Format */
+#include "mercury_trace_vars.h" /* for MR_Var_Spec */
typedef enum {
MR_SPY_PRINT, MR_SPY_STOP
@@ -46,6 +48,10 @@
typedef struct MR_Spy_Print_List_Struct *MR_Spy_Print_List;
typedef enum {
+ MR_SPY_TEST_EQUAL, MR_SPY_TEST_NOT_EQUAL
+} MR_Spy_Test;
+
+typedef enum {
MR_SPY_PRINT_GOAL,
MR_SPY_PRINT_ALL,
MR_SPY_PRINT_ONE,
@@ -65,6 +71,17 @@
typedef struct MR_Spy_Point_Struct MR_Spy_Point;
+typedef struct {
+ MR_Var_Spec cond_var_spec;
+ char *cond_path;
+ MR_Spy_Test cond_test;
+ MR_CTerm cond_term;
+ MR_bool cond_require_var;
+ MR_bool cond_require_path;
+ char *cond_what_string;
+ char *cond_term_string;
+} MR_Spy_Cond;
+
struct MR_Spy_Point_Struct {
MR_bool spy_exists; /* MR_FALSE if deleted */
MR_bool spy_enabled;
@@ -72,6 +89,7 @@
MR_Spy_Action spy_action;
MR_Spy_Ignore_When spy_ignore_when;
int spy_ignore_count;
+ MR_Spy_Cond *spy_cond;
MR_Spy_Print_List spy_print_list;
const MR_Proc_Layout *spy_proc; /* if not LINENO */
const MR_Label_Layout *spy_label; /* if SPECIFIC */
@@ -90,6 +108,8 @@
extern int MR_spy_point_max;
extern int MR_most_recent_spy_point;
+
+extern const char *MR_spy_point_cond_problem;
/*
** Check whether the event described by the given label layout and port
Index: trace/mercury_trace_vars.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_vars.c,v
retrieving revision 1.60
diff -u -b -r1.60 mercury_trace_vars.c
--- trace/mercury_trace_vars.c 28 Jan 2005 02:47:44 -0000 1.60
+++ trace/mercury_trace_vars.c 30 Jan 2005 06:47:43 -0000
@@ -138,7 +138,6 @@
int *var_index_ptr, MR_bool *is_ambiguous_ptr);
static char * MR_trace_var_completer_next(const char *word,
size_t word_len, MR_Completer_Data *data);
-static const char * MR_trace_bad_path(const char *path);
static int MR_trace_print_var_name(FILE *out,
MR_Var_Details *var);
static const char * MR_trace_valid_var_number(int var_number);
@@ -935,21 +934,17 @@
}
const char *
-MR_trace_parse_browse_one(FILE *out, MR_bool print_var_name, char *word_spec,
- MR_Browser browser, MR_Browse_Caller_Type caller, MR_Browse_Format format,
- MR_bool must_be_unique)
+MR_trace_parse_var_path(char *word_spec, MR_Var_Spec *var_spec, char **path)
{
- MR_Var_Spec var_spec;
- char *path;
char *s;
- int n;
+ char *start;
s = strpbrk(word_spec, "^/");
if (s == NULL) {
- path = NULL;
+ *path = NULL;
} else {
- path = s;
+ start = s;
do {
if (*s == '^' || *s == '/') {
@@ -973,11 +968,27 @@
}
} while (*s != '\0');
- *path = '\0';
- path++;
+ *start = '\0';
+ *path = start+1;
}
- MR_convert_arg_to_var_spec(word_spec, &var_spec);
+ MR_convert_arg_to_var_spec(word_spec, var_spec);
+ return NULL;
+}
+
+const char *
+MR_trace_parse_browse_one(FILE *out, MR_bool print_var_name, char *word_spec,
+ MR_Browser browser, MR_Browse_Caller_Type caller, MR_Browse_Format format,
+ MR_bool must_be_unique)
+{
+ MR_Var_Spec var_spec;
+ char *path;
+ const char *problem;
+
+ problem = MR_trace_parse_var_path(word_spec, &var_spec, &path);
+ if (problem != NULL) {
+ return problem;
+ }
return MR_trace_browse_one_path(out, print_var_name, var_spec, path,
browser, caller, format, must_be_unique);
@@ -992,25 +1003,47 @@
browser, caller, format, must_be_unique);
}
+const char *
+MR_lookup_unambiguous_var_spec(MR_Var_Spec var_spec,
+ MR_TypeInfo *type_info, MR_Word *value)
+{
+ int var_num;
+ MR_bool is_ambiguous;
+ const char *problem;
+
+ problem = MR_lookup_var_spec(var_spec, &var_num, &is_ambiguous);
+ if (problem != NULL) {
+ return problem;
+ }
+
+ if (is_ambiguous) {
+ return "variable name is not unique";
+ }
+
+ *type_info = MR_point.MR_point_vars[var_num].MR_var_type;
+ *value = MR_point.MR_point_vars[var_num].MR_var_value;
+ return NULL;
+}
+
static const char *
MR_trace_browse_one_path(FILE *out, MR_bool print_var_name,
MR_Var_Spec var_spec, char *path, MR_Browser browser,
MR_Browse_Caller_Type caller, MR_Browse_Format format,
MR_bool must_be_unique)
{
- int i;
+ int var_num;
MR_bool is_ambiguous;
const char *problem;
char *bad_path;
- problem = MR_lookup_var_spec(var_spec, &i, &is_ambiguous);
+ problem = MR_lookup_var_spec(var_spec, &var_num, &is_ambiguous);
if (problem != NULL) {
return problem;
}
if (! is_ambiguous) {
bad_path = MR_trace_browse_var(out, print_var_name,
- &MR_point.MR_point_vars[i], path, browser, caller, format);
+ &MR_point.MR_point_vars[var_num], path, browser, caller, format);
if (bad_path != NULL) {
return MR_trace_bad_path(bad_path);
}
@@ -1024,16 +1057,17 @@
success_count = 0;
do {
bad_path = MR_trace_browse_var(out, print_var_name,
- &MR_point.MR_point_vars[i], path, browser, caller, format);
+ &MR_point.MR_point_vars[var_num], path, browser, caller,
+ format);
if (bad_path == NULL) {
success_count++;
}
- i++;
- } while (i < MR_point.MR_point_var_count &&
+ var_num++;
+ } while (var_num < MR_point.MR_point_var_count &&
MR_streq(var_spec.MR_var_spec_name,
- MR_point.MR_point_vars[i].MR_var_fullname));
+ MR_point.MR_point_vars[var_num].MR_var_fullname));
if (success_count == 0) {
return "the selected path does not exist "
@@ -1053,13 +1087,13 @@
#else
- int i;
+ int var_num;
MR_bool is_ambiguous;
const char *problem;
MR_Var_Spec var_spec;
MR_convert_arg_to_var_spec(word_spec, &var_spec);
- problem = MR_lookup_var_spec(var_spec, &i, &is_ambiguous);
+ problem = MR_lookup_var_spec(var_spec, &var_num, &is_ambiguous);
if (problem != NULL) {
return problem;
}
@@ -1067,18 +1101,18 @@
if (is_ambiguous) {
do {
fprintf(out, "%20s: %6u\n",
- MR_point.MR_point_vars[i].MR_var_fullname,
- MR_term_size(MR_point.MR_point_vars[i].MR_var_type,
- MR_point.MR_point_vars[i].MR_var_value));
- i++;
- } while (i < MR_point.MR_point_var_count &&
+ MR_point.MR_point_vars[var_num].MR_var_fullname,
+ MR_term_size(MR_point.MR_point_vars[var_num].MR_var_type,
+ MR_point.MR_point_vars[var_num].MR_var_value));
+ var_num++;
+ } while (var_num < MR_point.MR_point_var_count &&
MR_streq(var_spec.MR_var_spec_name,
- MR_point.MR_point_vars[i].MR_var_fullname));
+ MR_point.MR_point_vars[var_num].MR_var_fullname));
} else {
fprintf(out, "%20s: %6u\n",
- MR_point.MR_point_vars[i].MR_var_fullname,
- MR_term_size(MR_point.MR_point_vars[i].MR_var_type,
- MR_point.MR_point_vars[i].MR_var_value));
+ MR_point.MR_point_vars[var_num].MR_var_fullname,
+ MR_term_size(MR_point.MR_point_vars[var_num].MR_var_type,
+ MR_point.MR_point_vars[var_num].MR_var_value));
}
return NULL;
@@ -1092,18 +1126,18 @@
#ifndef MR_RECORD_TERM_SIZES
return "term sizes not available in this grade";
#else
- int i;
+ int var_num;
const char *problem;
if (MR_point.MR_point_problem != NULL) {
return MR_point.MR_point_problem;
}
- for (i = 0; i < MR_point.MR_point_var_count; i++) {
+ for (var_num = 0; var_num < MR_point.MR_point_var_count; var_num++) {
fprintf(out, "%-20s %6u\n",
- MR_point.MR_point_vars[i].MR_var_fullname,
- MR_term_size(MR_point.MR_point_vars[i].MR_var_type,
- MR_point.MR_point_vars[i].MR_var_value));
+ MR_point.MR_point_vars[var_num].MR_var_fullname,
+ MR_term_size(MR_point.MR_point_vars[var_num].MR_var_type,
+ MR_point.MR_point_vars[var_num].MR_var_value));
}
return NULL;
@@ -1114,7 +1148,7 @@
#define BAD_PATH_MSG_PREFIX "the path "
#define BAD_PATH_MSG_SUFFIX " does not exist"
-static const char *
+const char *
MR_trace_bad_path(const char *path)
{
static char buffer[BAD_PATH_BUFFER_SIZE];
@@ -1133,7 +1167,7 @@
const char *
MR_trace_browse_all(FILE *out, MR_Browser browser, MR_Browse_Format format)
{
- int i;
+ int var_num;
if (MR_point.MR_point_problem != NULL) {
return MR_point.MR_point_problem;
@@ -1143,9 +1177,10 @@
fprintf(out, "mdb: there are no live variables.\n");
}
- for (i = 0; i < MR_point.MR_point_var_count; i++) {
- (void) MR_trace_browse_var(out, MR_TRUE, &MR_point.MR_point_vars[i],
- NULL, browser, MR_BROWSE_CALLER_PRINT_ALL, format);
+ for (var_num = 0; var_num < MR_point.MR_point_var_count; var_num++) {
+ (void) MR_trace_browse_var(out, MR_TRUE,
+ &MR_point.MR_point_vars[var_num], NULL, browser,
+ MR_BROWSE_CALLER_PRINT_ALL, format);
}
return NULL;
@@ -1167,24 +1202,22 @@
return MR_trace_browse_all(out, MR_trace_print, MR_BROWSE_DEFAULT_FORMAT);
}
-static char *
-MR_trace_browse_var(FILE *out, MR_bool print_var_name, MR_Var_Details *var,
- char *path, MR_Browser browser, MR_Browse_Caller_Type caller,
- MR_Browse_Format format)
+char *
+MR_select_specified_subterm(char *path, MR_TypeInfo type_info, MR_Word *value,
+ MR_TypeInfo *sub_type_info, MR_Word **sub_value)
{
- MR_TypeInfo typeinfo;
- MR_TypeInfo new_typeinfo;
- MR_Word *value;
+ MR_TypeInfo new_type_info;
MR_Word *new_value;
char *old_path;
int arg_num;
int len;
- MR_bool saved_io_tabling_enabled;
- typeinfo = var->MR_var_type;
- value = &var->MR_var_value;
+ if (path == NULL) {
+ *sub_value = value;
+ *sub_type_info = type_info;
+ return NULL;
+ }
- if (path != NULL) {
while (*path != '\0') {
old_path = path;
@@ -1210,7 +1243,7 @@
saved_char = *path;
*path = '\0';
- if (! MR_named_arg_num(typeinfo, value, old_path, &arg_num))
+ if (! MR_named_arg_num(type_info, value, old_path, &arg_num))
{
*path = saved_char;
return old_path;
@@ -1224,15 +1257,37 @@
path++; /* step over / or ^ */
}
- if (MR_arg(typeinfo, value, arg_num, &new_typeinfo,
- &new_value, MR_NONCANON_CC))
+ if (MR_arg(type_info, value, arg_num, &new_type_info, &new_value,
+ MR_NONCANON_CC))
{
- typeinfo = new_typeinfo;
+ type_info = new_type_info;
value = new_value;
} else {
return old_path;
}
}
+
+ *sub_value = value;
+ *sub_type_info = type_info;
+ return NULL;
+}
+
+static char *
+MR_trace_browse_var(FILE *out, MR_bool print_var_name, MR_Var_Details *var,
+ char *path, MR_Browser browser, MR_Browse_Caller_Type caller,
+ MR_Browse_Format format)
+{
+ MR_TypeInfo type_info;
+ MR_Word *value;
+ int len;
+ MR_bool saved_io_tabling_enabled;
+ char *bad_path;
+
+ bad_path = MR_select_specified_subterm(path, var->MR_var_type,
+ &var->MR_var_value, &type_info, &value);
+
+ if (bad_path != NULL) {
+ return bad_path;
}
if (print_var_name) {
@@ -1262,7 +1317,7 @@
saved_io_tabling_enabled = MR_io_tabling_enabled;
MR_io_tabling_enabled = MR_FALSE;
- (*browser)((MR_Word) typeinfo, *value, caller, format);
+ (*browser)((MR_Word) type_info, *value, caller, format);
MR_io_tabling_enabled = saved_io_tabling_enabled;
return NULL;
}
Index: trace/mercury_trace_vars.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_vars.h,v
retrieving revision 1.26
diff -u -b -r1.26 mercury_trace_vars.h
--- trace/mercury_trace_vars.h 19 Jul 2004 03:37:55 -0000 1.26
+++ trace/mercury_trace_vars.h 30 Jan 2005 06:14:36 -0000
@@ -30,9 +30,10 @@
** in the third set.
**
** The functions MR_trace_var_count, MR_trace_list_vars,
-** MR_trace_return_var_info, MR_trace_headvar_num, MR_trace_parse_browse_one,
-** MR_trace_browse_one and MR_trace_browse_all all work in the context
-** established by MR_trace_init_point_vars and possibly MR_trace_set_level.
+** MR_trace_return_var_info, MR_trace_headvar_num, MR_trace_parse_var_path,
+** MR_trace_parse_browse_one, MR_trace_browse_one and MR_trace_browse_all
+** all work in the context established by MR_trace_init_point_vars and
+** possibly MR_trace_set_level.
**
** This context may say that there is no information available about
** the variables live at the current location (this is possible if the
@@ -181,8 +182,19 @@
MR_Browse_Format format);
/*
+** Parse the given word into a variable specification and the specification
+** of a path within that variable. The variable is specified by either its name
+** or its sequence number in the set of live variables at the current point;
+** the desired part is specified by zero or more suffixes of the form
+** ^argnum or /argnum.
+*/
+
+extern const char *MR_trace_parse_var_path(char *word_spec,
+ MR_Var_Spec *var_spec, char **path);
+
+/*
** Print the (names and) values of (the specified parts of) the specified
-** variables. (The variable is specified by either its name or its sequence
+** variable. (The variable is specified by either its name or its sequence
** number in the set of live variables at the current point; the desired part
** is specified by zero or more suffixes of the form ^argnum or /argnum.
**
@@ -230,6 +242,7 @@
extern const char *MR_trace_browse_all(FILE *out, MR_Browser browser,
MR_Browse_Format format);
+
/*
** Sets the current set of variables to be ones live at the program point
** referred to by level_layout, base_sp and base_curfr arguments, and then
@@ -242,6 +255,33 @@
const MR_Label_Layout *level_layout,
MR_Word *base_sp, MR_Word *base_curfr,
int ancestor_level, MR_bool print_optionals);
+
+/*
+** If the given variable specification is unambiguous, then set *value to
+** the value of the specified variable, and set *type_info to its type.
+*/
+
+extern const char *MR_lookup_unambiguous_var_spec(MR_Var_Spec var_spec,
+ MR_TypeInfo *type_info, MR_Word *value);
+
+/*
+** *value and type_info describe a term, and path specifies a subterm of that
+** term. If the path is valid, return NULL and put the specified subterm in
+** *sub_value and **sub_type_info. If it is not valid, return the invalid part
+** of the path specification. This can be turned into an error message with
+** MR_trace_bad_path.
+*/
+
+extern char *MR_select_specified_subterm(char *path,
+ MR_TypeInfo type_info, MR_Word *value,
+ MR_TypeInfo *sub_type_info,
+ MR_Word **sub_value);
+
+/*
+** Given an invalid path specification, return an error message for that error.
+*/
+
+extern const char *MR_trace_bad_path(const char *path);
/*
** Print the size of the specified variable(s) to the specified file.
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