[m-rev.] for post-commit review: regularize mdb commands for browser parameters

Zoltan Somogyi zs at cs.mu.OZ.AU
Tue Apr 4 17:26:01 AEST 2006


For both branches.

browser/declarative_tree.m:
	Fix references to predicates that have been moved to other modules
	in the standard library.

Replace the "set" command of mdb with a bunch of commands: the `format',
`format_param', `list_context_lines', `list_path', `xml_browser_cmd',
`xml_tmp_filename', `fail_trace_counts', `pass_trace_counts' and
`max_io_actions' commands. Each of these set just one parameter
or one of set of closely related parameters.

Move all these commands, and some existing commands that set parameters
that were elsewhere, to the "parameter" command category.

Extend some of these commands so that if given no arguments, they report
the current values of the parameters they would otherwise set. 

Replace the "set" commands of the mdb browser and of the declarative debugger
with a bunch of commands: "format", "depth", "size", "width", "lines",
"actions" and "params" (the last prints the current value of the parameters).

For each category of mdb commands, create files mercury_trace_cmd_<cat>.[ch],
and move the functions dealing with that category of commands there from
mercury_trace_internal.c. Give each of these new files a logical structure
that was sometimes missing from the relevant parts of mercury_trace_internal.c.

NEWS:
	Mention these changes.

doc/mdb_categories:
	Document these changes.

doc/user_guide.texi:
	Document these changes.

	Fix an old documentation bug: you couldn't set listing paramaters
	from a declarative debugger command.

	Fix an old documentation bug: the description of the goal_path step
	for scopes was obsolete.

	Fix some obsolete references to : as module qualifier.

browser/parse.m:
	Update the browser command set along the lines at the top.

browser/declarative_user.m:
	Update the declarative debugger command set along the lines at the top.

	Move the declaration for the type representing declarative debugger
	commands to near the top of the file.

browser/browser_info.m:
	Provide some access predicates.

	Update the predicate that generates mdb commands to save the persistent
	state of the debugger to generate the new forms of parameter commands.

	Move types and predicates for dealing with browser parameters from
	browse.m to here, so that declarative_user.m can use them too.

browser/browse.m:
	Delete the code moved to browser_info.m, and conform to the other
	changes in the other modules.

browser/listing.m:
	Provide a predicate to return the type of listing paths.

scripts/mdbrc.in:
	Update the commands that set the XML parameters.

scripts/Mmakefile:
	Get mmake to rebuild mdbrc from mdbrc.in when mdbrc.in changes.

trace/mercury_trace_internal.c:
trace/mercury_trace_cmds.h:
trace/mercury_trace_cmd_*.[ch]:
	Implement the changes described at the top.

	Fix an old bug: the commands that update the search path for the "list"
	command don't make the search path term permanent, which is needed in
	non-conservative-gc grades.

trace/mercury_trace_spy.c:
	Fix some obsolete references to : as module qualifier.

trace/mercury_trace_browse.[ch]:
	Delete the functionality now moved to mercury_trace_cmd_parameter.c.

tests/debugger/mdb_command_test.inp:
	Update the set of commands being tested.

tests/debugger/save.{inp,exp}:
	Update the parameter commands in this test case.

cvs diff: Diffing .
Index: NEWS
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/NEWS,v
retrieving revision 1.409
diff -u -b -r1.409 NEWS
--- NEWS	31 Mar 2006 05:12:07 -0000	1.409
+++ NEWS	1 Apr 2006 11:14:33 -0000
@@ -61,6 +61,10 @@
   left the goal at which the term was available as the value of a program
   variable.
 * Users can now see the set of places where two terms differ from each other.
+* The `set' command has been replaced by several other commands: the `format',
+  `format_param', `list_context_lines', `list_path', `xml_browser_cmd',
+  `xml_tmp_filename', `fail_trace_counts', `pass_trace_counts' and
+  `max_io_actions' commands.
 * The `save_to_file' command has been renamed the `dump' command.
 * The `save' command now saves the entire persistent state of the debugger
   (with one small exception that cannot be reestablished by an mdb command from
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/browse.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/browser/browse.m,v
retrieving revision 1.59
diff -u -b -r1.59 browse.m
--- browser/browse.m	31 Mar 2006 05:12:09 -0000	1.59
+++ browser/browse.m	2 Apr 2006 03:22:03 -0000
@@ -215,26 +215,6 @@
 
 %---------------------------------------------------------------------------%
 %
-% If the term browser is called from the internal debugger, input is
-% done via a call to the readline library (if available), using streams
-% MR_mdb_in and MR_mdb_out.  If it is called from the external debugger,
-% Input/Output are done via MR_debugger_socket_in/MR_debugger_socket_out.
-% In the latter case we need to output terms; their type is
-% term_browser_response.
-
-:- type term_browser_response
-    --->    browser_str(string)
-    ;       browser_int(int)
-    ;       browser_nl
-    ;       browser_end_command
-    ;       browser_quit.
-
-:- type debugger
-    --->    internal
-    ;       external.
-
-%---------------------------------------------------------------------------%
-%
 % Saving terms to files
 %
 
@@ -614,18 +594,8 @@
         help(Debugger, !IO),
         Quit = no
     ;
-        Command = set,
-        show_settings(Debugger, !.Info, !IO),
-        Quit = no
-    ;
-        Command = set(MaybeOptionTable, Setting),
-        (
-            MaybeOptionTable = ok(OptionTable),
-            set_browse_param(OptionTable, Setting, !Info)
-        ;
-            MaybeOptionTable = error(Msg),
-            write_string_debugger(Debugger, Msg, !IO)
-        ),
+        Command = param_command(ParamCmd),
+        run_param_command(Debugger, ParamCmd, yes, !Info, !IO),
         Quit = no
     ;
         Command = cd,
@@ -770,27 +740,25 @@
 
 bool_format_option_is_true(Format - bool(yes), Format).
 
-:- pred set_browse_param(option_table(setting_option)::in, setting::in,
-    browser_info::in, browser_info::out) is det.
-
-set_browse_param(OptionTable, Setting, !Info) :-
-    set_browser_param_from_option_table(yes, OptionTable, Setting,
-        !.Info ^ state, NewState),
-    !:Info = !.Info ^ state := NewState.
-
 :- pred help(debugger::in, io::di, io::uo) is det.
 
-help(Debugger) -->
-    { string.append_list([
+help(Debugger, !IO) :-
+    string.append_list([
 "Commands are:\n",
 "\t[print|p|ls] [format_options] [path]\n",
 "\t               -- print the specified subterm using the `browse' params\n",
 "\tcd [path]      -- cd to the specified subterm (default is root)\n",
 "\tcdr n path     -- repeatedly apply the cd command n times\n",
 "\tpwd            -- print the path to the current subterm\n",
-"\tset [setting_options] var value\n",
+"\tformat [format_options] <flat|raw-prety|verbose|pretty>\n",
+"\t               -- set the format\n",
+"\tdepth [format_param_options] <n>\n",
+"\tsize  [format_param_options] <n>\n",
+"\twidth [format_param_options] <n>\n",
+"\tlines [format_param_options] <n>\n",
+"\tnum_io_actions <n>\n",
 "\t               -- set a parameter value\n",
-"\tset            -- show parameter values\n",
+"\tparams         -- show format and parameter values\n",
 "\tmark [path]    -- mark the given subterm (default is current) and quit\n",
 "\tmode [path]    -- show the mode of a subterm (default is current)\n",
 "\tquit           -- quit browser\n",
@@ -802,14 +770,10 @@
 "\t?              -- help\n",
 "\th              -- help\n",
 "\n",
-"-- Parameter variables with integer values:\n",
-"--  size <n>; depth <n>; path <n>; width <n>; lines <n>; num_io_actions <n>;\n",
-"-- Parameter variables with non-integer values:\n",
-"--  format <flat,raw_pretty,verbose,pretty>;\n",
 "-- Paths can be Unix-style or SICStus-style: /2/3/1 or ^2^3^1\n",
 "\n"],
-        HelpMessage) },
-    write_string_debugger(Debugger, HelpMessage).
+        HelpMessage),
+    write_string_debugger(Debugger, HelpMessage, !IO).
 
 %---------------------------------------------------------------------------%
 %
@@ -1336,60 +1300,6 @@
 % Miscellaneous path handling
 %
 
-:- pred write_path(debugger::in, list(dir)::in, io::di, io::uo) is det.
-
-write_path(Debugger, [], !IO) :-
-    write_string_debugger(Debugger, "/", !IO).
-write_path(Debugger, [Dir], !IO) :-
-    (
-        Dir = parent,
-        write_string_debugger(Debugger, "/", !IO)
-    ;
-        Dir = child_num(N),
-        write_string_debugger(Debugger, "/", !IO),
-        write_int_debugger(Debugger, N, !IO)
-    ;
-        Dir = child_name(Name),
-        write_string_debugger(Debugger, "/", !IO),
-        write_string_debugger(Debugger, Name, !IO)
-    ).
-write_path(Debugger, [Dir, Dir2 | Dirs], !IO) :-
-    write_path_2(Debugger, [Dir, Dir2 | Dirs], !IO).
-
-:- pred write_path_2(debugger::in, list(dir)::in, io::di, io::uo) is det.
-
-write_path_2(Debugger, [], !IO) :-
-    write_string_debugger(Debugger, "/", !IO).
-write_path_2(Debugger, [Dir], !IO) :-
-    (
-        Dir = parent,
-        write_string_debugger(Debugger, "/..", !IO)
-    ;
-        Dir = child_num(N),
-        write_string_debugger(Debugger, "/", !IO),
-        write_int_debugger(Debugger, N, !IO)
-    ;
-        Dir = child_name(Name),
-        write_string_debugger(Debugger, "/", !IO),
-        write_string_debugger(Debugger, Name, !IO)
-    ).
-write_path_2(Debugger, [Dir, Dir2 | Dirs], !IO) :-
-    (
-        Dir = parent,
-        write_string_debugger(Debugger, "/..", !IO),
-        write_path_2(Debugger, [Dir2 | Dirs], !IO)
-    ;
-        Dir = child_num(N),
-        write_string_debugger(Debugger, "/", !IO),
-        write_int_debugger(Debugger, N, !IO),
-        write_path_2(Debugger, [Dir2 | Dirs], !IO)
-    ;
-        Dir = child_name(Name),
-        write_string_debugger(Debugger, "/", !IO),
-        write_string_debugger(Debugger, Name, !IO),
-        write_path_2(Debugger, [Dir2 | Dirs], !IO)
-    ).
-
 :- type deref_result(T)
     --->    deref_result(T)
     ;       deref_error(list(dir), dir).
@@ -1574,8 +1484,8 @@
     write_string_debugger(Debugger, pad_right("", ' ', row_name_len), !IO),
     write_string_debugger(Debugger, pad_right("depth", ' ', depth_len), !IO),
     write_string_debugger(Debugger, pad_right("size", ' ', size_len), !IO),
-    write_string_debugger(Debugger, pad_right("x clip", ' ', x_len), !IO),
-    write_string_debugger(Debugger, pad_right("y clip", ' ', y_len), !IO),
+    write_string_debugger(Debugger, pad_right("x clip", ' ', width_len), !IO),
+    write_string_debugger(Debugger, pad_right("y clip", ' ', lines_len), !IO),
     nl_debugger(Debugger, !IO),
 
     show_settings_caller_format(Debugger, Info, Caller, CallerName,
@@ -1605,24 +1515,24 @@
     write_string_debugger(Debugger,
         pad_right(int_to_string(Params ^ size), ' ', size_len), !IO),
     write_string_debugger(Debugger,
-        pad_right(int_to_string(Params ^ width), ' ', x_len), !IO),
+        pad_right(int_to_string(Params ^ width), ' ', width_len), !IO),
     write_string_debugger(Debugger,
-        pad_right(int_to_string(Params ^ lines), ' ', y_len), !IO),
+        pad_right(int_to_string(Params ^ lines), ' ', lines_len), !IO),
     nl_debugger(Debugger, !IO).
 
 :- func row_name_len = int.
 :- func centering_len = int.
 :- func depth_len = int.
 :- func size_len = int.
-:- func x_len = int.
-:- func y_len = int.
+:- func width_len = int.
+:- func lines_len = int.
 
 row_name_len  = 30.
 centering_len =  3.
 depth_len     = 10.
 size_len      = 10.
-x_len         = 10.
-y_len         = 10.
+width_len     = 10.
+lines_len     = 10.
 
 :- pred string_to_path(string::in, path::out) is semidet.
 
@@ -1732,13 +1642,6 @@
 
 %---------------------------------------------------------------------------%
 
-:- pred write_string_debugger(debugger::in, string::in, io::di, io::uo) is det.
-
-write_string_debugger(internal, String, !IO) :-
-    io.write_string(String, !IO).
-write_string_debugger(external, String, !IO) :-
-    send_term_to_socket(browser_str(String), !IO).
-
 :- pred write_term_mode_debugger(debugger::in, maybe(browser_mode_func)::in,
     list(dir)::in, io::di, io::uo) is det.
 
@@ -1760,47 +1663,6 @@
 browser_mode_to_string(output) = "Output".
 browser_mode_to_string(not_applicable) = "Not Applicable".
 browser_mode_to_string(unbound) = "Unbound".
-
-:- pred nl_debugger(debugger::in, io::di, io::uo) is det.
-
-nl_debugger(internal, !IO) :-
-    io.nl(!IO).
-nl_debugger(external, !IO) :-
-    send_term_to_socket(browser_nl, !IO).
-
-:- pred write_int_debugger(debugger::in, int::in, io::di, io::uo) is det.
-
-write_int_debugger(internal, Int, !IO) :-
-    io.write_int(Int, !IO).
-write_int_debugger(external, Int, !IO) :-
-    send_term_to_socket(browser_int(Int), !IO).
-
-:- pred print_format_debugger(debugger::in, portray_format::in,
-    io::di, io::uo) is det.
-
-print_format_debugger(internal, X, !IO) :-
-    io.print(X, !IO).
-print_format_debugger(external, X, !IO) :-
-    (
-        X = flat,
-        send_term_to_socket(browser_str("flat"), !IO)
-    ;
-        X = raw_pretty,
-        send_term_to_socket(browser_str("raw_pretty"), !IO)
-    ;
-        X = verbose,
-        send_term_to_socket(browser_str("verbose"), !IO)
-    ;
-        X = pretty,
-        send_term_to_socket(browser_str("pretty"), !IO)
-    ).
-
-:- pred send_term_to_socket(term_browser_response::in, io::di, io::uo) is det.
-
-send_term_to_socket(Term, !IO) :-
-    write(Term, !IO),
-    print(".\n", !IO),
-    flush_output(!IO).
 
 %---------------------------------------------------------------------------%
 
Index: browser/browser_info.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/browser/browser_info.m,v
retrieving revision 1.26
diff -u -b -r1.26 browser_info.m
--- browser/browser_info.m	31 Mar 2006 05:12:10 -0000	1.26
+++ browser/browser_info.m	2 Apr 2006 04:07:03 -0000
@@ -149,12 +149,9 @@
 :- type setting
     --->    depth(int)
     ;       size(int)
-    ;       format(portray_format)
     ;       width(int)
     ;       lines(int)
-    ;       num_io_actions(int)
-    ;       xml_browser_cmd(string)
-    ;       xml_tmp_filename(string).
+    ;       format(portray_format).
 
     % Initialise a new browser_info.  The optional portray_format
     % overrides the default format.
@@ -181,7 +178,7 @@
 
 %---------------------------------------------------------------------------%
 
-    % An data type that holds persistent browser settings.
+    % A data type that holds persistent browser settings.
     % This state must be saved by the caller of the browse module
     % between calls.
     %
@@ -229,6 +226,74 @@
     option_table(setting_option)::in, setting::in,
     browser_persistent_state::in, browser_persistent_state::out) is det.
 
+:- pred info_set_browse_param(option_table(setting_option)::in,
+    setting::in, browser_info::in, browser_info::out) is det.
+
+:- pred info_set_num_io_actions(int::in,
+    browser_info::in, browser_info::out) is det.
+
+:- pred info_set_xml_browser_cmd(string::in,
+    browser_info::in, browser_info::out) is det.
+
+:- pred info_set_xml_tmp_filename(string::in,
+    browser_info::in, browser_info::out) is det.
+
+:- pred get_num_io_actions(browser_persistent_state::in, int::out) is det.
+:- pred set_num_io_actions(int::in,
+    browser_persistent_state::in, browser_persistent_state::out) is det.
+
+:- type param_cmd
+    --->    format(maybe_option_table(setting_option), setting)
+    ;       format_param(maybe_option_table(setting_option), setting)
+    ;       num_io_actions(int)
+    ;       print_params.
+% We can't set the browser command from within the browser because we parse
+% user commands from the browser by breaking them up into words at whitespace,
+% which doesn't respect quotation marks. Since the browser command will usually
+% include spaces, this parsing method would need to be changed before we could
+% include xml_browser_cmd here. And until we handle xml_browser_cmd, there is
+% no point in handling xml_tmp_filename.
+%
+%   ;       xml_browser_cmd(string)
+%   ;       xml_tmp_filename(string)
+
+:- type debugger
+    --->    internal
+    ;       external.
+%
+% If the term browser is called from the internal debugger, input is
+% done via a call to the readline library (if available), using streams
+% MR_mdb_in and MR_mdb_out.  If it is called from the external debugger,
+% Input/Output are done via MR_debugger_socket_in/MR_debugger_socket_out.
+% In the latter case we need to output terms; their type is
+% term_browser_response.
+
+:- type term_browser_response
+    --->    browser_str(string)
+    ;       browser_int(int)
+    ;       browser_nl
+    ;       browser_end_command
+    ;       browser_quit.
+
+:- pred run_param_command(debugger::in, param_cmd::in, bool::in,
+    browser_info::in, browser_info::out, io::di, io::uo) is det.
+
+:- pred show_settings(debugger::in, bool::in, browser_info::in,
+    io::di, io::uo) is det.
+
+:- pred nl_debugger(debugger::in, io::di, io::uo) is det.
+
+:- pred write_string_debugger(debugger::in, string::in, io::di, io::uo) is det.
+
+:- pred write_int_debugger(debugger::in, int::in, io::di, io::uo) is det.
+
+:- pred print_format_debugger(debugger::in, portray_format::in,
+    io::di, io::uo) is det.
+
+:- pred write_path(debugger::in, list(dir)::in, io::di, io::uo) is det.
+
+:- pred send_term_to_socket(term_browser_response::in, io::di, io::uo) is det.
+
 :- pred browser_params_to_string(browser_persistent_state::in, bool::in,
     string::out) is det.
 
@@ -319,6 +384,27 @@
 set_lines_from_mdb(P, B, A, F, Pr, V, NPr, Lines, !Browser) :-
     set_browser_param(no, P, B, A, F, Pr, V, NPr, lines(Lines), !Browser).
 
+info_set_browse_param(OptionTable, Setting, !Info) :-
+    PersistentState0 = !.Info ^ state,
+    set_browser_param_from_option_table(yes, OptionTable, Setting,
+        PersistentState0, PersistentState),
+    !:Info = !.Info ^ state := PersistentState.
+
+info_set_num_io_actions(N, !Info) :-
+    PersistentState0 = !.Info ^ state,
+    set_num_io_actions(N, PersistentState0, PersistentState),
+    !:Info = !.Info ^ state := PersistentState.
+
+info_set_xml_browser_cmd(Cmd, !Info) :-
+    PersistentState0 = !.Info ^ state,
+    set_xml_browser_cmd_from_mdb(Cmd, PersistentState0, PersistentState),
+    !:Info = !.Info ^ state := PersistentState.
+
+info_set_xml_tmp_filename(FileName, !Info) :-
+    PersistentState0 = !.Info ^ state,
+    set_xml_tmp_filename_from_mdb(FileName, PersistentState0, PersistentState),
+    !:Info = !.Info ^ state := PersistentState.
+
 :- pred set_format_from_mdb(bool::in, bool::in, bool::in, portray_format::in,
     browser_persistent_state::in, browser_persistent_state::out) is det.
 :- pragma export(set_format_from_mdb(in, in, in, in, in, out),
@@ -328,14 +414,32 @@
     % Any format flags are ignored for this parameter.
     set_browser_param(no, P, B, A, no, no, no, no, format(Format), !Browser).
 
-:- pred set_num_io_actions_from_mdb(int::in,
-    browser_persistent_state::in, browser_persistent_state::out) is det.
-:- pragma export(set_num_io_actions_from_mdb(in, in, out),
-    "ML_BROWSE_set_num_io_actions_from_mdb").
+:- pragma export(get_num_io_actions(in, out),
+    "ML_BROWSE_get_num_io_actions").
+
+get_num_io_actions(Browser, NumIOActions) :-
+    NumIOActions = Browser ^ num_printed_io_actions.
 
-set_num_io_actions_from_mdb(NumIOActions, !Browser) :-
+:- pragma export(set_num_io_actions(in, in, out),
+    "ML_BROWSE_set_num_io_actions").
+
+set_num_io_actions(NumIOActions, !Browser) :-
     !:Browser = !.Browser ^ num_printed_io_actions := NumIOActions.
 
+:- pred get_xml_browser_cmd_from_mdb(browser_persistent_state::in,
+    string::out) is det.
+:- pragma export(get_xml_browser_cmd_from_mdb(in, out),
+    "ML_BROWSE_get_xml_browser_cmd_from_mdb").
+
+get_xml_browser_cmd_from_mdb(Browser, Command) :-
+    MaybeCommand = Browser ^ xml_browser_cmd,
+    (
+        MaybeCommand = no,
+        Command = ""
+    ;
+        MaybeCommand = yes(Command)
+    ).
+
 :- pred set_xml_browser_cmd_from_mdb(string::in,
     browser_persistent_state::in, browser_persistent_state::out) is det.
 :- pragma export(set_xml_browser_cmd_from_mdb(in, in, out),
@@ -348,6 +452,20 @@
         !:Browser = !.Browser ^ xml_browser_cmd := yes(Command)
     ).
 
+:- pred get_xml_tmp_filename_from_mdb(browser_persistent_state::in,
+    string::out) is det.
+:- pragma export(get_xml_tmp_filename_from_mdb(in, out),
+    "ML_BROWSE_get_xml_tmp_filename_from_mdb").
+
+get_xml_tmp_filename_from_mdb(Browser, FileName) :-
+    MaybeFileName = Browser ^ xml_tmp_filename,
+    (
+        MaybeFileName = no,
+        FileName = ""
+    ;
+        MaybeFileName = yes(FileName)
+    ).
+
 :- pred set_xml_tmp_filename_from_mdb(string::in,
     browser_persistent_state::in, browser_persistent_state::out) is det.
 :- pragma export(set_xml_tmp_filename_from_mdb(in, in, out),
@@ -491,13 +609,6 @@
 
 set_browser_param(FromBrowser, P0, B0, A0, F0, Pr0, V0, NPr0, Setting,
         !State) :-
-    ( Setting = num_io_actions(NumIoActions) ->
-        !:State = !.State ^ num_printed_io_actions := NumIoActions
-    ; Setting = xml_browser_cmd(CommandStr) ->
-        !:State = !.State ^ xml_browser_cmd := yes(CommandStr)
-    ; Setting = xml_tmp_filename(CommandStr) ->
-        !:State = !.State ^ xml_tmp_filename := yes(CommandStr)
-    ;
         (
             FromBrowser = no,
             default_all_yes(P0, B0, A0, P, B, A)
@@ -524,8 +635,7 @@
         maybe_set_param(A, F, Pr, V, NPr, Setting, AParams0, AParams),
         !:State = browser_persistent_state(PParams, BParams, AParams,
             !.State ^ num_printed_io_actions,
-            !.State ^ xml_browser_cmd, !.State ^ xml_tmp_filename)
-    ).
+        !.State ^ xml_browser_cmd, !.State ^ xml_tmp_filename).
 
 set_browser_param_maybe_caller_type(FromBrowser, MaybeCallerType,
         F0, Pr0, V0, NPr0, Setting, !State) :-
@@ -536,13 +646,13 @@
 set_browser_param_from_option_table(FromBrowser, OptionTable, Setting,
         !State) :-
     set_browser_param(FromBrowser,
-        lookup_bool_option(OptionTable, print):bool,
-        lookup_bool_option(OptionTable, browse):bool,
-        lookup_bool_option(OptionTable, print_all):bool,
-        lookup_bool_option(OptionTable, flat):bool,
-        lookup_bool_option(OptionTable, raw_pretty):bool,
-        lookup_bool_option(OptionTable, verbose):bool,
-        lookup_bool_option(OptionTable, pretty):bool,
+        lookup_bool_option(OptionTable, set_print):bool,
+        lookup_bool_option(OptionTable, set_browse):bool,
+        lookup_bool_option(OptionTable, set_print_all):bool,
+        lookup_bool_option(OptionTable, set_flat):bool,
+        lookup_bool_option(OptionTable, set_raw_pretty):bool,
+        lookup_bool_option(OptionTable, set_verbose):bool,
+        lookup_bool_option(OptionTable, set_pretty):bool,
         Setting, !State).
 
 :- pred affected_caller_types(bool::in, maybe(browse_caller_type)::in,
@@ -635,12 +745,6 @@
     error("maybe_set_param_2: cannot set format here").
 maybe_set_param_2(yes, width(W), Params, Params ^ width := W).
 maybe_set_param_2(yes, lines(L), Params, Params ^ lines := L).
-maybe_set_param_2(yes, num_io_actions(_), _, _) :-
-    error("maybe_set_param_2: num_io_actions").
-maybe_set_param_2(yes, xml_browser_cmd(_), _, _) :-
-    error("maybe_set_param_2: xml_browser_cmd").
-maybe_set_param_2(yes, xml_tmp_filename(_), _, _) :-
-    error("maybe_set_param_2: xml_tmp_filename").
 
 :- pred get_caller_params(browser_persistent_state::in, browse_caller_type::in,
     caller_params::out) is det.
@@ -662,6 +766,218 @@
 
 %---------------------------------------------------------------------------%
 
+run_param_command(Debugger, ParamCmd, ShowPath, !PersistentState, !IO) :-
+    (
+        ParamCmd = format(MaybeOptionTable, Setting),
+        (
+            MaybeOptionTable = ok(OptionTable),
+            info_set_browse_param(OptionTable, Setting, !PersistentState)
+        ;
+            MaybeOptionTable = error(Msg),
+            write_string_debugger(Debugger, Msg, !IO)
+        )
+    ;
+        ParamCmd = format_param(MaybeOptionTable, Setting),
+        (
+            MaybeOptionTable = ok(OptionTable),
+            info_set_browse_param(OptionTable, Setting, !PersistentState)
+        ;
+            MaybeOptionTable = error(Msg),
+            write_string_debugger(Debugger, Msg, !IO)
+        )
+    ;
+        ParamCmd = num_io_actions(N),
+        info_set_num_io_actions(N, !PersistentState)
+    ;
+        ParamCmd = print_params,
+        show_settings(Debugger, ShowPath, !.PersistentState, !IO)
+%   ;
+%       ParamCmd = xml_browser_cmd(Cmd),
+%       set_xml_browser_cmd(Cmd, !PersistentState)
+%   ;
+%       ParamCmd = xml_tmp_filename(FileName),
+%       set_xml_tmp_filename(FileName, !PersistentState)
+    ).
+
+%---------------------------------------------------------------------------%
+%
+% Display predicates.
+%
+
+show_settings(Debugger, ShowPath, Info, !IO) :-
+    show_settings_caller(Debugger, Info, browse, "Browser", !IO),
+    show_settings_caller(Debugger, Info, print, "Print", !IO),
+    show_settings_caller(Debugger, Info, print_all, "Printall", !IO),
+
+    write_string_debugger(Debugger,
+        "Number of I/O actions printed is: ", !IO),
+    write_int_debugger(Debugger,
+        get_num_printed_io_actions(Info ^ state), !IO),
+    nl_debugger(Debugger, !IO),
+
+    (
+        ShowPath = yes,
+        write_string_debugger(Debugger, "Current path is: ", !IO),
+        write_path(Debugger, Info ^ dirs, !IO),
+        nl_debugger(Debugger, !IO)
+    ;
+        ShowPath = no
+    ).
+
+:- pred show_settings_caller(debugger::in, browser_info::in,
+    browse_caller_type::in, string::in, io::di, io::uo) is det.
+
+show_settings_caller(Debugger, Info, Caller, CallerName, !IO) :-
+    browser_info.get_format(Info, Caller, no, Format),
+    write_string_debugger(Debugger, CallerName ++ " default format: ", !IO),
+    print_format_debugger(Debugger, Format, !IO),
+    nl_debugger(Debugger, !IO),
+
+    write_string_debugger(Debugger, pad_right("", ' ', row_name_len), !IO),
+    write_string_debugger(Debugger, pad_right(" ", ' ', centering_len), !IO),
+    write_string_debugger(Debugger, pad_right("depth", ' ', depth_len), !IO),
+    write_string_debugger(Debugger, pad_right("size", ' ', size_len), !IO),
+    write_string_debugger(Debugger, pad_right("width", ' ', width_len), !IO),
+    write_string_debugger(Debugger, pad_right("lines", ' ', lines_len), !IO),
+    nl_debugger(Debugger, !IO),
+
+    show_settings_caller_format(Debugger, Info, Caller, CallerName,
+        flat, "flat", !IO),
+    show_settings_caller_format(Debugger, Info, Caller, CallerName,
+        verbose, "verbose", !IO),
+    show_settings_caller_format(Debugger, Info, Caller, CallerName,
+        pretty, "pretty", !IO),
+    show_settings_caller_format(Debugger, Info, Caller, CallerName,
+        raw_pretty, "raw_pretty", !IO),
+    nl_debugger(Debugger, !IO).
+
+:- pred show_settings_caller_format(debugger::in, browser_info::in,
+    browse_caller_type::in, string::in, portray_format::in, string::in,
+    io::di, io::uo) is det.
+
+show_settings_caller_format(Debugger, Info, Caller, CallerName,
+        Format, FormatName, !IO) :-
+    browser_info.get_format_params(Info, Caller, Format, Params),
+    write_string_debugger(Debugger,
+        pad_right(CallerName ++ " " ++ FormatName ++ ":", ' ', row_name_len),
+        !IO),
+    write_string_debugger(Debugger,
+        pad_right(" ", ' ', centering_len), !IO),
+    write_string_debugger(Debugger,
+        pad_right(int_to_string(Params ^ depth), ' ', depth_len), !IO),
+    write_string_debugger(Debugger,
+        pad_right(int_to_string(Params ^ size), ' ', size_len), !IO),
+    write_string_debugger(Debugger,
+        pad_right(int_to_string(Params ^ width), ' ', width_len), !IO),
+    write_string_debugger(Debugger,
+        pad_right(int_to_string(Params ^ lines), ' ', lines_len), !IO),
+    nl_debugger(Debugger, !IO).
+
+:- func row_name_len = int.
+:- func centering_len = int.
+:- func depth_len = int.
+:- func size_len = int.
+:- func width_len = int.
+:- func lines_len = int.
+
+row_name_len  = 30.
+centering_len =  3.
+depth_len     = 10.
+size_len      = 10.
+width_len     = 10.
+lines_len     = 10.
+
+nl_debugger(internal, !IO) :-
+    io.nl(!IO).
+nl_debugger(external, !IO) :-
+    send_term_to_socket(browser_nl, !IO).
+
+write_string_debugger(internal, String, !IO) :-
+    io.write_string(String, !IO).
+write_string_debugger(external, String, !IO) :-
+    send_term_to_socket(browser_str(String), !IO).
+
+write_int_debugger(internal, Int, !IO) :-
+    io.write_int(Int, !IO).
+write_int_debugger(external, Int, !IO) :-
+    send_term_to_socket(browser_int(Int), !IO).
+
+print_format_debugger(internal, X, !IO) :-
+    io.print(X, !IO).
+print_format_debugger(external, X, !IO) :-
+    (
+        X = flat,
+        send_term_to_socket(browser_str("flat"), !IO)
+    ;
+        X = raw_pretty,
+        send_term_to_socket(browser_str("raw_pretty"), !IO)
+    ;
+        X = verbose,
+        send_term_to_socket(browser_str("verbose"), !IO)
+    ;
+        X = pretty,
+        send_term_to_socket(browser_str("pretty"), !IO)
+    ).
+
+write_path(Debugger, [], !IO) :-
+    write_string_debugger(Debugger, "/", !IO).
+write_path(Debugger, [Dir], !IO) :-
+    (
+        Dir = parent,
+        write_string_debugger(Debugger, "/", !IO)
+    ;
+        Dir = child_num(N),
+        write_string_debugger(Debugger, "/", !IO),
+        write_int_debugger(Debugger, N, !IO)
+    ;
+        Dir = child_name(Name),
+        write_string_debugger(Debugger, "/", !IO),
+        write_string_debugger(Debugger, Name, !IO)
+    ).
+write_path(Debugger, [Dir, Dir2 | Dirs], !IO) :-
+    write_path_2(Debugger, [Dir, Dir2 | Dirs], !IO).
+
+:- pred write_path_2(debugger::in, list(dir)::in, io::di, io::uo) is det.
+
+write_path_2(Debugger, [], !IO) :-
+    write_string_debugger(Debugger, "/", !IO).
+write_path_2(Debugger, [Dir], !IO) :-
+    (
+        Dir = parent,
+        write_string_debugger(Debugger, "/..", !IO)
+    ;
+        Dir = child_num(N),
+        write_string_debugger(Debugger, "/", !IO),
+        write_int_debugger(Debugger, N, !IO)
+    ;
+        Dir = child_name(Name),
+        write_string_debugger(Debugger, "/", !IO),
+        write_string_debugger(Debugger, Name, !IO)
+    ).
+write_path_2(Debugger, [Dir, Dir2 | Dirs], !IO) :-
+    (
+        Dir = parent,
+        write_string_debugger(Debugger, "/..", !IO),
+        write_path_2(Debugger, [Dir2 | Dirs], !IO)
+    ;
+        Dir = child_num(N),
+        write_string_debugger(Debugger, "/", !IO),
+        write_int_debugger(Debugger, N, !IO),
+        write_path_2(Debugger, [Dir2 | Dirs], !IO)
+    ;
+        Dir = child_name(Name),
+        write_string_debugger(Debugger, "/", !IO),
+        write_string_debugger(Debugger, Name, !IO),
+        write_path_2(Debugger, [Dir2 | Dirs], !IO)
+    ).
+
+send_term_to_socket(Term, !IO) :-
+    write(Term, !IO),
+    print(".\n", !IO),
+    flush_output(!IO).
+
+%---------------------------------------------------------------------------%
+
 :- pragma export(browser_params_to_string(in, in, out),
     "ML_BROWSE_browser_params_to_string").
 
@@ -671,11 +987,11 @@
     (
         MDBCommandFormat = yes,
         ParamCmds = 
-            caller_params_to_mdb_command("-P", PrintParams) ++
-            caller_params_to_mdb_command("-B", BrowseParams) ++
-            caller_params_to_mdb_command("-A", PrintAllParams),
+            caller_params_to_mdb_command("-P ", PrintParams) ++
+            caller_params_to_mdb_command("-B ", BrowseParams) ++
+            caller_params_to_mdb_command("-A ", PrintAllParams),
         NumIOActionCmd =
-            "set max_io_actions " ++ int_to_string(NumIOActions) ++ "\n",
+            "max_io_actions " ++ int_to_string(NumIOActions) ++ "\n",
         (
             MaybeXMLBrowserCmd = yes(XMLBrowserCmd),
             % XMLBrowserCmd shouldn't be "" if MaybeXMLBrowserCmd is yes,
@@ -683,7 +999,7 @@
             XMLBrowserCmd \= ""
         ->
             XMLBrowserCmdCmd =
-                "set xml_browser_cmd " ++ XMLBrowserCmd ++ "\n"
+                "xml_browser_cmd " ++ XMLBrowserCmd ++ "\n"
         ;
             XMLBrowserCmdCmd = ""
         ),
@@ -694,7 +1010,7 @@
             XMLTmpFileName \= ""
         ->
             XMLTmpFileNameCmd =
-                "set xml_tmp_filename " ++ XMLTmpFileName ++ "\n"
+                "xml_tmp_filename " ++ XMLTmpFileName ++ "\n"
         ;
             XMLTmpFileNameCmd = ""
         ),
@@ -735,15 +1051,15 @@
 :- func caller_params_to_mdb_command(string, caller_params) = string.
 
 caller_params_to_mdb_command(CallerOpt, CallerParams) = Cmds :-
-    CmdCallerOpt = "set " ++ CallerOpt ++ " ",
     CallerParams = caller_params(Format, FlatParams, RawPrettyParams,
         VerboseParams, PrettyParams),
-    FormatCmd = CmdCallerOpt ++ "format " ++ format_to_string(Format) ++ "\n",
+    FormatCmd = "format " ++ CallerOpt ++ format_to_string(Format) ++ "\n",
+    CmdPrefix = "format_param " ++ CallerOpt,
     FormatParamCmds =
-        format_params_to_mdb_command(CmdCallerOpt ++ "-f ", FlatParams) ++
-        format_params_to_mdb_command(CmdCallerOpt ++ "-r ", RawPrettyParams) ++
-        format_params_to_mdb_command(CmdCallerOpt ++ "-v ", VerboseParams) ++
-        format_params_to_mdb_command(CmdCallerOpt ++ "-p ", PrettyParams),
+        format_params_to_mdb_command(CmdPrefix ++ "-f ", FlatParams) ++
+        format_params_to_mdb_command(CmdPrefix ++ "-r ", RawPrettyParams) ++
+        format_params_to_mdb_command(CmdPrefix ++ "-v ", VerboseParams) ++
+        format_params_to_mdb_command(CmdPrefix ++ "-p ", PrettyParams),
     Cmds = FormatCmd ++ FormatParamCmds.
 
 :- func caller_params_to_desc(caller_params) = string.
Index: browser/declarative_user.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/browser/declarative_user.m,v
retrieving revision 1.59
diff -u -b -r1.59 declarative_user.m
--- browser/declarative_user.m	31 Mar 2006 05:12:10 -0000	1.59
+++ browser/declarative_user.m	4 Apr 2006 01:12:48 -0000
@@ -125,6 +125,72 @@
 
 %-----------------------------------------------------------------------------%
 
+:- type user_command
+    --->    yes
+            % The node is correct.
+
+    ;       no
+            % The node is erroneous.
+
+    ;       inadmissible
+            % The node is inadmissible.
+
+    ;       skip
+            % The user has no answer.
+
+    ;       browse_arg(maybe(int))
+            % Browse the nth argument before answering.  Or browse
+            % the whole predicate/function if the maybe is no.
+
+    ;       browse_xml_arg(maybe(int))
+            % Browse the argument using an XML browser.
+
+    ;       browse_io(int)
+            % Browse the nth IO action before answering.
+
+    ;       print_arg(int, int)
+            % Print the nth to the mth arguments before answering.
+
+    ;       print_io(int, int)
+            % Print the nth to the mth IO actions before answering.
+
+    ;       pd
+            % Commence procedural debugging from this point.
+
+    ;       param_command(param_cmd)
+
+    ;       trust_predicate
+            % Trust the predicate being asked about.
+
+    ;       trust_module
+            % Trust the module being asked about.
+
+    ;       info
+            % Print some information about the current question.
+
+    ;       undo
+            % Undo the user's last answer.
+
+    ;       ask
+            % The user wants the current question re-asked.
+
+    ;       change_search(user_search_mode)
+            % Change the current search strategy.
+
+    ;       quit
+            % Abort this diagnosis session.
+
+    ;       help(maybe(string))
+            % Request help before answering.  If the maybe argument
+            % is no then a general help message is displayed,
+            % otherwise help on the given command is displayed.
+
+    ;       empty_command
+            % User just pressed return.
+
+    ;       illegal_command.
+            % None of the above.
+
 :- type user_state
     --->    user(
                 instr               :: io.input_stream,
@@ -264,17 +330,14 @@
     print_atom_arguments(TraceAtom, From, To, !.User, !IO),
     query_user(UserQuestion, Response, !User, !IO).
 
-handle_command(set(MaybeOptionTable, Setting), UserQuestion, Response, !User,
-        !IO) :-
-    (
-        MaybeOptionTable = ok(OptionTable),
-        set_browser_param_from_option_table(no, OptionTable, Setting,
-            !.User ^ browser, Browser),
-        !:User = !.User ^ browser := Browser
-    ;
-        MaybeOptionTable = error(Msg),
-        io.write_string(Msg++"\n", !IO)
-    ),
+handle_command(param_command(ParamCommand), UserQuestion, Response,
+        !User, !IO) :-
+    Browser0 = !.User ^ browser,
+    DummyTerm = synthetic_term("", [], no),
+    Info0 = browser_info(DummyTerm, [], browse, no, Browser0, no_track, no),
+    run_param_command(internal, ParamCommand, no, Info0, Info, !IO),
+    Info = browser_info(_, _, _, _, Browser, _, _),
+    !:User = !.User ^ browser := Browser,
     query_user(UserQuestion, Response, !User, !IO).
 
 handle_command(trust_predicate, UserQuestion, trust_predicate(Question),
@@ -770,73 +833,6 @@
 
 %-----------------------------------------------------------------------------%
 
-:- type user_command
-    --->    yes
-            % The node is correct.
-
-    ;       no
-            % The node is erroneous.
-
-    ;       inadmissible
-            % The node is inadmissible.
-
-    ;       skip
-            % The user has no answer.
-
-    ;       browse_arg(maybe(int))
-            % Browse the nth argument before answering.  Or browse
-            % the whole predicate/function if the maybe is no.
-
-    ;       browse_xml_arg(maybe(int))
-            % Browse the argument using an XML browser.
-
-    ;       browse_io(int)
-            % Browse the nth IO action before answering.
-
-    ;       print_arg(int, int)
-            % Print the nth to the mth arguments before answering.
-
-    ;       print_io(int, int)
-            % Print the nth to the mth IO actions before answering.
-
-    ;       pd
-            % Commence procedural debugging from this point.
-
-    ;       set(maybe_option_table(setting_option), setting)
-            % Set a browser option.
-
-    ;       trust_predicate
-            % Trust the predicate being asked about.
-
-    ;       trust_module
-            % Trust the module being asked about.
-
-    ;       info
-            % Print some information about the current question.
-
-    ;       undo
-            % Undo the user's last answer.
-
-    ;       ask
-            % The user wants the current question re-asked.
-
-    ;       change_search(user_search_mode)
-            % Change the current search strategy.
-
-    ;       quit
-            % Abort this diagnosis session.
-
-    ;       help(maybe(string))
-            % Request help before answering.  If the maybe argument
-            % is no then a general help message is displayed,
-            % otherwise help on the given command is displayed.
-
-    ;       empty_command
-            % User just pressed return.
-
-    ;       illegal_command.
-            % None of the above.
-
 :- pred user_confirm_bug_help(user_state::in, io::di, io::uo) is det.
 
 user_confirm_bug_help(User, !IO) :-
@@ -909,7 +905,14 @@
 cmd_handler("browse",       browse_arg_cmd).
 cmd_handler("p",        print_arg_cmd).
 cmd_handler("print",        print_arg_cmd).
-cmd_handler("set",      set_arg_cmd).
+cmd_handler("format",   format_arg_cmd).
+cmd_handler("depth",    format_param_arg_cmd("depth")).
+cmd_handler("size",     format_param_arg_cmd("size")).
+cmd_handler("width",    format_param_arg_cmd("width")).
+cmd_handler("lines",    format_param_arg_cmd("lines")).
+cmd_handler("num_io_actions",  num_io_actions_cmd).
+% cmd_handler("xml_browser_cmd", set_xml_browser_cmd_cmd).
+% cmd_handler("xml_tmp_filename", set_xml_tmp_filename_cmd).
 cmd_handler("t",        trust_arg_cmd).
 cmd_handler("trust",        trust_arg_cmd).
 cmd_handler("mode",     search_mode_cmd).
@@ -946,13 +949,36 @@
 print_arg_cmd(["io", Arg]) = print_io(From, To) :-
     string_to_range(Arg, From, To).
 
-:- pred string_to_range(string::in, int::out, int::out) is semidet.
+:- func format_arg_cmd(list(string)::in) = (user_command::out) is semidet.
+
+format_arg_cmd(ArgWords) = param_command(format(MaybeOptionTable, Setting)) :-
+    ArgWords \= [],
+    parse.parse(["format" | ArgWords],
+        param_command(format(MaybeOptionTable, Setting))).
 
-:- func set_arg_cmd(list(string)::in) = (user_command::out) is semidet.
+:- func format_param_arg_cmd(string::in, list(string)::in)
+    = (user_command::out) is semidet.
 
-set_arg_cmd(ArgWords) = set(MaybeOptionTable, Setting) :-
+format_param_arg_cmd(Cmd, ArgWords)
+        = param_command(format_param(MaybeOptionTable, Setting)) :-
     ArgWords \= [],
-    parse.parse(["set" | ArgWords], set(MaybeOptionTable, Setting)).
+    parse.parse([Cmd | ArgWords],
+        param_command(format_param(MaybeOptionTable, Setting))).
+
+:- func num_io_actions_cmd(list(string)::in) = (user_command::out) is semidet.
+
+num_io_actions_cmd([Arg]) = param_command(num_io_actions(N)) :-
+    string.to_int(Arg, N).
+
+% :- func set_xml_browser_cmd_cmd(list(string)::in) = (user_command::out)
+%     is semidet.
+%
+% set_xml_browser_cmd_cmd([Arg]) = param_command(xml_browser_cmd(Arg)).
+%
+% :- func set_xml_tmp_filename_cmd(list(string)::in) = (user_command::out)
+%     is semidet.
+%
+% set_xml_tmp_filename_cmd([Arg]) = param_command(xml_tmp_filename(Arg)).
 
 :- func trust_arg_cmd(list(string)::in) = (user_command::out) is semidet.
 
@@ -980,6 +1006,8 @@
 
 help_cmd([]) = help(no).
 help_cmd([Cmd]) = help(yes(Cmd)).
+
+:- pred string_to_range(string::in, int::out, int::out) is semidet.
 
 string_to_range(Arg, From, To) :-
     ( string.to_int(Arg, Num) ->
Index: browser/listing.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/browser/listing.m,v
retrieving revision 1.4
diff -u -b -r1.4 listing.m
--- browser/listing.m	31 Mar 2006 05:12:10 -0000	1.4
+++ browser/listing.m	1 Apr 2006 06:59:40 -0000
@@ -89,6 +89,7 @@
 :- import_module int.
 :- import_module map.
 :- import_module maybe.
+:- import_module type_desc.
 
 %-----------------------------------------------------------------------------%
 
@@ -112,6 +113,12 @@
     "ML_LISTING_pop_list_path").
 :- pragma export(list_file(in, in, in, in, in, in, in, di, uo),
     "ML_LISTING_list_file").
+
+:- pred listing_type(type_desc::out) is det.
+:- pragma export(listing_type(out), "ML_LISTING_listing_type").
+
+listing_type(type_of(Path)) :-
+    clear_list_path(Path @ [], _).
 
 %-----------------------------------------------------------------------------%
 
Index: browser/parse.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/browser/parse.m,v
retrieving revision 1.28
diff -u -b -r1.28 parse.m
--- browser/parse.m	29 Mar 2006 08:06:32 -0000	1.28
+++ browser/parse.m	2 Apr 2006 17:21:38 -0000
@@ -35,7 +35,13 @@
 %       "p" [formatoptions] [path]  // short for print
 %       "display"
 %       "write"
-%       "set" [[setoptions] varvalue]
+%       "format" [formatcmdoptions] fmt
+%       "depth" [formatparamcmdoptions] value
+%       "size" [formatparamcmdoptions] value
+%       "width" [formatparamcmdoptions] value
+%       "lines" [formatparamcmdoptions] value
+%       "num_io_actions" int
+%       "params"
 %       "track" [--accurate] [path]
 %       "t" [--accurate] [path]
 %       "mark" [--accurate] [path]
@@ -57,11 +63,23 @@
 %       --verbose
 %       --pretty
 %
-%   setoptions:
+%   formatcmdoptions:
 %       /* empty */
-%       setoption setoptions
+%       formatcmdoption formatcmdoptions
 %
-%   setoption:
+%   formatcmdoption:
+%       -P
+%       -B
+%       -A
+%       --print
+%       --browse
+%       --print-all
+%
+%   formatparamcmdoptions:
+%       /* empty */
+%       formatparamcmdoption formatparamcmdoptions
+%
+%   formatparamcmdoption:
 %       -P
 %       -B
 %       -A
@@ -77,18 +95,6 @@
 %       --verbose
 %       --pretty
 %
-%   varvalue:
-%       "depth" num
-%       "size" num
-%       "clipx" num
-%       "clipy" num
-%       "format" fmt
-%       "num_io_actions" num
-%
-%   numlist:
-%       num
-%       num numlist
-%
 %   fmt:
 %       "flat"
 %       "raw_pretty"
@@ -129,14 +135,19 @@
     ;       mode_query
     ;       pwd
     ;       help
-    ;       set(maybe_option_table(setting_option), setting)
-    ;       set
+    ;       param_command(param_cmd)
     ;       quit
     ;       display
     ;       write
     ;       empty
     ;       unknown.
 
+:- type format_param_cmd
+    --->    param_depth
+    ;       param_size
+    ;       param_width
+    ;       param_lines.
+
 :- type path
     --->    root_rel(list(dir))
     ;       dot_rel(list(dir)).
@@ -148,13 +159,13 @@
     ;       pretty.
 
 :- type setting_option
-    --->    print
-    ;       browse
-    ;       print_all
-    ;       flat
-    ;       raw_pretty
-    ;       verbose
-    ;       pretty.
+    --->    set_print
+    ;       set_browse
+    ;       set_print_all
+    ;       set_flat
+    ;       set_raw_pretty
+    ;       set_verbose
+    ;       set_pretty.
 
     % If the term browser is called from the external debugger, the term
     % browser commands are send through the socket via terms of type
@@ -178,10 +189,13 @@
 
 :- import_module mdb.util.
 
+:- import_module assoc_list.
 :- import_module bool.
 :- import_module char.
 :- import_module int.
 :- import_module list.
+:- import_module map.
+:- import_module pair.
 
 :- type token
     --->    (.)
@@ -442,23 +456,63 @@
             Command = mode_query(Path)
         )
     ;
-        CmdToken = name("set")
+        CmdToken = name("format")
+    ->
+        (
+            ArgTokens = [],
+            Command = param_command(print_params)
+        ;
+            ArgTokens = [_ | _],
+            MaybeArgWords = yes(ArgWords),
+            OptionOps = option_ops_multi(short_format_cmd_option,
+                long_format_cmd_option, format_cmd_option_defaults),
+            getopt.process_options(OptionOps, ArgWords,
+                RemainingWords, MaybeOptionTable),
+            lexer_words(RemainingWords, RemainingTokens),
+            parse_format(RemainingTokens, Setting),
+            Command = param_command(format(MaybeOptionTable, Setting))
+        )
+    ;
+        (
+            CmdToken = name("depth"),
+            ParamCmd = param_depth
+        ;
+            CmdToken = name("size"),
+            ParamCmd = param_size
+        ;
+            CmdToken = name("width"),
+            ParamCmd = param_width
+        ;
+            CmdToken = name("lines"),
+            ParamCmd = param_lines
+        )
     ->
         (
             ArgTokens = [],
-            Command = set
+            Command = param_command(print_params)
         ;
             ArgTokens = [_ | _],
             MaybeArgWords = yes(ArgWords),
-            OptionOps = option_ops_multi(short_setting_option,
-                long_setting_option, setting_option_defaults),
+            OptionOps = option_ops_multi(short_format_param_cmd_option,
+                long_format_param_cmd_option,
+                format_param_cmd_option_defaults),
             getopt.process_options(OptionOps, ArgWords,
                 RemainingWords, MaybeOptionTable),
             lexer_words(RemainingWords, RemainingTokens),
-            parse_setting(RemainingTokens, Setting),
-            Command = set(MaybeOptionTable, Setting)
+            RemainingTokens = [num(N)],
+            param_cmd_to_setting(ParamCmd, N, Setting),
+            Command = param_command(format_param(MaybeOptionTable, Setting))
         )
     ;
+        CmdToken = name("params")
+    ->
+        Command = param_command(print_params)
+    ;
+        CmdToken = name("num_io_actions")
+    ->
+        ArgTokens = [num(N)],
+        Command = param_command(num_io_actions(N))
+    ;
         CmdToken = name("quit")
     ->
         ArgTokens = [],
@@ -509,15 +563,22 @@
         CmdToken = (<)
     ->
         ArgTokens = [num(Depth)],
-        % compute the default MaybeOptionTable
-        OptionOps = option_ops_multi(short_setting_option,
-            long_setting_option, setting_option_defaults),
+        OptionOps = option_ops_multi(short_format_param_cmd_option,
+            long_format_param_cmd_option, format_param_cmd_option_defaults),
         getopt.process_options(OptionOps, [], _, MaybeOptionTable),
-        Command = set(MaybeOptionTable, depth(Depth))
+        Command = param_command(format_param(MaybeOptionTable, depth(Depth)))
     ;
         fail
     ).
 
+:- pred param_cmd_to_setting(format_param_cmd::in, int::in, setting::out)
+    is det.
+
+param_cmd_to_setting(param_depth, N, depth(N)).
+param_cmd_to_setting(param_size,  N, size(N)).
+param_cmd_to_setting(param_width, N, width(N)).
+param_cmd_to_setting(param_lines, N, lines(N)).
+
 :- pred parse_path(list(token)::in, path::out) is semidet.
 
     % SICStus is forgiving in the syntax of paths, hence so are we.
@@ -558,9 +619,24 @@
         parse_dirs(Tokens, Dirs)
     ).
 
-:- pred parse_setting(list(token)::in, setting::out) is semidet.
+:- pred parse_format(list(token)::in, setting::out) is semidet.
 
-parse_setting([Token | Tokens], Setting) :-
+parse_format([Fmt], Setting) :-
+    ( Fmt = name("flat") ->
+        Setting = format(flat)
+    ; Fmt = name("raw_pretty") ->
+        Setting = format(raw_pretty)
+    ; Fmt = name("verbose") ->
+        Setting = format(verbose)
+    ; Fmt = name("pretty") ->
+        Setting = format(pretty)
+    ;
+        fail
+    ).
+
+:- pred parse_format_param(list(token)::in, setting::out) is semidet.
+
+parse_format_param([Token | Tokens], Setting) :-
     ( Token = name("depth") ->
         Tokens = [num(Depth)],
         Setting = depth(Depth)
@@ -573,21 +649,6 @@
     ; Token = name("lines") ->
         Tokens = [num(Y)],
         Setting = lines(Y)
-    ; Token = name("num_io_actions") ->
-        Tokens = [num(Y)],
-        Setting = num_io_actions(Y)
-    ; Token = name("format") ->
-        Tokens = [Fmt],
-        ( Fmt = name("flat") ->
-            Setting = format(flat)
-        ; Fmt = name("raw_pretty") ->
-            Setting = format(raw_pretty)
-        ; Fmt = name("verbose") ->
-            Setting = format(verbose)
-        ;
-            Fmt = name("pretty"),
-            Setting = format(pretty)
-        )
     ;
         fail
     ).
@@ -617,36 +678,63 @@
 
 %---------------------------------------------------------------------------%
 
-:- pred short_setting_option(char::in, setting_option::out) is semidet.
+:- pred short_format_cmd_option(char::in, setting_option::out) is semidet.
+
+short_format_cmd_option('P', set_print).
+short_format_cmd_option('B', set_browse).
+short_format_cmd_option('A', set_print_all).
 
-short_setting_option('P', print).
-short_setting_option('B', browse).
-short_setting_option('A', print_all).
-short_setting_option('f', flat).
-short_setting_option('r', raw_pretty).
-short_setting_option('v', verbose).
-short_setting_option('p', pretty).
-
-:- pred long_setting_option(string::in, setting_option::out) is semidet.
-
-long_setting_option("print", print).
-long_setting_option("browse", browse).
-long_setting_option("print-all", print_all).
-long_setting_option("flat", flat).
-long_setting_option("raw-pretty", raw_pretty).
-long_setting_option("verbose", verbose).
-long_setting_option("pretty", pretty).
+:- pred long_format_cmd_option(string::in, setting_option::out) is semidet.
 
-:- pred setting_option_defaults(setting_option::out, option_data::out)
+long_format_cmd_option("print", set_print).
+long_format_cmd_option("browse", set_browse).
+long_format_cmd_option("print-all", set_print_all).
+
+:- pred format_cmd_option_defaults(setting_option::out, option_data::out)
     is multi.
 
-setting_option_defaults(print,      bool(no)).
-setting_option_defaults(browse,     bool(no)).
-setting_option_defaults(print_all,  bool(no)).
-setting_option_defaults(flat,       bool(no)).
-setting_option_defaults(raw_pretty, bool(no)).
-setting_option_defaults(verbose,    bool(no)).
-setting_option_defaults(pretty,     bool(no)).
+format_cmd_option_defaults(set_print,      bool(no)).
+format_cmd_option_defaults(set_browse,     bool(no)).
+format_cmd_option_defaults(set_print_all,  bool(no)).
+format_cmd_option_defaults(set_flat,       bool(no)).
+format_cmd_option_defaults(set_raw_pretty, bool(no)).
+format_cmd_option_defaults(set_verbose,    bool(no)).
+format_cmd_option_defaults(set_pretty,     bool(no)).
+
+%---------------------------------------------------------------------------%
+
+:- pred short_format_param_cmd_option(char::in, setting_option::out)
+    is semidet.
+
+short_format_param_cmd_option('P', set_print).
+short_format_param_cmd_option('B', set_browse).
+short_format_param_cmd_option('A', set_print_all).
+short_format_param_cmd_option('f', set_flat).
+short_format_param_cmd_option('r', set_raw_pretty).
+short_format_param_cmd_option('v', set_verbose).
+short_format_param_cmd_option('p', set_pretty).
+
+:- pred long_format_param_cmd_option(string::in, setting_option::out)
+    is semidet.
+
+long_format_param_cmd_option("print", set_print).
+long_format_param_cmd_option("browse", set_browse).
+long_format_param_cmd_option("print-all", set_print_all).
+long_format_param_cmd_option("flat", set_flat).
+long_format_param_cmd_option("raw-pretty", set_raw_pretty).
+long_format_param_cmd_option("verbose", set_verbose).
+long_format_param_cmd_option("pretty", set_pretty).
+
+:- pred format_param_cmd_option_defaults(setting_option::out,
+    option_data::out) is multi.
+
+format_param_cmd_option_defaults(set_print,      bool(no)).
+format_param_cmd_option_defaults(set_browse,     bool(no)).
+format_param_cmd_option_defaults(set_print_all,  bool(no)).
+format_param_cmd_option_defaults(set_flat,       bool(no)).
+format_param_cmd_option_defaults(set_raw_pretty, bool(no)).
+format_param_cmd_option_defaults(set_verbose,    bool(no)).
+format_param_cmd_option_defaults(set_pretty,     bool(no)).
 
 %---------------------------------------------------------------------------%
 
@@ -676,12 +764,6 @@
 %   io.write_string("pwd\n").
 % show_command(help) -->
 %   io.write_string("help\n").
-% show_command(set(Setting)) -->
-%   io.write_string("set "),
-%   show_setting(Setting),
-%   io.nl.
-% show_command(set) -->
-%   io.write_string("set\n").
 % show_command(quit) -->
 %   io.write_string("quit\n").
 % show_command(print) -->
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing debian/patches
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
Index: doc/mdb_categories
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/mdb_categories,v
retrieving revision 1.31
diff -u -b -r1.31 mdb_categories
--- doc/mdb_categories	31 Mar 2006 05:12:12 -0000	1.31
+++ doc/mdb_categories	1 Apr 2006 08:33:47 -0000
@@ -27,7 +27,7 @@
 browsing   - Commands that let users explore the state of the computation.
              The browsing commands are `vars', `held_vars', `print', `browse',
              `stack', `up', `down', `level', `current', `view', `hold',
-             `diff', `dump', `list', `push_list_dir' and `pop_list_dir'.
+             `diff', `dump', and `list'.
 
 end
 document_category 500 breakpoint
@@ -43,9 +43,12 @@
 end
 document_category 700 parameter
 parameter  - Commands that let users access debugger parameters.
-             The parameter commands are `set', `printlevel', `echo', `context',
-             `goal_paths' `scroll', `mmc_options', `scope', `alias',
-             `unalias', and `stack_default_limit'.
+             The parameter commands are `mmc_options', `printlevel', `scroll',
+             `stack_default_limit', `goal_paths' `scope', `echo', 
+             `context', `list_context_lines', `list_path', `push_list_dir',
+             `pop_list_dir', `fail_trace_counts', `pass_trace_counts',
+	     `max_io_actions', `xml_browser_cmd', `xml_tmp_filename',
+	     `format', `format_param', `alias' and `unalias'.
 
 end
 document_category 800 help
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.472
diff -u -b -r1.472 user_guide.texi
--- doc/user_guide.texi	31 Mar 2006 05:12:12 -0000	1.472
+++ doc/user_guide.texi	2 Apr 2006 06:46:38 -0000
@@ -1571,8 +1571,12 @@
 The else part of an if-then-else.
 @item ~
 The goal inside a negation.
+ at item q!
+The goal inside an existential quantification or other scope
+that changes the determinism of the goal.
 @item q
-The goal inside an existential quantification.
+The goal inside an existential quantification or other scope
+that doesn't change the determinism of the goal.
 @end table
 
 A path describes the position of a goal
@@ -2073,9 +2077,9 @@
 that specifies whether the procedure belongs
 to a unify, compare, index or init predicate.
 @item
-An optional prefix of the form @samp{@var{module}:}, @samp{@var{module}.}
-or @samp{@var{module}__} that specifies the name of the module that defines
-the predicate or function to which the procedure belongs.
+An optional prefix of the form @samp{@var{module}.} or @samp{@var{module}__}
+that specifies the name of the module that defines the predicate or function
+to which the procedure belongs.
 @item
 The name of the type constructor.
 @item
@@ -2878,16 +2882,6 @@
 Lists the source code text for the current environment, including
 @var{num} preceding and following lines.  If @var{num} is not provided then
 the default of two is used.
- at sp 1
- at item push_list_dir @var{dir1} @var{dir2} ...
- at kindex push_list_dir (mdb command)
-The @samp{list} command searches a list of directories when looking for a
-source code file.  The @samp{push_list_dir} pushes one or more such
-directories on to this list.
- at sp 1
- at item pop_list_dir
- at kindex pop_list_dir (mdb command)
-Pops the most recent @samp{push_list_dir}' directory from the search list.
 @end table
 
 @sp 1
@@ -3158,12 +3152,14 @@
 @kindex procedures (mdb command)
 Lists all the procedures in the debuggable module @var{module}.
 @sp 1
- at item register
+ at item register [-q]
 @kindex register (mdb command)
 Registers all debuggable modules with the debugger.
 Has no effect if this registration has already been done.
 The debugger will perform this registration when creating breakpoints
 and when listing debuggable modules and/or procedures.
+The command will print a message to this effect
+unless the @samp{-q} or @samp{--quiet} option is given.
 @end table
 
 @sp 1
@@ -3219,16 +3215,6 @@
 @item printlevel
 Reports the current default print level.
 @sp 1
- at item echo on
- at kindex echo (mdb command)
-Turns on the echoing of commands.
- at sp 1
- at item echo off
-Turns off the echoing of commands.
- at sp 1
- at item echo
-Reports whether commands are being echoed or not.
- at sp 1
 @item scroll on
 @kindex scroll (mdb command)
 Turns on user control over the scrolling of sequences of event reports.
@@ -3263,6 +3249,45 @@
 the @samp{stack} and @samp{nondet_stack} commands to @var{size}.
 If @var{size} is zero, the limit is disabled.
 @sp 1
+ at item goal_paths on
+ at kindex goal_path (mdb command)
+Turns on printing of goal paths at events.
+ at sp 1
+ at item goal_paths off
+Turns off printing of goal paths at events.
+ at sp 1
+ at item goal_paths
+Reports whether goal paths are printed at events.
+ at sp 1
+ at item scope all
+ at kindex scope (mdb command)
+Sets the default scope of new breakpoints to ``all'',
+i.e.@: by default, new breakpoints on procedures
+will stop at all events in the procedure.
+ at sp 1
+ at item scope interface
+Sets the default scope of new breakpoints to ``interface'',
+i.e.@: by default, new breakpoints on procedures
+will stop at all interface events in the procedure.
+ at sp 1
+ at item scope entry
+Sets the default scope of new breakpoints to ``entry'',
+i.e.@: by default, new breakpoints on procedures
+will stop only at events representing calls to the procedure.
+ at sp 1
+ at item scope
+Reports the current default scope of new breakpoints.
+ at sp 1
+ at item echo on
+ at kindex echo (mdb command)
+Turns on the echoing of commands.
+ at sp 1
+ at item echo off
+Turns off the echoing of commands.
+ at sp 1
+ at item echo
+Reports whether commands are being echoed or not.
+ at sp 1
 @item context none
 @kindex context (mdb command)
 @cindex line numbers
@@ -3299,33 +3324,175 @@
 @item context
 Reports where contexts are being printed.
 @sp 1
- at item goal_paths on
- at kindex goal_path (mdb command)
-Turns on printing of goal paths at events.
+ at item list_context_lines @var{num}
+ at kindex list_context_lines (mdb command)
+Sets the number of lines to be printed by the @samp{list} command
+printed before and after the target context.
 @sp 1
- at item goal_paths off
-Turns off printing of goal paths at events.
+ at item list_context_lines
+Prints the number of lines to be printed by the @samp{list} command
+printed before and after the target context.
 @sp 1
- at item goal_paths
-Reports whether goal paths are printed at events.
+ at item list_path @var{dir1} @var{dir2} ...
+ at kindex list_path (mdb command)
+The @samp{list} command searches a list of directories
+when looking for a source code file.
+The @samp{list_path} command sets the search path
+to the given list of directories.
+ at sp 1
+ at item list_path
+When invoked without arguments, the @samp{list_path} command
+prints the search path consulted by the @samp{list} command.
 @sp 1
- at item scope all
-Sets the default scope of new breakpoints to ``all'',
-i.e.@: by default, new breakpoints on procedures
-will stop at all events in the procedure.
+ at item push_list_dir @var{dir1} @var{dir2} ...
+ at kindex push_list_dir (mdb command)
+Pushes the given directories
+on to the search path consulted by the @samp{list} command.
 @sp 1
- at item scope interface
-Sets the default scope of new breakpoints to ``interface'',
-i.e.@: by default, new breakpoints on procedures
-will stop at all interface events in the procedure.
+ at item pop_list_dir
+ at kindex pop_list_dir (mdb command)
+Pops the leftmost (most recently pushed) directory
+from the search path consulted by the @samp{list} command.
 @sp 1
- at item scope entry
-Sets the default scope of new breakpoints to ``entry'',
-i.e.@: by default, new breakpoints on procedures
-will stop only at events representing calls to the procedure.
+ at item fail_trace_counts @var{filename}
+ at kindex fail_trace_counts (mdb command)
+The declarative debugger can exploit information
+about the failing and passing test cases to ask better questions.
+This command tells the @samp{dice} command
+that @var{filename} contains execution trace counts from failing test cases.
+The @samp{dice} command will use this file
+unless this is overridden with its @samp{--fail-trace-counts} option.
+ at sp 1
+ at item fail_trace_counts
+Prints the name of the file containing
+execution trace counts from failing test cases,
+if this has already been set.
 @sp 1
- at item scope
-Reports the current default scope of new breakpoints.
+ at item pass_trace_counts @var{filename}
+ at kindex pass_trace_counts (mdb command)
+The declarative debugger can exploit information
+about the failing and passing test cases to ask better questions.
+This command tells the @samp{dice} command
+that @var{filename} contains execution trace counts from passing test cases.
+The @samp{dice} command will use this file
+unless this is overridden with its @samp{--pass-trace-counts} option.
+ at sp 1
+ at item pass_trace_counts
+Prints the name of the file containing
+execution trace counts from passing test cases,
+if this has already been set.
+ at sp 1
+ at item max_io_actions @var{num}
+ at kindex max_io_actions (mdb command)
+Set the maximum number of I/O actions to print
+in questions from the declarative debugger to @var{num}.
+ at sp 1
+ at item max_io_actions
+Prints the maximum number of I/O actions to print
+in questions from the declarative debugger.
+ at sp 1
+ at item xml_browser_cmd @var{command}
+ at kindex xml_browser_cmd (mdb command)
+Set the shell command used to launch an XML browser to @var{command}.
+If you want a stylesheet to be applied to the XML
+before the browser is invoked,
+then you should do that in this command using the appropriate program 
+(such as xsltproc, which comes with libxslt
+and is available from http://xmlsoft.org/XSLT/).  
+By default if xsltproc and mozilla (or firefox) are available,
+xsltproc is invoked to apply the xul_tree.xsl stylesheet in
+extras/xml_stylesheets, then mozilla is invoked on the resulting XUL file.  
+ at sp 1
+You can use the apostrophe character (') to quote the command string,
+for example "xml_browser_cmd 'firefox file:///tmp/mdbtmp.xml'".
+ at sp 1
+ at item xml_browser_cmd
+Prints the shell command used to launch an XML browser,
+if this has been set.
+ at sp 1
+ at item xml_tmp_filename @var{filename}
+ at kindex xml_tmp_filename (mdb command)
+Tells the debugger to dump XML into the named file
+before invoking the XML browser.
+The command named as the argument of @samp{xml_browser_cmd}
+will usually refer to this file.
+ at sp 1
+ at item xml_tmp_filename
+Prints the temporary filename used for XML browsing,
+if this has been set.
+ at sp 1
+ at item format [-APB] @var{format}
+ at kindex format (mdb command)
+Sets the default format of the browser to @var{format},
+which should be one of @samp{flat}, @samp{pretty} and @samp{verbose}.
+ at sp 1
+The browser maintains separate configuration parameters
+for the three commands @samp{print *}, @samp{print @var{var}},
+and @samp{browse @var{var}}.
+A @samp{format} command applies to all three,
+unless it specifies one or more of the options
+ at samp{-A} or @samp{--print-all},
+ at samp{-P} or @samp{--print},
+and @samp{-B} or @samp{--browse},
+in which case it will set only the selected command's default format.
+ at sp 1
+ at item format_param [-APBfpv] @var{param} @var{value}
+ at kindex format_param (mdb command)
+ at kindex depth (mdb command)
+ at kindex size (mdb command)
+ at kindex width (mdb command)
+ at kindex lines (mdb command)
+Sets one of the parameters of the browser to the given value.
+The parameter @var{param} must be one of
+ at samp{depth}, @samp{size}, @samp{width} and @samp{lines}.
+ at sp 1
+ at itemize @bullet
+ at item
+ at samp{depth} is the maximum depth to which subterms will be displayed.
+Subterms at the depth limit may be abbreviated as functor/arity,
+or (in lists) may be replaced by an ellipsis (@samp{...}).
+The principal functor of any term has depth zero.
+For subterms which are not lists,
+the depth of any argument of the functor is one greater than the
+depth of the functor.
+For subterms which are lists,
+the depth of each element of the list
+is one greater than the depth of the list.
+ at sp 1
+ at item
+ at samp{size} is the suggested maximum number of functors to display.
+Beyond this limit, subterms may be abbreviated as functor/arity,
+or (in lists) may be replaced by an ellipsis (@samp{...}).
+For the purposes of this parameter,
+the size of a list is one greater than
+the sum of the sizes of the elements in the list.
+ at sp 1
+ at item
+ at samp{width} is the width of the screen in characters.
+ at sp 1
+ at item
+ at samp{lines} is the preferred maximum number of lines of one term to display.
+ at sp 1
+ at end itemize
+ at sp 1
+The browser maintains separate configuration parameters
+for the three commands @samp{print *}, @samp{print @var{var}},
+and @samp{browse @var{var}}.
+A @samp{format_param} command applies to all three,
+unless it specifies one or more of the options
+ at samp{-A} or @samp{--print-all},
+ at samp{-P} or @samp{--print},
+and @samp{-B} or @samp{--browse},
+in which case it will set only the selected command's parameters.
+ at sp 1
+The browser also maintains separate configuration parameters
+for the different output formats: flat, pretty and verbose.
+A @samp{format_param} command applies to all of these,
+unless it specifies one or more of the options
+ at samp{-f} or @samp{--flat},
+ at samp{-p} or @samp{--pretty},
+and @samp{-v} or @samp{--verbose},
+in which case it will set only the selected format's parameter.
 @sp 1
 @item alias @var{name} @var{command} [@var{command-parameter} ...]
 @kindex alias (mdb command)
@@ -3339,7 +3506,6 @@
 the debugger will substitute the given command and parameters
 whenever the user types in an empty command line.
 @sp 1
- at sp 1
 If @var{name} is the upper-case word @samp{NUMBER},
 the debugger will insert the given command and parameters
 before the command line
@@ -3586,7 +3752,7 @@
 @end itemize
 @sp 1
 The name of the file containing the failing slice can be specified with the 
- at samp{-f} or @samp{--fail-trace-count} option or with a separate 
+ at samp{-f} or @samp{--fail-trace-counts} option or with a separate 
 @samp{set fail_trace_count @var{filename}} command.
 @sp 1
 The name of a file containing a list of the files containing the passing
@@ -3633,110 +3799,6 @@
 
 @sp 1
 @table @code
- at item set [-APBfpv] @var{param} @var{value}
- at kindex set (mdb command)
- at kindex format (mdb command)
- at kindex depth (mdb command)
- at kindex size (mdb command)
- at kindex width (mdb command)
- at kindex lines (mdb command)
- at kindex xml_browser_cmd (mdb command)
- at kindex xml_tmp_filename (mdb command)
- at kindex fail_trace_counts (mdb command)
- at kindex pass_trace_counts (mdb command)
- at kindex list_path (mdb command)
- at kindex list_context_lines (mdb command)
-Updates the given configuration parameter.
-The parameters that can be configured are
- at samp{format}, @samp{depth}, @samp{size}, @samp{width}, @samp{lines}, 
- at samp{xml_browser_cmd}, @samp{xml_tmp_filename}, @samp{fail_trace_counts},
- at samp{pass_trace_counts}.
- at sp 1
- at itemize @bullet
- at item
- at samp{format} can be set to @samp{flat}, @samp{pretty} or @samp{verbose}
-to change the output style of the browser.
- at sp 1
- at item
- at samp{depth} is the maximum depth to which subterms will be displayed.
-Subterms at the depth limit may be abbreviated as functor/arity,
-or (in lists) may be replaced by an ellipsis (@samp{...}).
-The principal functor of any term has depth zero.
-For subterms which are not lists,
-the depth of any argument of the functor is one greater than the
-depth of the functor.
-For subterms which are lists,
-the depth of each element of the list
-is one greater than the depth of the list.
- at sp 1
- at item
- at samp{size} is the suggested maximum number of functors to display.
-Beyond this limit, subterms may be abbreviated as functor/arity,
-or (in lists) may be replaced by an ellipsis (@samp{...}).
-For the purposes of this parameter,
-the size of a list is one greater than
-the sum of the sizes of the elements in the list.
- at sp 1
- at item
- at samp{width} is the width of the screen in characters.
- at sp 1
- at item
- at samp{lines} is the maximum number of lines of one term to display.
- at sp 1
- at item
- at samp{xml_tmp_filename} is the name of the file to dump XML to before
-invoking your XML browser.
- at sp 1
- at item
- at samp{xml_browser_cmd} is the shell command(s) used to invoke your XML browser.
-If you want a stylesheet to be applied to the XML before the browser is invoked
-then you should do that in this command using the appropriate program 
-(such as xsltproc, which comes with libxslt and is available from
-http://xmlsoft.org/XSLT/).  
-By default if xsltproc and mozilla (or firefox) are available,
-xsltproc is invoked to apply the xul_tree.xsl stylesheet in
-extras/xml_stylesheets, then mozilla is invoked on the resulting XUL file.  
- at sp 1
-You can use the apostrophe character (') to quote the command string when using
-the @samp{set} command, for example "set xml_browser_cmd 'firefox
-file:///tmp/mdbtmp.xml'".
- at item
- at samp{fail_trace_count} is the name of a file that contains the slice of a
-failing test case run.  This configuration parameter is used by the 
- at samp{dice} command if no @samp{--fail-trace-count} option is given for that
-command.  See @ref{Experimental commands} for more information on the 
- at samp{dice} command.
- at sp 1
- at item
- at samp{pass_trace_counts} is the name of a file that contains a list of file
-names which contain the slices of passing test case runs.  This configuration
-parameter is used by the @samp{dice} command if no @samp{--pass-trace-counts}
-option is given for that command.  See @ref{Experimental commands} for more
-information on the @samp{dice} command.
- at end itemize
- at sp 1
-The browser maintains separate configuration parameters
-for the three commands @samp{print *}, @samp{print @var{var}},
-and @samp{browse @var{var}}.
-A single @samp{set} command can modify the parameters
-for more than one of these;
-the options @samp{-A} or @samp{--print-all}, @samp{-P} or @samp{--print},
-and @samp{-B} or @samp{--browse}
-select which commands will be affected by the change.
-If none of these options is given,
-the default is to affect all commands.
- at sp 1
-The browser also maintains separate configuration parameters
-for the three different output formats.
-This applies to all parameters except for the format itself.
-The options @samp{-f} or @samp{--flat}, @samp{-p} or @samp{--pretty},
-and @samp{-v} or @samp{--verbose}
-select which formats will be affected by the change.
-If none of these options is given,
-the default is to affect all formats.
-In the case that the format itself is being set,
-these options are ignored.
- at sp 1
 @item source [-i] @var{filename}
 @kindex source (mdb command)
 Executes the commands in the file named @var{filename}.
@@ -4254,11 +4316,28 @@
 @item print io @var{n}- at var{m}
 Print the @var{n}th to @var{m}th IO actions (inclusive).
 @sp 1
- at item set @var{param} @var{value}
-Update the given configuration parameter.
-The parameters that can be configured are
- at samp{list_path}, @samp{list_context_lines}, @samp{format}, @samp{depth},
- at samp{size}, @samp{width} and @samp{lines}.
+ at item format @var{format}
+Set the default format to @var{format},
+which should be one of @samp{flat}, @samp{verbose} and @samp{pretty}.
+ at sp 1
+ at item depth @var{num}
+Set the maximum depth to which terms are printed to @var{num}.
+ at sp 1
+ at item size @var{num}
+Set the maximum number of function symbols
+to be printed in terms to @var{num}.
+ at sp 1
+ at item width @var{num}
+Set the number of columnds in which terms are to be printed to @var{num}.
+ at sp 1
+ at item lines @var{num}
+Set the maximum number of lines in terms to be printed to @var{num}.
+ at sp 1
+ at item actions @var{num}
+Set the maximum number of I/O actions to be printed in questions to @var{num}.
+ at sp 1
+ at item params
+Print the current values of browser parameters.
 @sp 1
 @item track [-a] [@var{term-path}]
 The @samp{track} command can only be given from within the interactive
cvs diff: Diffing extras
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/gator
cvs diff: Diffing extras/gator/generations
cvs diff: Diffing extras/gator/generations/1
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/solver_types
cvs diff: Diffing extras/solver_types/library
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/windows_installer_generator
cvs diff: Diffing extras/windows_installer_generator/sample
cvs diff: Diffing extras/windows_installer_generator/sample/images
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
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
Index: scripts/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/scripts/Mmakefile,v
retrieving revision 1.39
diff -u -b -r1.39 Mmakefile
--- scripts/Mmakefile	25 May 2005 05:19:50 -0000	1.39
+++ scripts/Mmakefile	3 Apr 2006 16:10:13 -0000
@@ -69,7 +69,7 @@
 		chmod a+x $* ; \
 		fi \
 	done
-	@for file in $(CONF_FILES) ; do \
+	@for file in $(CONF_FILES) $(CONF_DEBUG_SCRIPTS) ; do \
 		if test "$*" = "$$file" ; then \
 		$(MERCURY_DIR)/config.status --file=$* ; \
 		if grep -n '[^$$]@' $@; then false; else true; fi \
Index: scripts/mdbrc.in
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/scripts/mdbrc.in,v
retrieving revision 1.5
diff -u -b -r1.5 mdbrc.in
--- scripts/mdbrc.in	11 Dec 2004 01:59:51 -0000	1.5
+++ scripts/mdbrc.in	1 Apr 2006 11:20:31 -0000
@@ -15,5 +15,5 @@
 alias	e	exception
 alias	EMPTY	step
 alias	NUMBER	step
-set xml_browser_cmd '@DEFAULT_XML_BROWSER_CMD@'
-set xml_tmp_filename '@DEFAULT_XML_TMP_FILENAME@'
+xml_browser_cmd '@DEFAULT_XML_BROWSER_CMD@'
+xml_tmp_filename '@DEFAULT_XML_TMP_FILENAME@'
cvs diff: Diffing slice
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
Index: tests/debugger/breakpoints.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/breakpoints.exp,v
retrieving revision 1.14
diff -u -b -r1.14 breakpoints.exp
--- tests/debugger/breakpoints.exp	29 Mar 2006 00:57:42 -0000	1.14
+++ tests/debugger/breakpoints.exp	1 Apr 2006 13:43:25 -0000
@@ -106,8 +106,8 @@
 
 mdb> break_print 1 none
  1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
-mdb> set -p depth 10
-mdb> set -p size 20
+mdb> format_param -p depth 10
+mdb> format_param -p size 20
 mdb> break_print -p -n 1 HeadVar__1 HeadVar__2
  1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
             HeadVar__1 (pretty, nowarn), HeadVar__2 (pretty, nowarn)
Index: tests/debugger/breakpoints.exp2
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/breakpoints.exp2,v
retrieving revision 1.10
diff -u -b -r1.10 breakpoints.exp2
--- tests/debugger/breakpoints.exp2	30 Mar 2006 00:42:00 -0000	1.10
+++ tests/debugger/breakpoints.exp2	1 Apr 2006 13:43:29 -0000
@@ -114,8 +114,8 @@
 
 mdb> break_print 1 none
  1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
-mdb> set -p depth 10
-mdb> set -p size 20
+mdb> format_param -p depth 10
+mdb> format_param -p size 20
 mdb> break_print -p -n 1 HeadVar__1 HeadVar__2
  1: + stop  interface pred breakpoints.qperm/2-0 (nondet)
             HeadVar__1 (pretty, nowarn), HeadVar__2 (pretty, nowarn)
Index: tests/debugger/breakpoints.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/breakpoints.inp,v
retrieving revision 1.8
diff -u -b -r1.8 breakpoints.inp
--- tests/debugger/breakpoints.inp	27 Jan 2005 06:17:37 -0000	1.8
+++ tests/debugger/breakpoints.inp	1 Apr 2006 13:43:07 -0000
@@ -30,8 +30,8 @@
 break_print -v -n 1 HeadVar__1 HeadVar__2
 continue
 break_print 1 none
-set -p depth 10
-set -p size 20
+format_param -p depth 10
+format_param -p size 20
 break_print -p -n 1 HeadVar__1 HeadVar__2
 continue
 finish -N
Index: tests/debugger/browse_pretty.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/browse_pretty.exp,v
retrieving revision 1.13
diff -u -b -r1.13 browse_pretty.exp
--- tests/debugger/browse_pretty.exp	5 Nov 2004 06:30:20 -0000	1.13
+++ tests/debugger/browse_pretty.exp	2 Apr 2006 17:01:31 -0000
@@ -6,17 +6,17 @@
 mdb> print *
        Data (arg 1)           	big(big(big(small, [|]/2, small), [1, ...], small), [1, 2, 3], big(big/3, [|]/2, small))
 mdb> browse 1
-browser> set format pretty
-browser> set depth 10
+browser> format pretty
+browser> depth 10
 browser> ls
 big(big(big(small, [1], small), [1, 2], small), [1, 2, 3], 
   big(big(small, [1, 2, 3, 4], big(small, [1, 2, 3, 4, 5], small)), 
     [1, 2, 3, 4, 5, 6], small))
-browser> set width 131
+browser> width 131
 browser> ls
 big(big(big(small, [1], small), [1, 2], small), [1, 2, 3], 
   big(big(small, [1, 2, 3, 4], big(small, [1, 2, 3, 4, 5], small)), [1, 2, 3, 4, 5, 6], small))
-browser> set width 30
+browser> width 30
 browser> ls
 big(
   big(
@@ -29,7 +29,7 @@
         [1, 2, 3, 4, 5], 
         small)), 
     [1, 2, 3, 4, 5, 6], small))
-browser> set width 10
+browser> width 10
 browser> ls
 big(
   big(
@@ -64,26 +64,26 @@
      4, 
      5, 6], 
     small))
-browser> set width 79
-browser> set depth 3
+browser> width 79
+browser> depth 3
 browser> ls
 big(big(big(...), ...), [1, ...], ...)
-browser> set format raw_pretty
-browser> set lines 4
-browser> set width 40
+browser> format raw_pretty
+browser> lines 4
+browser> width 40
 browser> ls
 big(
   big(big/3, [|]/2, small), 
   [|](1, [|](2, [|](3, []))), 
   big(big/3, [|]/2, small))
-browser> set width 80
+browser> width 80
 browser> ls
 big(
   big(big(small, [|](1, []), small), [|](1, [|](2, [])), small), 
   [|](1, [|](2, [|](3, []))), 
   big(big(small, [|]/2, big/3), [|](1, [|](2, [|](3, [|]/2))), small))
-browser> set lines 12
-browser> set width 40
+browser> lines 12
+browser> width 40
 browser> ls
 big(
   big(
@@ -96,8 +96,8 @@
     [|](1, [|](2, [|](3, [|]/2))), 
     small))
 browser> cd 3
-browser> set lines 4
-browser> set width 30
+browser> lines 4
+browser> width 30
 browser> ls
 big(
   big(small, [|]/2, big/3), 
Index: tests/debugger/browse_pretty.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/browse_pretty.inp,v
retrieving revision 1.5
diff -u -b -r1.5 browse_pretty.inp
--- tests/debugger/browse_pretty.inp	5 Nov 2004 06:30:20 -0000	1.5
+++ tests/debugger/browse_pretty.inp	2 Apr 2006 17:01:55 -0000
@@ -2,30 +2,30 @@
 goto 3
 print *
 browse 1
-set format pretty
-set depth 10
+format pretty
+depth 10
 ls
-set width 131
+width 131
 ls
-set width 30
+width 30
 ls
-set width 10
+width 10
 ls
-set width 79
-set depth 3
+width 79
+depth 3
 ls
-set format raw_pretty
-set lines 4
-set width 40
+format raw_pretty
+lines 4
+width 40
 ls
-set width 80
+width 80
 ls
-set lines 12
-set width 40
+lines 12
+width 40
 ls
 cd 3
-set lines 4
-set width 30
+lines 4
+width 30
 ls
 quit
 print goal
Index: tests/debugger/browser_test.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/browser_test.exp,v
retrieving revision 1.25
diff -u -b -r1.25 browser_test.exp
--- tests/debugger/browser_test.exp	31 Mar 2006 05:12:15 -0000	1.25
+++ tests/debugger/browser_test.exp	1 Apr 2006 13:52:50 -0000
@@ -11,11 +11,11 @@
 mdb> delete *
  0: E stop  interface pred browser_test.big_data/1-0 (det)
 mdb> dump 1 browser_test.save.1
-mdb> set format raw_pretty
+mdb> format raw_pretty
 mdb> print *
        Data (arg 1)           	
 big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
-mdb> set -A format verbose
+mdb> format -A verbose
 mdb> print *
        Data (arg 1)           	
 big
@@ -29,7 +29,7 @@
   big(big(small, 1, small), 2, small), 
   3, 
   big(big(small, 4, big(small, 5, small)), 6, small))
-mdb> set -AP format flat
+mdb> format -AP flat
 mdb> print -f 1
        Data (arg 1)           	big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
 mdb> print -p 1
@@ -106,8 +106,8 @@
   3, 
   big(big(small, 4, big(small, 5, small)), 6, small))
 browser> quit
-mdb> set xml_tmp_filename './browser_test.xml.out'
-mdb> set xml_browser_cmd 'cat ./browser_test.xml.out'
+mdb> xml_tmp_filename './browser_test.xml.out'
+mdb> xml_browser_cmd 'cat ./browser_test.xml.out'
 mdb> browse --xml 1
 Saving term to XML file...
 Launching XML browser (this may take some time) ...
@@ -166,12 +166,12 @@
 		<small functor="small" type="browser_test.big" arity="0" />
 	</big>
 </big>
-mdb> set -A -f depth 1
+mdb> format_param -A -f depth 1
 mdb> print *
        Data (arg 1)           	big(big/3, 3, big/3)
 mdb> print Data/1
        Data (arg 1)           	big(big(small, 1, small), 2, small)
-mdb> set -f depth 3
+mdb> format_param -f depth 3
 mdb> print 1
        Data (arg 1)           	big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
 mdb> print Data/1/2
Index: tests/debugger/browser_test.exp2
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/browser_test.exp2,v
retrieving revision 1.16
diff -u -b -r1.16 browser_test.exp2
--- tests/debugger/browser_test.exp2	30 Jan 2003 05:59:26 -0000	1.16
+++ tests/debugger/browser_test.exp2	1 Apr 2006 13:53:14 -0000
@@ -3,11 +3,11 @@
 Command echo enabled.
 mdb> goto 3
       E2:     C2  2 EXIT pred browser_test.big_data/1-0 (det) browser_test.m:18 (browser_test.m:12)
-mdb> set format pretty
+mdb> format pretty
 mdb> print *
        Data (arg 1)           	
 big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
-mdb> set -A format verbose
+mdb> format -A verbose
 mdb> print *
        Data (arg 1)           	
 big
@@ -21,7 +21,7 @@
   big(big(small, 1, small), 2, small), 
   3, 
   big(big(small, 4, big(small, 5, small)), 6, small))
-mdb> set -AP format flat
+mdb> format -AP flat
 mdb> print -f 1
        Data (arg 1)           	big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
 mdb> print -r 1
@@ -84,12 +84,12 @@
   3, 
   big(big(small, 4, big(small, 5, small)), 6, small))
 browser> quit
-mdb> set -A -f depth 1
+mdb> format_param -A -f depth 1
 mdb> print *
        Data (arg 1)           	big(big/3, 3, big/3)
 mdb> print Data/1
        Data (arg 1)           	big(big(small, 1, small), 2, small)
-mdb> set -f depth 3
+mdb> format_param -f depth 3
 mdb> print 1
        Data (arg 1)           	big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
 mdb> print Data/1/2
Index: tests/debugger/browser_test.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/browser_test.inp,v
retrieving revision 1.15
diff -u -b -r1.15 browser_test.inp
--- tests/debugger/browser_test.inp	31 Mar 2006 05:12:15 -0000	1.15
+++ tests/debugger/browser_test.inp	1 Apr 2006 13:52:20 -0000
@@ -5,12 +5,12 @@
 finish
 delete *
 dump 1 browser_test.save.1
-set format raw_pretty
+format raw_pretty
 print *
-set -A format verbose
+format -A verbose
 print *
 browse 1; ls; quit
-set -AP format flat
+format -AP flat
 print -f 1
 print -p 1
 print -v 1
@@ -36,14 +36,14 @@
 cdr 3 ../1/..
 ls
 quit
-set xml_tmp_filename './browser_test.xml.out'
-set xml_browser_cmd 'cat ./browser_test.xml.out'
+xml_tmp_filename './browser_test.xml.out'
+xml_browser_cmd 'cat ./browser_test.xml.out'
 browse --xml 1
 browse -x Data
-set -A -f depth 1
+format_param -A -f depth 1
 print *
 print Data/1
-set -f depth 3
+format_param -f depth 3
 print 1
 print Data/1/2
 print 1^1^2^3
Index: tests/debugger/completion.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/completion.exp,v
retrieving revision 1.31
diff -u -b -r1.31 completion.exp
--- tests/debugger/completion.exp	25 Oct 2005 04:00:53 -0000	1.31
+++ tests/debugger/completion.exp	4 Apr 2006 04:28:33 -0000
@@ -3,41 +3,43 @@
 Command echo enabled.
 mdb> register --quiet
 mdb> 
-?                    exception            query
-P                    excp                 quit
-alias                f                    r
-all_class_decls      finish               register
-all_procedures       flag                 retry
-all_regs             forward              return
-all_type_ctors       g                    s
-ambiguity            gen_stack            save
-b                    goal_paths           save_to_file
-break                goto                 scope
-break_print          h                    scroll
-browse               held_vars            set
-c                    help                 source
-cc_query             histogram_all        stack
-class_decl           histogram_exp        stack_default_limit
-clear_histogram      hold                 stack_regs
-condition            ignore               stats
-consumer             io_query             step
-context              level                subgoal
-continue             list                 table
-current              maxdepth             table_io
-cut_stack            mindepth             term_size
-d                    mm_stacks            trust
-dd                   mmc_options          trusted
-debug_vars           modules              type_ctor
-delete               next                 unalias
-dice                 nondet_stack         unhide_events
-diff                 p                    untrust
-disable              pneg_stack           up
-document             pop_list_dir         v
-document_category    print                var_details
-down                 print_optionals      vars
-e                    printlevel           view
-echo                 procedures           
-enable               push_list_dir        
+?                    excp                 print_optionals
+P                    f                    printlevel
+alias                fail_trace_counts    procedures
+all_class_decls      finish               push_list_dir
+all_procedures       flag                 query
+all_regs             format               quit
+all_type_ctors       format_param         r
+ambiguity            forward              register
+b                    g                    retry
+break                gen_stack            return
+break_print          goal_paths           s
+browse               goto                 save
+c                    h                    scope
+cc_query             held_vars            scroll
+class_decl           help                 source
+clear_histogram      histogram_all        stack
+condition            histogram_exp        stack_default_limit
+consumer             hold                 stack_regs
+context              ignore               stats
+continue             io_query             step
+current              level                subgoal
+cut_stack            list                 table
+d                    list_context_lines   table_io
+dd                   list_path            term_size
+debug_vars           max_io_actions       trust
+delete               maxdepth             trusted
+dice                 mindepth             type_ctor
+diff                 mm_stacks            unalias
+disable              mmc_options          unhide_events
+document             modules              untrust
+document_category    next                 up
+down                 nondet_stack         v
+dump                 p                    var_details
+e                    pass_trace_counts    vars
+echo                 pneg_stack           view
+enable               pop_list_dir         xml_browser_cmd
+exception            print                xml_tmp_filename
 h              help           histogram_exp  
 held_vars      histogram_all  hold           
 var_details  vars         view         
@@ -63,7 +65,9 @@
 List of procedures in module `completion.sub1'
 pred completion.sub1.zp/1-0 (det)
 func completion.sub1.z1/0-0 (det)
-mdb> set --flat format pretty 
+mdb> 
+format        format_param  
+format_param  --flat  lines 10
 mdb> unalias excp 
 Alias `excp' removed.
 mdb> b zabc3 
@@ -91,7 +95,7 @@
 mdb> 
 2d                  2dice               2document_category
 2dd                 2diff               2down
-2debug_vars         2disable            
+2debug_vars         2disable            2dump
 2delete             2document           
 2debug_vars  2delete      
 2delete 
Index: tests/debugger/completion.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/completion.inp,v
retrieving revision 1.11
diff -u -b -r1.11 completion.inp
--- tests/debugger/completion.inp	1 Aug 2005 02:40:11 -0000	1.11
+++ tests/debugger/completion.inp	4 Apr 2006 01:04:40 -0000
@@ -4,7 +4,7 @@
 p --f@@D@
 stac@ @
 proc at complet@. at 1
-set --f at fo@p@
+form at _par@ --f@ lines 10
 una at ex@
 b za@
 b func*complet at z@
Index: tests/debugger/dice.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/dice.exp,v
retrieving revision 1.3
diff -u -b -r1.3 dice.exp
--- tests/debugger/dice.exp	29 Mar 2006 00:57:42 -0000	1.3
+++ tests/debugger/dice.exp	1 Apr 2006 13:44:17 -0000
@@ -26,8 +26,8 @@
 pred dice.msort_n/4-0    <e;t;>           dice.m:50   11 (3)    4      0.27
 pred dice.msort_n/4-0    <e;t;s2;>        dice.m:47   11 (3)    4      0.27
 pred dice.msort_n/4-0    <e;e;>           dice.m:55    8 (3)    3      0.27
-mdb> set fail_trace_count dice.fail
-mdb> set pass_trace_counts dice.passes
+mdb> fail_trace_counts dice.fail
+mdb> pass_trace_counts dice.passes
 mdb> dice -sS -m dice
 Procedure                Path/Port        File:Line Pass (3) Fail Suspicion
 pred dice.merge/3-0      <s2;c2;s2;c4;e;> dice.m:74    0 (0)    1      1.00
Index: tests/debugger/dice.exp2
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/dice.exp2,v
retrieving revision 1.1
diff -u -b -r1.1 dice.exp2
--- tests/debugger/dice.exp2	10 Feb 2005 04:10:31 -0000	1.1
+++ tests/debugger/dice.exp2	1 Apr 2006 13:44:22 -0000
@@ -54,8 +54,8 @@
 func int.+/2-0                   EXIT             int.m:82            44 (3)   13      0.23
 func int.-/2-0                   CALL             int.m:96            34 (3)   11      0.24
 func int.-/2-0                   EXIT             int.m:96            34 (3)   11      0.24
-mdb> set fail_trace_count dice.fail
-mdb> set pass_trace_counts dice.passes
+mdb> fail_trace_counts dice.fail
+mdb> pass_trace_counts dice.passes
 mdb> dice -sS
 Procedure                          Path/Port        File:Line       Pass (3) Fail Suspicion
 pred dice.merge/3-0                <s2;c2;s2;c4;e;> dice.m:74          0 (0)    1      1.00
Index: tests/debugger/dice.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/dice.inp,v
retrieving revision 1.2
diff -u -b -r1.2 dice.inp
--- tests/debugger/dice.inp	18 Feb 2005 04:05:35 -0000	1.2
+++ tests/debugger/dice.inp	1 Apr 2006 13:44:28 -0000
@@ -2,8 +2,8 @@
 context none
 echo on
 dice -f dice.fail -p dice.passes -m dice
-set fail_trace_count dice.fail
-set pass_trace_counts dice.passes
+fail_trace_counts dice.fail
+pass_trace_counts dice.passes
 dice -sS -m dice
 dice -sSF -m dice
 dice -n 3 -s P -m dice
Index: tests/debugger/exception_value.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/exception_value.exp,v
retrieving revision 1.9
diff -u -b -r1.9 exception_value.exp
--- tests/debugger/exception_value.exp	16 Nov 2004 00:16:38 -0000	1.9
+++ tests/debugger/exception_value.exp	2 Apr 2006 17:03:14 -0000
@@ -21,8 +21,8 @@
 mdb> finish
       E5:     C3 EXCP pred exception_value.q/1-0 (det)
 mdb> browse exception
-browser> set depth 9
-browser> set size 99
+browser> depth 9
+browser> size 99
 browser> ls
 "q oops" - [1, 2, 3]
 browser> quit
Index: tests/debugger/exception_value.exp2
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/exception_value.exp2,v
retrieving revision 1.9
diff -u -b -r1.9 exception_value.exp2
--- tests/debugger/exception_value.exp2	16 Nov 2004 00:16:38 -0000	1.9
+++ tests/debugger/exception_value.exp2	2 Apr 2006 17:03:25 -0000
@@ -18,8 +18,8 @@
 mdb> finish
       E5:     C3 EXCP pred exception_value.q/1-0 (det)
 mdb> browse exception
-browser> set depth 9
-browser> set size 99
+browser> depth 9
+browser> size 99
 browser> ls
 "q oops" - [1, 2, 3]
 browser> quit
Index: tests/debugger/exception_value.exp3
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/exception_value.exp3,v
retrieving revision 1.2
diff -u -b -r1.2 exception_value.exp3
--- tests/debugger/exception_value.exp3	10 Nov 2004 02:21:40 -0000	1.2
+++ tests/debugger/exception_value.exp3	2 Apr 2006 17:04:06 -0000
@@ -18,8 +18,8 @@
 mdb> finish
       E5:     C3  8 EXCP pred exception_value.q/1-0 (det)
 mdb> browse exception
-browser> set depth 9
-browser> set size 99
+browser> depth 9
+browser> size 99
 browser> ls
 "q oops" - [1, 2, 3]
 browser> quit
Index: tests/debugger/exception_value.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/exception_value.inp,v
retrieving revision 1.1
diff -u -b -r1.1 exception_value.inp
--- tests/debugger/exception_value.inp	19 Jun 2000 07:59:20 -0000	1.1
+++ tests/debugger/exception_value.inp	2 Apr 2006 17:03:06 -0000
@@ -8,8 +8,8 @@
 continue
 finish
 browse exception
-set depth 9
-set size 99
+depth 9
+size 99
 ls
 quit
 continue
Index: tests/debugger/higher_order.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/higher_order.exp,v
retrieving revision 1.7
diff -u -b -r1.7 higher_order.exp
--- tests/debugger/higher_order.exp	26 May 2005 00:17:04 -0000	1.7
+++ tests/debugger/higher_order.exp	1 Apr 2006 13:45:19 -0000
@@ -3,9 +3,9 @@
 Command echo enabled.
 mdb> context none
 Contexts will not be printed.
-mdb> set size 100
-mdb> set depth 100
-mdb> set format flat
+mdb> format_param size 100
+mdb> format_param depth 100
+mdb> format flat
 mdb> step
       E2:     C2 CALL pred higher_order.domap/3-0 (det)
 mdb> print *
Index: tests/debugger/higher_order.exp2
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/higher_order.exp2,v
retrieving revision 1.2
diff -u -b -r1.2 higher_order.exp2
--- tests/debugger/higher_order.exp2	17 Jan 2003 05:56:53 -0000	1.2
+++ tests/debugger/higher_order.exp2	1 Apr 2006 13:45:30 -0000
@@ -3,9 +3,9 @@
 Command echo enabled.
 mdb> context none
 Contexts will not be printed.
-mdb> set size 100
-mdb> set depth 100
-mdb> set format flat
+mdb> format_param size 100
+mdb> format_param depth 100
+mdb> format flat
 mdb> step
        2:      2  2 CALL pred higher_order.domap/3-0 (det)
 mdb> print *
Index: tests/debugger/higher_order.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/higher_order.inp,v
retrieving revision 1.1
diff -u -b -r1.1 higher_order.inp
--- tests/debugger/higher_order.inp	24 Feb 2002 11:53:39 -0000	1.1
+++ tests/debugger/higher_order.inp	1 Apr 2006 13:46:02 -0000
@@ -1,8 +1,8 @@
 echo on
 context none
-set size 100
-set depth 100
-set format flat
+format_param size 100
+format_param depth 100
+format flat
 step
 print *
 finish
Index: tests/debugger/loopcheck.exp3
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/loopcheck.exp3,v
retrieving revision 1.4
diff -u -b -r1.4 loopcheck.exp3
--- tests/debugger/loopcheck.exp3	7 Dec 2005 16:07:13 -0000	1.4
+++ tests/debugger/loopcheck.exp3	2 Apr 2006 17:05:36 -0000
@@ -10,9 +10,9 @@
  1: + stop  interface pred loopcheck.loop/1-0 (det)
 mdb> finish
        2:      2  2 CALL pred loopcheck.loop/1-0 (det)
-                         loopcheck.m:21 (from loopcheck.m:14)
+                         loopcheck.m:20 (from loopcheck.m:14)
        3:      3  3 CALL pred loopcheck.loop/1-0 (det)
-                         loopcheck.m:21 (from loopcheck.m:21)
+                         loopcheck.m:20 (from loopcheck.m:21)
       12:      3  3 EXCP pred loopcheck.loop/1-0 (det)
                          loopcheck.m:21 (from loopcheck.m:21)
       13:      2  2 EXCP pred loopcheck.loop/1-0 (det)
Index: tests/debugger/mdb_command_test.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/mdb_command_test.inp,v
retrieving revision 1.49
diff -u -b -r1.49 mdb_command_test.inp
--- tests/debugger/mdb_command_test.inp	31 Mar 2006 05:12:15 -0000	1.49
+++ tests/debugger/mdb_command_test.inp	4 Apr 2006 04:21:46 -0000
@@ -7,7 +7,13 @@
 mode                 xyzzy xyzzy xyzzy xyzzy xyzzy
 browse               xyzzy xyzzy xyzzy xyzzy xyzzy
 print                xyzzy xyzzy xyzzy xyzzy xyzzy
-set                  xyzzy xyzzy xyzzy xyzzy xyzzy
+format               xyzzy xyzzy xyzzy xyzzy xyzzy
+depth                xyzzy xyzzy xyzzy xyzzy xyzzy
+size                 xyzzy xyzzy xyzzy xyzzy xyzzy
+width                xyzzy xyzzy xyzzy xyzzy xyzzy
+lines                xyzzy xyzzy xyzzy xyzzy xyzzy
+actions              xyzzy xyzzy xyzzy xyzzy xyzzy
+params               xyzzy xyzzy xyzzy xyzzy xyzzy
 track                xyzzy xyzzy xyzzy xyzzy xyzzy
 mark                 xyzzy xyzzy xyzzy xyzzy xyzzy
 pd                   xyzzy xyzzy xyzzy xyzzy xyzzy
@@ -41,8 +47,6 @@
 diff                 xyzzy xyzzy xyzzy xyzzy xyzzy
 dump                 xyzzy xyzzy xyzzy xyzzy xyzzy
 list                 xyzzy xyzzy xyzzy xyzzy xyzzy
-push_list_dir        xyzzy xyzzy xyzzy xyzzy xyzzy
-pop_list_dir         xyzzy xyzzy xyzzy xyzzy xyzzy
 break                xyzzy xyzzy xyzzy xyzzy xyzzy
 condition            xyzzy xyzzy xyzzy xyzzy xyzzy
 ignore               xyzzy xyzzy xyzzy xyzzy xyzzy
@@ -56,18 +60,28 @@
 table_io             xyzzy xyzzy xyzzy xyzzy xyzzy
 mmc_options          xyzzy xyzzy xyzzy xyzzy xyzzy
 printlevel           xyzzy xyzzy xyzzy xyzzy xyzzy
-echo                 xyzzy xyzzy xyzzy xyzzy xyzzy
 scroll               xyzzy xyzzy xyzzy xyzzy xyzzy
 stack_default_limit  xyzzy xyzzy xyzzy xyzzy xyzzy
-context              xyzzy xyzzy xyzzy xyzzy xyzzy
 goal_paths           xyzzy xyzzy xyzzy xyzzy xyzzy
 scope                xyzzy xyzzy xyzzy xyzzy xyzzy
+echo                 xyzzy xyzzy xyzzy xyzzy xyzzy
+context              xyzzy xyzzy xyzzy xyzzy xyzzy
+list_context_lines   xyzzy xyzzy xyzzy xyzzy xyzzy
+list_path            xyzzy xyzzy xyzzy xyzzy xyzzy
+push_list_dir        xyzzy xyzzy xyzzy xyzzy xyzzy
+pop_list_dir         xyzzy xyzzy xyzzy xyzzy xyzzy
+fail_trace_counts    xyzzy xyzzy xyzzy xyzzy xyzzy
+pass_trace_counts    xyzzy xyzzy xyzzy xyzzy xyzzy
+max_io_actions       xyzzy xyzzy xyzzy xyzzy xyzzy
+xml_browser_cmd      xyzzy xyzzy xyzzy xyzzy xyzzy
+xml_tmp_filename     xyzzy xyzzy xyzzy xyzzy xyzzy
+format               xyzzy xyzzy xyzzy xyzzy xyzzy
+format_param         xyzzy xyzzy xyzzy xyzzy xyzzy
 unalias              xyzzy xyzzy xyzzy xyzzy xyzzy
 dd                   xyzzy xyzzy xyzzy xyzzy xyzzy
 trust                xyzzy xyzzy xyzzy xyzzy xyzzy
 trusted              xyzzy xyzzy xyzzy xyzzy xyzzy
 untrust              xyzzy xyzzy xyzzy xyzzy xyzzy
-set                  xyzzy xyzzy xyzzy xyzzy xyzzy
 source               xyzzy xyzzy xyzzy xyzzy xyzzy
 save                 xyzzy xyzzy xyzzy xyzzy xyzzy
 quit                 xyzzy xyzzy xyzzy xyzzy xyzzy
Index: tests/debugger/polymorphic_output.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/polymorphic_output.exp,v
retrieving revision 1.16
diff -u -b -r1.16 polymorphic_output.exp
--- tests/debugger/polymorphic_output.exp	23 Mar 2006 02:11:57 -0000	1.16
+++ tests/debugger/polymorphic_output.exp	1 Apr 2006 13:46:21 -0000
@@ -12,8 +12,8 @@
  0: E stop  interface func polymorphic_output.functor_names/1-0 (det)
 mdb> p goal
 functor_names(two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))) = _
-mdb> set format verbose
-mdb> set lines 100
+mdb> format verbose
+mdb> format_param lines 100
 mdb> p goal
 functor_names
 1-two
@@ -34,7 +34,7 @@
 |   4-empty
 2-_
 
-mdb> set format flat
+mdb> format flat
 mdb> browse goal
 browser> ^1
 browser> p
Index: tests/debugger/polymorphic_output.exp2
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/polymorphic_output.exp2,v
retrieving revision 1.19
diff -u -b -r1.19 polymorphic_output.exp2
--- tests/debugger/polymorphic_output.exp2	22 Mar 2006 02:56:26 -0000	1.19
+++ tests/debugger/polymorphic_output.exp2	1 Apr 2006 13:46:32 -0000
@@ -12,8 +12,8 @@
  0: E stop  interface func polymorphic_output.functor_names/1-0 (det)
 mdb> p goal
 functor_names(two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))) = _
-mdb> set format verbose
-mdb> set lines 100
+mdb> format verbose
+mdb> format_param lines 100
 mdb> p goal
 functor_names
 1-two
@@ -34,7 +34,7 @@
 |   4-empty
 2-_
 
-mdb> set format flat
+mdb> format flat
 mdb> browse goal
 browser> ^1
 browser> p
Index: tests/debugger/polymorphic_output.exp3
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/polymorphic_output.exp3,v
retrieving revision 1.11
diff -u -b -r1.11 polymorphic_output.exp3
--- tests/debugger/polymorphic_output.exp3	8 Feb 2006 21:48:34 -0000	1.11
+++ tests/debugger/polymorphic_output.exp3	1 Apr 2006 13:46:42 -0000
@@ -12,8 +12,8 @@
  0: E stop  interface func polymorphic_output.functor_names/1-0 (det)
 mdb> p goal
 functor_names(two("three", 3, three("four", 4, "one", 1, empty, empty, empty), two("two", 2, empty, empty))) = _
-mdb> set format verbose
-mdb> set lines 100
+mdb> format verbose
+mdb> format_param lines 100
 mdb> p goal
 functor_names
 1-two
@@ -34,7 +34,7 @@
 |   4-empty
 2-_
 
-mdb> set format flat
+mdb> format flat
 mdb> browse goal
 browser> ^1
 browser> p
Index: tests/debugger/polymorphic_output.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/polymorphic_output.inp,v
retrieving revision 1.4
diff -u -b -r1.4 polymorphic_output.inp
--- tests/debugger/polymorphic_output.inp	22 Mar 2006 02:56:26 -0000	1.4
+++ tests/debugger/polymorphic_output.inp	1 Apr 2006 13:46:52 -0000
@@ -5,10 +5,10 @@
 c
 delete 0
 p goal
-set format verbose
-set lines 100
+format verbose
+format_param lines 100
 p goal
-set format flat
+format flat
 browse goal
 ^1
 p
Index: tests/debugger/save.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/save.exp,v
retrieving revision 1.1
diff -u -b -r1.1 save.exp
--- tests/debugger/save.exp	31 Mar 2006 05:12:15 -0000	1.1
+++ tests/debugger/save.exp	1 Apr 2006 11:19:02 -0000
@@ -49,58 +49,58 @@
 break pred*save.nodiag/3-0
 condition B = 5
 scope interface
-set -P format flat
-set -P -f depth 3
-set -P -f size 10
-set -P -f width 80
-set -P -f lines 25
-set -P -r depth 3
-set -P -r size 10
-set -P -r width 80
-set -P -r lines 25
-set -P -v depth 3
-set -P -v size 10
-set -P -v width 80
-set -P -v lines 25
-set -P -p depth 3
-set -P -p size 10
-set -P -p width 80
-set -P -p lines 25
-set -B format flat
-set -B -f depth 10
-set -B -f size 30
-set -B -f width 80
-set -B -f lines 25
-set -B -r depth 10
-set -B -r size 30
-set -B -r width 80
-set -B -r lines 25
-set -B -v depth 10
-set -B -v size 30
-set -B -v width 80
-set -B -v lines 25
-set -B -p depth 10
-set -B -p size 30
-set -B -p width 80
-set -B -p lines 25
-set -A format flat
-set -A -f depth 3
-set -A -f size 10
-set -A -f width 80
-set -A -f lines 2
-set -A -r depth 3
-set -A -r size 10
-set -A -r width 80
-set -A -r lines 2
-set -A -v depth 3
-set -A -v size 10
-set -A -v width 80
-set -A -v lines 5
-set -A -p depth 3
-set -A -p size 10
-set -A -p width 80
-set -A -p lines 2
-set max_io_actions 20
+format -P flat
+format_param -P -f depth 3
+format_param -P -f size 10
+format_param -P -f width 80
+format_param -P -f lines 25
+format_param -P -r depth 3
+format_param -P -r size 10
+format_param -P -r width 80
+format_param -P -r lines 25
+format_param -P -v depth 3
+format_param -P -v size 10
+format_param -P -v width 80
+format_param -P -v lines 25
+format_param -P -p depth 3
+format_param -P -p size 10
+format_param -P -p width 80
+format_param -P -p lines 25
+format -B flat
+format_param -B -f depth 10
+format_param -B -f size 30
+format_param -B -f width 80
+format_param -B -f lines 25
+format_param -B -r depth 10
+format_param -B -r size 30
+format_param -B -r width 80
+format_param -B -r lines 25
+format_param -B -v depth 10
+format_param -B -v size 30
+format_param -B -v width 80
+format_param -B -v lines 25
+format_param -B -p depth 10
+format_param -B -p size 30
+format_param -B -p width 80
+format_param -B -p lines 25
+format -A flat
+format_param -A -f depth 3
+format_param -A -f size 10
+format_param -A -f width 80
+format_param -A -f lines 2
+format_param -A -r depth 3
+format_param -A -r size 10
+format_param -A -r width 80
+format_param -A -r lines 2
+format_param -A -v depth 3
+format_param -A -v size 10
+format_param -A -v width 80
+format_param -A -v lines 5
+format_param -A -p depth 3
+format_param -A -p size 10
+format_param -A -p width 80
+format_param -A -p lines 2
+max_io_actions 20
 trust save
 trust std lib
-set list_context_lines 2
+list_context_lines 2
cvs diff: Diffing tests/debugger/declarative
Index: tests/debugger/declarative/browse_arg.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/browse_arg.exp,v
retrieving revision 1.9
diff -u -b -r1.9 browse_arg.exp
--- tests/debugger/declarative/browse_arg.exp	29 Mar 2006 08:07:55 -0000	1.9
+++ tests/debugger/declarative/browse_arg.exp	1 Apr 2006 14:13:11 -0000
@@ -8,9 +8,9 @@
        2:      2  2 CALL pred browse_arg.p/2-0 (det) browse_arg.m:19 (browse_arg.m:8)
 mdb> finish
        3:      2  2 EXIT pred browse_arg.p/2-0 (det) browse_arg.m:19 (browse_arg.m:8)
-mdb> set depth 10
-mdb> set xml_browser_cmd 'cat ./browse_arg.xml.out'
-mdb> set xml_tmp_filename './browse_arg.xml.out'
+mdb> format_param depth 10
+mdb> xml_browser_cmd 'cat ./browse_arg.xml.out'
+mdb> xml_tmp_filename './browse_arg.xml.out'
 mdb> dd -d 3 -n 7
 p(1, baz(1, bar))
 Valid? browse 2
Index: tests/debugger/declarative/browse_arg.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/browse_arg.inp,v
retrieving revision 1.6
diff -u -b -r1.6 browse_arg.inp
--- tests/debugger/declarative/browse_arg.inp	20 May 2005 05:40:21 -0000	1.6
+++ tests/debugger/declarative/browse_arg.inp	3 Apr 2006 16:12:48 -0000
@@ -3,18 +3,18 @@
 break p
 continue
 finish
-set depth 10
-set xml_browser_cmd 'cat ./browse_arg.xml.out'
-set xml_tmp_filename './browse_arg.xml.out'
+format_param depth 10
+xml_browser_cmd 'cat ./browse_arg.xml.out'
+xml_tmp_filename './browse_arg.xml.out'
 dd -d 3 -n 7
 browse 2
 ls
 quit
-set format verbose
+format verbose
 print
-set -B format pretty
+format -B pretty
 p
-set -P format pretty
+format -P pretty
 p
 b -x 2
 b --xml
Index: tests/debugger/declarative/change_search.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/change_search.exp,v
retrieving revision 1.2
diff -u -b -r1.2 change_search.exp
--- tests/debugger/declarative/change_search.exp	24 Aug 2005 09:07:12 -0000	1.2
+++ tests/debugger/declarative/change_search.exp	3 Apr 2006 18:39:52 -0000
@@ -8,8 +8,8 @@
       E2:     C2 CALL pred change_search.mylast/2-0 (det)
 mdb> finish -n
       E3:     C2 EXIT pred change_search.mylast/2-0 (det)
-mdb> set format pretty
-mdb> set depth 10
+mdb> format pretty
+mdb> format_param depth 10
 mdb> dd
 mylast([1, 2, 3, 4, 5, 6, 7, 8, ...], no)
 Valid? info
Index: tests/debugger/declarative/change_search.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/change_search.inp,v
retrieving revision 1.1
diff -u -b -r1.1 change_search.inp
--- tests/debugger/declarative/change_search.inp	19 Aug 2005 16:08:31 -0000	1.1
+++ tests/debugger/declarative/change_search.inp	3 Apr 2006 16:13:53 -0000
@@ -4,8 +4,8 @@
 break mylast
 continue
 finish -n
-set format pretty
-set depth 10
+format pretty
+format_param depth 10
 dd
 info
 no
Index: tests/debugger/declarative/dependency.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/dependency.exp,v
retrieving revision 1.11
diff -u -b -r1.11 dependency.exp
--- tests/debugger/declarative/dependency.exp	20 May 2005 05:40:22 -0000	1.11
+++ tests/debugger/declarative/dependency.exp	3 Apr 2006 18:40:02 -0000
@@ -15,9 +15,9 @@
        4:      3  2 CALL pred dependency.test/1-0 (cc_multi) dependency.m:19 (dependency.m:13)
 mdb> finish
       18:      3  2 EXIT pred dependency.test/1-0 (cc_multi) dependency.m:19 (dependency.m:13)
-mdb> set depth 20
-mdb> set size 201
-mdb> set format raw_pretty
+mdb> format_param depth 20
+mdb> format_param size 201
+mdb> format raw_pretty
 mdb> p proc_body
 	
 proc_rep(
Index: tests/debugger/declarative/dependency.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/dependency.inp,v
retrieving revision 1.5
diff -u -b -r1.5 dependency.inp
--- tests/debugger/declarative/dependency.inp	20 May 2005 05:40:22 -0000	1.5
+++ tests/debugger/declarative/dependency.inp	3 Apr 2006 16:14:25 -0000
@@ -6,9 +6,9 @@
 quit
 step
 finish
-set depth 20
-set size 201
-set format raw_pretty
+format_param depth 20
+format_param size 201
+format raw_pretty
 p proc_body
 dd -d 3 -n 7
 browse 1
Index: tests/debugger/declarative/dice.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/dice.exp,v
retrieving revision 1.1
diff -u -b -r1.1 dice.exp
--- tests/debugger/declarative/dice.exp	24 Aug 2005 09:07:12 -0000	1.1
+++ tests/debugger/declarative/dice.exp	3 Apr 2006 18:40:19 -0000
@@ -12,8 +12,8 @@
  0: E stop  interface pred dice.merge_sort/2-0 (det)
 mdb> finish
       E3:     C2 EXIT pred dice.merge_sort/2-0 (det)
-mdb> set format pretty
-mdb> set depth 10
+mdb> format pretty
+mdb> format_param depth 10
 mdb> dd -s sdq -f dice.fail -p dice.pass
 merge_sort([4, 1, 2, 3], [1, 1, 2, 3])
 Valid? n
Index: tests/debugger/declarative/dice.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/dice.inp,v
retrieving revision 1.1
diff -u -b -r1.1 dice.inp
--- tests/debugger/declarative/dice.inp	24 Aug 2005 09:07:12 -0000	1.1
+++ tests/debugger/declarative/dice.inp	3 Apr 2006 16:14:47 -0000
@@ -6,8 +6,8 @@
 continue
 delete *
 finish
-set format pretty
-set depth 10
+format pretty
+format_param depth 10
 dd -s sdq -f dice.fail -p dice.pass
 n
 n
Index: tests/debugger/declarative/divide_and_query1.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/divide_and_query1.exp,v
retrieving revision 1.3
diff -u -b -r1.3 divide_and_query1.exp
--- tests/debugger/declarative/divide_and_query1.exp	20 May 2005 05:40:22 -0000	1.3
+++ tests/debugger/declarative/divide_and_query1.exp	3 Apr 2006 18:40:29 -0000
@@ -2,8 +2,8 @@
 mdb> mdb> Contexts will not be printed.
 mdb> echo on
 Command echo enabled.
-mdb> set format flat
-mdb> set size 100
+mdb> format flat
+mdb> format_param size 100
 mdb> break to_b
  0: + stop  interface pred divide_and_query1.to_b/2-0 (det)
 mdb> c -n
Index: tests/debugger/declarative/divide_and_query1.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/divide_and_query1.inp,v
retrieving revision 1.2
diff -u -b -r1.2 divide_and_query1.inp
--- tests/debugger/declarative/divide_and_query1.inp	20 May 2005 05:40:23 -0000	1.2
+++ tests/debugger/declarative/divide_and_query1.inp	3 Apr 2006 16:16:01 -0000
@@ -1,8 +1,8 @@
 register --quiet
 context none
 echo on
-set format flat
-set size 100
+format flat
+format_param size 100
 break to_b
 c -n
 f -n
Index: tests/debugger/declarative/find_origin.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/find_origin.inp,v
retrieving revision 1.2
diff -u -b -r1.2 find_origin.inp
--- tests/debugger/declarative/find_origin.inp	20 May 2005 05:40:24 -0000	1.2
+++ tests/debugger/declarative/find_origin.inp	3 Apr 2006 16:13:04 -0000
@@ -19,7 +19,7 @@
 b 2
 mark
 browse
-set format pretty
+format pretty
 p
 quit
 no
Index: tests/debugger/declarative/sort.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/sort.exp,v
retrieving revision 1.1
diff -u -b -r1.1 sort.exp
--- tests/debugger/declarative/sort.exp	20 May 2005 07:14:35 -0000	1.1
+++ tests/debugger/declarative/sort.exp	4 Apr 2006 01:16:31 -0000
@@ -10,8 +10,8 @@
 ian
 ian
       E2:     C1 EXIT pred sort.main/2-0 (det) sort.m:27
-mdb> set format pretty
-mdb> set depth 1
+mdb> format pretty
+mdb> format_param depth 1
 mdb> dd
 main(...)
 16 tabled IO actions:
@@ -31,10 +31,10 @@
 write_string(...)
 write_string(...)
 write_string(...)
-Valid? set depth 10
+Valid? depth 10
 dd> print io 9
 read_line_as_string_2(<<foreign>>, yes, -1, "")
-dd> set depth 1
+dd> depth 1
 dd> no
 open_stream(...)
 3 tabled IO actions:
Index: tests/debugger/declarative/sort.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/sort.inp,v
retrieving revision 1.1
diff -u -b -r1.1 sort.inp
--- tests/debugger/declarative/sort.inp	20 May 2005 07:14:36 -0000	1.1
+++ tests/debugger/declarative/sort.inp	3 Apr 2006 16:19:45 -0000
@@ -2,12 +2,12 @@
 register --quiet
 table_io start
 finish
-set format pretty
-set depth 1
+format pretty
+format_param depth 1
 dd
-set depth 10
+depth 10
 print io 9
-set depth 1
+depth 1
 no
 yes
 quit
Index: tests/debugger/declarative/tabled_read_decl.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/tabled_read_decl.exp,v
retrieving revision 1.15
diff -u -b -r1.15 tabled_read_decl.exp
--- tests/debugger/declarative/tabled_read_decl.exp	20 May 2005 05:40:30 -0000	1.15
+++ tests/debugger/declarative/tabled_read_decl.exp	3 Apr 2006 18:44:20 -0000
@@ -34,10 +34,10 @@
 dd> browse io 4
 browser> print
 read_char_code('<<c_pointer>>', 10)
-browser> set num_io_actions 3
+browser> num_io_actions 3
 browser> quit
 dd> browse 1
-browser> set num_io_actions 10
+browser> num_io_actions 10
 browser> quit
 dd> no
 test_2('<<c_pointer>>', 1, 1123, _, _)
Index: tests/debugger/declarative/tabled_read_decl.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/tabled_read_decl.inp,v
retrieving revision 1.6
diff -u -b -r1.6 tabled_read_decl.inp
--- tests/debugger/declarative/tabled_read_decl.inp	20 May 2005 05:40:30 -0000	1.6
+++ tests/debugger/declarative/tabled_read_decl.inp	3 Apr 2006 16:17:15 -0000
@@ -13,10 +13,10 @@
 print io 2-1
 browse io 4
 print
-set num_io_actions 3
+num_io_actions 3
 quit
 browse 1
-set num_io_actions 10
+num_io_actions 10
 quit
 no
 yes
Index: tests/debugger/declarative/tabled_read_decl_goto.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/tabled_read_decl_goto.exp,v
retrieving revision 1.1
diff -u -b -r1.1 tabled_read_decl_goto.exp
--- tests/debugger/declarative/tabled_read_decl_goto.exp	16 Sep 2005 05:42:58 -0000	1.1
+++ tests/debugger/declarative/tabled_read_decl_goto.exp	3 Apr 2006 18:44:27 -0000
@@ -34,10 +34,10 @@
 dd> browse io 4
 browser> print
 read_char_code('<<c_pointer>>', 10)
-browser> set num_io_actions 3
+browser> num_io_actions 3
 browser> quit
 dd> browse 1
-browser> set num_io_actions 10
+browser> num_io_actions 10
 browser> quit
 dd> no
 test_2('<<c_pointer>>', 1, 1123, _, _)
Index: tests/debugger/declarative/tabled_read_decl_goto.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/tabled_read_decl_goto.inp,v
retrieving revision 1.1
diff -u -b -r1.1 tabled_read_decl_goto.inp
--- tests/debugger/declarative/tabled_read_decl_goto.inp	16 Sep 2005 05:42:58 -0000	1.1
+++ tests/debugger/declarative/tabled_read_decl_goto.inp	3 Apr 2006 16:17:47 -0000
@@ -13,10 +13,10 @@
 print io 2-1
 browse io 4
 print
-set num_io_actions 3
+num_io_actions 3
 quit
 browse 1
-set num_io_actions 10
+num_io_actions 10
 quit
 no
 yes
Index: tests/debugger/declarative/track_through_catch.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/declarative/track_through_catch.exp,v
retrieving revision 1.4
diff -u -b -r1.4 track_through_catch.exp
--- tests/debugger/declarative/track_through_catch.exp	30 Mar 2006 04:44:59 -0000	1.4
+++ tests/debugger/declarative/track_through_catch.exp	3 Apr 2006 18:45:27 -0000
@@ -35,13 +35,14 @@
 Valid? b 2
 browser> cd 1
 browser> track
-cc_multi_equal(succeeded(2), succeeded(2))
+succeeded(2)
+p(2)
 Valid? info
-Context of current question : builtin.m:1061 (exception.m:488)
+Context of current question : track_through_catch.m:21 (track_through_catch.m:14)
 Search mode                 : top down                        
 The current question was chosen because the marked subterm was bound by
-the foreign procedure call inside the predicate builtin.cc_multi_equal/2
-(builtin.m:1055). The path to the subterm in the atom is 2/1.
+the unification inside the predicate track_through_catch.p/1
+(track_through_catch.m:21). The path to the subterm in the atom is 1.
 dd> quit
 Diagnosis aborted.
       E5:     C2 EXIT pred exception.try/2-0 (cc_multi) exception.m:480 (track_through_catch.m:15)
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/trailing
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
Index: trace/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/Mmakefile,v
retrieving revision 1.44
diff -u -b -r1.44 Mmakefile
--- trace/Mmakefile	11 Jul 2005 07:30:30 -0000	1.44
+++ trace/Mmakefile	3 Apr 2006 12:39:22 -0000
@@ -13,6 +13,18 @@
 HDRS		=	\
 			mercury_trace_alias.h		\
 			mercury_trace_browse.h		\
+			mercury_trace_cmd_backward.h	\
+			mercury_trace_cmd_breakpoint.h	\
+			mercury_trace_cmd_browsing.h	\
+			mercury_trace_cmd_dd.h		\
+			mercury_trace_cmd_developer.h	\
+			mercury_trace_cmd_exp.h		\
+			mercury_trace_cmd_help.h	\
+			mercury_trace_cmd_misc.h	\
+			mercury_trace_cmd_parameter.h	\
+			mercury_trace_cmd_queries.h	\
+			mercury_trace_cmds.h		\
+			mercury_trace_cmd_table_io.h	\
 			mercury_trace_completion.h	\
 			mercury_trace_declarative.h	\
 			mercury_trace_external.h 	\
@@ -32,6 +44,18 @@
 			mercury_trace_alias.c		\
 			mercury_trace_browse.c		\
 			mercury_trace.c			\
+			mercury_trace_cmd_backward.c	\
+			mercury_trace_cmd_breakpoint.c	\
+			mercury_trace_cmd_browsing.c	\
+			mercury_trace_cmd_dd.c		\
+			mercury_trace_cmd_developer.c	\
+			mercury_trace_cmd_exp.c		\
+			mercury_trace_cmd_forward.c	\
+			mercury_trace_cmd_help.c	\
+			mercury_trace_cmd_misc.c	\
+			mercury_trace_cmd_parameter.c	\
+			mercury_trace_cmd_queries.c	\
+			mercury_trace_cmd_table_io.c	\
 			mercury_trace_completion.c	\
 			mercury_trace_declarative.c	\
 			mercury_trace_external.c 	\
Index: trace/mercury_trace_alias.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_alias.c,v
retrieving revision 1.9
diff -u -b -r1.9 mercury_trace_alias.c
--- trace/mercury_trace_alias.c	31 Mar 2006 05:12:18 -0000	1.9
+++ trace/mercury_trace_alias.c	3 Apr 2006 12:24:32 -0000
@@ -18,11 +18,15 @@
 #include "mercury_array_macros.h"
 
 #include "mercury_trace_alias.h"
+#include "mercury_trace_util.h"
 
 static  MR_Alias    *MR_alias_records = NULL;
 static  int         MR_alias_record_max = 0;
 static  int         MR_alias_record_next = 0;
 
+/* The initial size of arrays of words. */
+#define MR_INIT_WORD_COUNT  20
+
 /* The initial size of the alias table. */
 #define INIT_ALIAS_COUNT    32
 
@@ -179,4 +183,43 @@
 MR_trace_filter_alias_completions(const char *word, MR_Completer_Data *data)
 {
     return (MR_strdiff(word, "EMPTY") && MR_strdiff(word, "NUMBER"));
+}
+
+void
+MR_trace_expand_aliases(char ***words, int *word_max, int *word_count)
+{
+    const char  *alias_key;
+    char        **alias_words;
+    int         alias_word_count;
+    int         alias_copy_start;
+    int         i;
+    int         n;
+
+    if (*word_count == 0) {
+        alias_key = "EMPTY";
+        alias_copy_start = 0;
+    } else if (MR_trace_is_natural_number(*words[0], &n)) {
+        alias_key = "NUMBER";
+        alias_copy_start = 0;
+    } else {
+        alias_key = *words[0];
+        alias_copy_start = 1;
+    }
+
+    if (MR_trace_lookup_alias(alias_key, &alias_words, &alias_word_count)) {
+        MR_ensure_big_enough(*word_count + alias_word_count, *word, char *,
+            MR_INIT_WORD_COUNT);
+
+        /* Move the original words (except the alias key) up. */
+        for (i = *word_count - 1; i >= alias_copy_start; i--) {
+            (*words)[i + alias_word_count - alias_copy_start] = (*words)[i];
+        }
+
+        /* Move the alias body to the words array. */
+        for (i = 0; i < alias_word_count; i++) {
+            (*words)[i] = alias_words[i];
+        }
+
+        *word_count += alias_word_count - alias_copy_start;
+    }
 }
Index: trace/mercury_trace_alias.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_alias.h,v
retrieving revision 1.6
diff -u -b -r1.6 mercury_trace_alias.h
--- trace/mercury_trace_alias.h	31 Mar 2006 05:12:18 -0000	1.6
+++ trace/mercury_trace_alias.h	3 Apr 2006 08:15:22 -0000
@@ -73,9 +73,19 @@
 extern  void        MR_trace_print_all_aliases(FILE *fp,
                         MR_bool mdb_command_format);
 
+/*
+** If the main command in *words[0] MR_trace_expand_aliases is an alias, then
+** expand the alias. Words, word_max and word_count should form a resizeable
+** array of words, in the sense of mercury_array_macros.h.
+*/
+
+extern  void        MR_trace_expand_aliases(char ***words, int *word_max,
+                        int *word_count);
+
 /* A Readline completer for aliases. */ 
 extern  MR_Completer_List
                     *MR_trace_alias_completer(const char *word,
                         size_t word_length);
+
 
 #endif  /* MERCURY_TRACE_ALIAS_H */
Index: trace/mercury_trace_browse.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_browse.c,v
retrieving revision 1.38
diff -u -b -r1.38 mercury_trace_browse.c
--- trace/mercury_trace_browse.c	31 Mar 2006 05:12:18 -0000	1.38
+++ trace/mercury_trace_browse.c	3 Apr 2006 08:59:46 -0000
@@ -45,9 +45,6 @@
 
 MR_Word             MR_trace_browser_persistent_state;
 
-static  MR_bool     MR_trace_is_portray_format(const char *str,
-                        MR_Browse_Format *format);
-
 MR_Word
 MR_type_value_to_browser_term(MR_TypeInfo type_info, MR_Word value)
 {
@@ -132,6 +129,28 @@
     );
 }
 
+MR_bool
+MR_trace_is_portray_format(const char *str, MR_Browse_Format *format)
+{
+    *format = MR_BROWSE_DEFAULT_FORMAT;
+
+    if (MR_streq(str, "flat")) {
+        *format = MR_BROWSE_FORMAT_FLAT;
+        return MR_TRUE;
+    } else if (MR_streq(str, "raw_pretty")) {
+        *format = MR_BROWSE_FORMAT_RAW_PRETTY;
+        return MR_TRUE;
+    } else if (MR_streq(str, "verbose")) {
+        *format = MR_BROWSE_FORMAT_VERBOSE;
+        return MR_TRUE;
+    } else if (MR_streq(str, "pretty")) {
+        *format = MR_BROWSE_FORMAT_PRETTY;
+        return MR_TRUE;
+    }
+
+    return MR_FALSE;
+}
+
 void
 MR_trace_browse(MR_Word type_info, MR_Word value, MR_Browse_Format format)
 {
@@ -283,119 +302,6 @@
                 (MR_Word) caller, MR_trace_browser_persistent_state);
         );
     }
-}
-
-MR_bool
-MR_trace_set_browser_param(MR_Word print, MR_Word browse, MR_Word print_all,
-    MR_Word flat, MR_Word raw_pretty, MR_Word verbose, 
-    MR_Word pretty, const char *param, const char *value)
-{
-    int                 depth;
-    int                 size;
-    int                 width;
-    int                 lines;
-    MR_Browse_Format    new_format;
-    MR_String           aligned_value;
-    char                *copied_value;
-
-    MR_trace_browse_ensure_init();
-
-    if (MR_streq(param, "format") &&
-        MR_trace_is_portray_format(value, &new_format))
-    {
-        MR_TRACE_CALL_MERCURY(
-            ML_BROWSE_set_format_from_mdb(print, browse,
-                print_all, new_format,
-                MR_trace_browser_persistent_state,
-                &MR_trace_browser_persistent_state);
-        );
-    } else if (MR_streq(param, "depth") &&
-        MR_trace_is_natural_number(value, &depth))
-    {
-        MR_TRACE_CALL_MERCURY(
-            ML_BROWSE_set_depth_from_mdb(print, browse, print_all,
-                flat, raw_pretty, verbose, pretty, depth,
-                MR_trace_browser_persistent_state,
-                &MR_trace_browser_persistent_state);
-        );
-    } else if (MR_streq(param, "size") &&
-        MR_trace_is_natural_number(value, &size))
-    {
-        MR_TRACE_CALL_MERCURY(
-            ML_BROWSE_set_size_from_mdb(print, browse, print_all,
-                flat, raw_pretty, verbose, pretty, size,
-                MR_trace_browser_persistent_state,
-                &MR_trace_browser_persistent_state);
-        );
-    } else if (MR_streq(param, "width") &&
-        MR_trace_is_natural_number(value, &width))
-    {
-        MR_TRACE_CALL_MERCURY(
-            ML_BROWSE_set_width_from_mdb(print, browse, print_all,
-                flat, raw_pretty, verbose, pretty, width,
-                MR_trace_browser_persistent_state,
-                &MR_trace_browser_persistent_state);
-        );
-    } else if (MR_streq(param, "lines") &&
-        MR_trace_is_natural_number(value, &lines))
-    {
-        MR_TRACE_CALL_MERCURY(
-            ML_BROWSE_set_lines_from_mdb(print, browse, print_all,
-                flat, raw_pretty, verbose, pretty, lines,
-                MR_trace_browser_persistent_state,
-                &MR_trace_browser_persistent_state);
-        );
-    } else if (MR_streq(param, "xml_browser_cmd")) {
-        copied_value = (char *) MR_GC_malloc(strlen(value) + 1);
-        strcpy(copied_value, value);
-        MR_TRACE_USE_HP(
-            MR_make_aligned_string(aligned_value, copied_value);
-        );
-        MR_TRACE_CALL_MERCURY(
-            ML_BROWSE_set_xml_browser_cmd_from_mdb(aligned_value, 
-                MR_trace_browser_persistent_state,
-                &MR_trace_browser_persistent_state);
-        );
-    } else if (MR_streq(param, "xml_tmp_filename")) {
-        copied_value = (char *) MR_GC_malloc(strlen(value) + 1);
-        strcpy(copied_value, value);
-        MR_TRACE_USE_HP(
-            MR_make_aligned_string(aligned_value, copied_value);
-        );
-        MR_TRACE_CALL_MERCURY(
-            ML_BROWSE_set_xml_tmp_filename_from_mdb(aligned_value, 
-                MR_trace_browser_persistent_state,
-                &MR_trace_browser_persistent_state);
-        );
-    } else {
-        return MR_FALSE;
-    }
-
-    MR_trace_browser_persistent_state =
-        MR_make_permanent(MR_trace_browser_persistent_state,
-            MR_trace_browser_persistent_state_type);
-    return MR_TRUE;
-}
-
-static MR_bool
-MR_trace_is_portray_format(const char *str, MR_Browse_Format *format)
-{
-    *format = MR_BROWSE_DEFAULT_FORMAT;
-
-    if (MR_streq(str, "flat")) {
-        *format = MR_BROWSE_FORMAT_FLAT;
-        return MR_TRUE;
-    } else if (MR_streq(str, "raw_pretty")) {
-        *format = MR_BROWSE_FORMAT_RAW_PRETTY;
-        return MR_TRUE;
-    } else if (MR_streq(str, "verbose")) {
-        *format = MR_BROWSE_FORMAT_VERBOSE;
-        return MR_TRUE;
-    } else if (MR_streq(str, "pretty")) {
-        *format = MR_BROWSE_FORMAT_PRETTY;
-        return MR_TRUE;
-    }
-    return MR_FALSE;
 }
 
 void
Index: trace/mercury_trace_browse.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_browse.h,v
retrieving revision 1.23
diff -u -b -r1.23 mercury_trace_browse.h
--- trace/mercury_trace_browse.h	31 Mar 2006 14:50:40 -0000	1.23
+++ trace/mercury_trace_browse.h	3 Apr 2006 09:02:51 -0000
@@ -1,4 +1,7 @@
 /*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
 ** Copyright (C) 1998-2002, 2004-2006 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.
@@ -19,7 +22,7 @@
 #include "mercury_std.h"	/* for MR_bool                     */
 #include "mercury_tags.h"	/* for MR_DEFINE_MERCURY_ENUM_CONST     */
 
-#include <stdio.h>	/* For FILE */
+#include <stdio.h>          /* for FILE */
 
 /*
 ** Convert a term (expressed either as a typeinfo/value pair or as a univ)
@@ -36,7 +39,8 @@
 ** Save the given browser term to the named file.
 */
 
-extern	void	MR_trace_save_term(const char *filename, MR_Word browser_term);
+extern  void        MR_trace_save_term(const char *filename,
+                        MR_Word browser_term);
 extern	void	MR_trace_save_term_xml(const char *filename, 
 			MR_Word browser_term);
 
@@ -63,9 +67,18 @@
 /*
 ** This value must be different from any of the MR_BROWSE_FORMAT_* values.
 */
+
 #define MR_BROWSE_DEFAULT_FORMAT	-1
 
 /*
+** If *str represents a value of type MR_Browse_Format, set *format to that
+** value.
+*/
+
+extern  MR_bool     MR_trace_is_portray_format(const char *str,
+                        MR_Browse_Format *format);
+
+/*
 ** Interactively browse a term.
 */
 
@@ -94,14 +107,6 @@
 			MR_Word is_func, MR_Browse_Caller_Type caller,
 			MR_Browse_Format format);
 
-/*
-** Set browser parameters.
-*/
-
-extern	MR_bool	MR_trace_set_browser_param(MR_Word print, MR_Word browse,
-			MR_Word print_all, MR_Word flat, MR_Word raw_pretty,
-			MR_Word verbose, MR_Word pretty, const char *param, 
-			const char *value);
 
 /*
 ** Print all the browser parameters. If mdb_command_format is true, print them
@@ -122,6 +127,7 @@
 ** that it is possible to cast to/from MR_Word in order to interface with
 ** Mercury code.
 */
+
 typedef enum { 
 	MR_DEFINE_MERCURY_ENUM_CONST(MR_NORMAL_QUERY), 
 	MR_DEFINE_MERCURY_ENUM_CONST(MR_CC_QUERY), 
@@ -132,21 +138,23 @@
 			int num_imports, /* const */ char *imports[]);
 
 #ifdef MR_USE_EXTERNAL_DEBUGGER
-extern	void	MR_trace_query_external(MR_Query_Type type, MR_String options,
-			int num_imports, MR_Word imports_list);
+extern  void        MR_trace_query_external(MR_Query_Type type,
+                        MR_String options, int num_imports,
+                        MR_Word imports_list);
 #endif
 
 /* 
 ** Points to the state of the interactive term browser that should persist
 ** between browsing sessions, like the format settings.
 */
+
 extern	MR_Word	MR_trace_browser_persistent_state;
 
 /*
 ** Initializes the interactive term browser persistent state or does nothing
 ** if it's already been initialized.
 */
-extern	void	MR_trace_browse_ensure_init(void);
 
+extern  void        MR_trace_browse_ensure_init(void);
 
 #endif	/* MERCURY_TRACE_BROWSE_H */
Index: trace/mercury_trace_cmd_backward.c
===================================================================
RCS file: trace/mercury_trace_cmd_backward.c
diff -N trace/mercury_trace_cmd_backward.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_backward.c	3 Apr 2006 12:48:17 -0000
@@ -0,0 +1,185 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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 module implements the mdb commands in the "backward" category.
+**
+** The structure of these files is:
+**
+** - all the #includes
+** - local macros and declarations of local static functions
+** - one function for each command in the category
+** - any auxiliary functions
+** - any command argument strings
+** - option processing functions.
+*/
+
+#include "mercury_std.h"
+#include "mercury_getopt.h"
+
+#include "mercury_trace.h"
+#include "mercury_trace_internal.h"
+#include "mercury_trace_cmds.h"
+#include "mercury_trace_cmd_backward.h"
+#include "mercury_trace_cmd_parameter.h"
+#include "mercury_trace_util.h"
+
+/****************************************************************************/
+
+/*
+** The message to print for retries through un-io-tabled areas, when
+** the MR_RETRY_IO_INTERACTIVE option is given.
+*/
+
+#define MR_UNTABLED_IO_RETRY_MESSAGE \
+    "Retry across I/O operations is not always safe.\n" \
+    "Are you sure you want to do it? "
+
+static  MR_bool     MR_trace_options_retry(MR_Retry_Across_Io *across_io,
+                        MR_bool *assume_all_io_is_tabled,
+                        char ***words, int *word_count);
+
+/****************************************************************************/
+
+MR_Next
+MR_trace_cmd_retry(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int                 n;
+    int                 ancestor_level;
+    MR_Retry_Across_Io  across_io;
+    const char          *problem;
+    MR_Retry_Result     result;
+    MR_bool             assume_all_io_is_tabled;
+    MR_bool             unsafe_retry;
+
+    ancestor_level = 0;
+    across_io = MR_RETRY_IO_INTERACTIVE;
+    assume_all_io_is_tabled = MR_FALSE;
+    if (! MR_trace_options_retry(&across_io, &assume_all_io_is_tabled,
+        &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+        ancestor_level = n;
+    } else if (word_count == 1) {
+        ancestor_level = 0;
+    } else {
+        MR_trace_usage_cur_cmd();
+        return KEEP_INTERACTING;
+    }
+
+    if (ancestor_level == 0 && MR_port_is_entry(event_info->MR_trace_port)) {
+        MR_trace_do_noop();
+        return KEEP_INTERACTING;
+    }
+
+    result = MR_trace_retry(event_info, ancestor_level,
+        across_io, assume_all_io_is_tabled, MR_UNTABLED_IO_RETRY_MESSAGE,
+        &unsafe_retry, &problem, MR_mdb_in, MR_mdb_out,
+        jumpaddr);
+    switch (result) {
+
+    case MR_RETRY_OK_DIRECT:
+        cmd->MR_trace_cmd = MR_CMD_GOTO;
+        cmd->MR_trace_stop_event = MR_trace_event_number + 1;
+        cmd->MR_trace_strict = MR_FALSE;
+        cmd->MR_trace_print_level = MR_default_print_level;
+        return STOP_INTERACTING;
+
+    case MR_RETRY_OK_FINISH_FIRST:
+        cmd->MR_trace_cmd = MR_CMD_FINISH;
+        cmd->MR_trace_stop_depth = event_info->MR_call_depth - ancestor_level;
+        cmd->MR_trace_strict = MR_TRUE;
+        cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE;
+
+        /* Arrange to retry the call once it is finished. */
+        /* XXX we should use the same options as the original retry */
+        MR_insert_line_at_head("retry -o");
+        return STOP_INTERACTING;
+
+    case MR_RETRY_OK_FAIL_FIRST:
+        cmd->MR_trace_cmd = MR_CMD_FAIL;
+        cmd->MR_trace_stop_depth = event_info->MR_call_depth - ancestor_level;
+        cmd->MR_trace_strict = MR_TRUE;
+        cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE;
+
+        /* Arrange to retry the call once it is finished. */
+        /* XXX we should use the same options as the original retry */
+        MR_insert_line_at_head("retry -o");
+        return STOP_INTERACTING;
+
+    case MR_RETRY_ERROR:
+        fflush(MR_mdb_out);
+        fprintf(MR_mdb_err, "%s\n", problem);
+        return KEEP_INTERACTING;
+    }
+
+    MR_fatal_error("unrecognized retry result");
+}
+
+/****************************************************************************/
+
+/*
+** "retry --assume-all-io-is-tabled" is deliberately not documented as
+** it is for developers only.
+*/
+
+const char *const    MR_trace_retry_cmd_args[] =
+    { "--force", "--interactive", "--only-if-safe", NULL };
+
+/****************************************************************************/
+
+static struct MR_option MR_trace_retry_opts[] =
+{
+    { "assume-all-io-is-tabled",    MR_no_argument, NULL,   'a' },
+    { "force",                      MR_no_argument, NULL,   'f' },
+    { "interactive",                MR_no_argument, NULL,   'i' },
+    { "only-if-safe",               MR_no_argument, NULL,   'o' },
+    { NULL,                         MR_no_argument, NULL,   0 }
+};
+
+static MR_bool
+MR_trace_options_retry(MR_Retry_Across_Io *across_io,
+    MR_bool *assume_all_io_is_tabled, char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "afio",
+        MR_trace_retry_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'a':
+                *assume_all_io_is_tabled = MR_TRUE;
+                break;
+
+            case 'f':
+                *across_io = MR_RETRY_IO_FORCE;
+                break;
+
+            case 'i':
+                *across_io = MR_RETRY_IO_INTERACTIVE;
+                break;
+
+            case 'o':
+                *across_io = MR_RETRY_IO_ONLY_IF_SAFE;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
Index: trace/mercury_trace_cmd_backward.h
===================================================================
RCS file: trace/mercury_trace_cmd_backward.h
diff -N trace/mercury_trace_cmd_backward.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_backward.h	3 Apr 2006 10:36:53 -0000
@@ -0,0 +1,16 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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.
+*/
+
+#include "mercury_imp.h"
+
+#include "mercury_trace_cmds.h"
+
+extern  MR_TraceCmdFunc     MR_trace_cmd_retry;
+
+extern  const char *const   MR_trace_retry_cmd_args[];
Index: trace/mercury_trace_cmd_breakpoint.c
===================================================================
RCS file: trace/mercury_trace_cmd_breakpoint.c
diff -N trace/mercury_trace_cmd_breakpoint.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_breakpoint.c	3 Apr 2006 12:50:17 -0000
@@ -0,0 +1,1043 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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 module implements the mdb commands in the "breakpoint" category.
+**
+** The structure of these files is:
+**
+** - all the #includes
+** - local macros and declarations of local static functions
+** - one function for each command in the category
+** - any auxiliary functions
+** - any command argument strings
+** - option processing functions.
+*/
+
+#include "mercury_std.h"
+#include "mercury_getopt.h"
+
+#include "mercury_trace_internal.h"
+#include "mercury_trace_cmds.h"
+#include "mercury_trace_cmd_breakpoint.h"
+#include "mercury_trace_cmd_parameter.h"
+#include "mercury_trace_spy.h"
+#include "mercury_trace_tables.h"
+#include "mercury_trace_util.h"
+
+/****************************************************************************/
+
+typedef enum {
+        MR_MULTIMATCH_ASK, MR_MULTIMATCH_ALL, MR_MULTIMATCH_ONE
+} MR_MultiMatch;
+
+static  MR_Spy_Print_List
+                    MR_add_to_print_list_end(MR_Browse_Format format,
+                        char *word, MR_bool warn, 
+                        MR_Spy_Print_List print_list);
+static  void        MR_maybe_print_spy_point(int slot, const char *problem);
+static  MR_bool     MR_parse_source_locn(char *word, const char **file,
+                        int *line);
+
+static  MR_bool     MR_trace_options_when_action_multi_ignore(MR_Spy_When *when,
+                        MR_Spy_Action *action, MR_MultiMatch *multi_match,
+                        MR_Spy_Ignore_When *ignore_when, int *ignore_count,
+                        MR_Spy_Print_List *print_list,
+                        char ***words, int *word_count);
+static  MR_bool     MR_trace_options_condition(int *break_num,
+                        MR_bool *require_var, MR_bool *require_path,
+                        char ***words, int *word_count);
+static  MR_bool     MR_trace_options_ignore_count(
+                        MR_Spy_Ignore_When *ignore_when,
+                        int *ignore_count, char ***words, int *word_count);
+static  MR_bool     MR_trace_options_break_print(MR_Browse_Format *format,
+                        MR_bool *at_start, MR_bool *warn, char ***words,
+                        int *word_count);
+static  MR_bool     MR_trace_options_register(MR_bool *verbose, char ***words,
+                        int *word_count);
+
+/****************************************************************************/
+
+MR_Next
+MR_trace_cmd_break(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    const MR_Label_Layout   *layout;
+    MR_Proc_Spec            spec;
+    MR_Spy_When             when;
+    MR_Spy_Action           action;
+    MR_MultiMatch           multi_match;
+    MR_Spy_Ignore_When      ignore_when;
+    int                     ignore_count;
+    MR_Spy_Print_List       print_list;
+    const char              *file;
+    int                     line;
+    int                     breakline;
+    const char              *problem;
+
+    layout = event_info->MR_event_sll;
+
+    if (word_count == 2 && MR_streq(words[1], "info")) {
+        int i;
+        int count;
+
+        count = 0;
+        for (i = 0; i < MR_spy_point_next; i++) {
+            if (MR_spy_points[i]->spy_exists) {
+                MR_print_spy_point(MR_mdb_out, i, MR_TRUE);
+                count++;
+            }
+        }
+
+        if (count == 0) {
+            fprintf(MR_mdb_out, "There are no break points.\n");
+        }
+
+        return KEEP_INTERACTING;
+    }
+
+    when = MR_default_breakpoint_scope;
+    action = MR_SPY_STOP;
+    multi_match = MR_MULTIMATCH_ASK;
+    /*
+    ** The value of ignore_when doesn't matter
+    ** while ignore_count contains zero.
+    */
+    ignore_when = MR_SPY_DONT_IGNORE;
+    ignore_count = 0;
+    print_list = NULL;
+    if (! MR_trace_options_when_action_multi_ignore(&when, &action,
+        &multi_match, &ignore_when, &ignore_count, &print_list,
+        &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 2 && MR_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, MR_TRUE);
+        slot = MR_add_proc_spy_point(MR_SPY_SPECIFIC, action, ignore_when,
+            ignore_count, layout->MR_sll_entry, layout, print_list, &problem);
+        MR_maybe_print_spy_point(slot, problem);
+    } else if (word_count == 2 && MR_parse_proc_spec(words[1], &spec)) {
+        MR_Matches_Info matches;
+        int             slot;
+
+        MR_register_all_modules_and_procs(MR_mdb_out, MR_TRUE);
+        matches = MR_search_for_matching_procedures(&spec);
+        if (matches.match_proc_next == 0) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: there is no such procedure.\n");
+        } else if (matches.match_proc_next == 1) {
+            slot = MR_add_proc_spy_point(when, action, ignore_when,
+                ignore_count, matches.match_procs[0], NULL, print_list,
+                &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, ignore_when,
+                    ignore_count, matches.match_procs[i], NULL, print_list,
+                    &problem);
+                MR_maybe_print_spy_point(slot, problem);
+            }
+        } else {
+            char    buf[80];
+            int     i;
+            char    *line2;
+
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err,
+                "Ambiguous procedure specification. The matches are:\n");
+
+            for (i = 0; i < matches.match_proc_next; i++) {
+                fprintf(MR_mdb_out, "%d: ", i);
+                MR_print_proc_id_and_nl(MR_mdb_out, matches.match_procs[i]);
+            }
+
+            if (multi_match == MR_MULTIMATCH_ONE) {
+                return KEEP_INTERACTING;
+            }
+
+            sprintf(buf, "\nWhich do you want to put "
+                "a breakpoint on (0-%d or *)? ",
+                matches.match_proc_next - 1);
+            line2 = MR_trace_getline(buf, MR_mdb_in, MR_mdb_out);
+            if (line2 == NULL) {
+                /* This means the user input EOF. */
+                fprintf(MR_mdb_out, "none of them\n");
+            } else if (MR_streq(line2, "*")) {
+                for (i = 0; i < matches.match_proc_next; i++) {
+                    slot = MR_add_proc_spy_point(when, action, ignore_when,
+                        ignore_count, matches.match_procs[i], NULL, print_list,
+                        &problem);
+                    MR_maybe_print_spy_point(slot, problem);
+                }
+
+                MR_free(line2);
+            } else if (MR_trace_is_natural_number(line2, &i)) {
+                if (0 <= i && i < matches.match_proc_next) {
+                    slot = MR_add_proc_spy_point(when, action, ignore_when,
+                        ignore_count, matches.match_procs[i], NULL, print_list,
+                        &problem);
+                    MR_maybe_print_spy_point(slot, problem);
+                } else {
+                    fprintf(MR_mdb_out, "no such match\n");
+                }
+                MR_free(line2);
+            } else {
+                fprintf(MR_mdb_out, "none of them\n");
+                MR_free(line2);
+            }
+        }
+    } else if (word_count == 2 &&
+        MR_parse_source_locn(words[1], &file, &line))
+    {
+        int slot;
+
+        slot = MR_add_line_spy_point(action, ignore_when, ignore_count, file,
+            line, print_list, &problem);
+        MR_maybe_print_spy_point(slot, problem);
+    } else if (word_count == 2 &&
+        MR_trace_is_natural_number(words[1], &breakline))
+    {
+        int slot;
+
+        if (MR_find_context(layout, &file, &line)) {
+            slot = MR_add_line_spy_point(action, ignore_when, ignore_count,
+                file, breakline, print_list, &problem);
+            MR_maybe_print_spy_point(slot, problem);
+        } else {
+            MR_fatal_error("cannot find current filename");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_condition(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, 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))
+    {
+        /* the usage message has already been printed */
+        return KEEP_INTERACTING;
+    } else if (word_count < 4) {
+        MR_trace_usage_cur_cmd();
+        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], "!=") || 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;
+}
+
+MR_Next
+MR_trace_cmd_ignore(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    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))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 2 && MR_trace_is_natural_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 && MR_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, "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 {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: there is no most recent break point.\n");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_break_print(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int                 n;
+    int                 i;
+    MR_Browse_Format    format;
+    MR_bool             at_start;
+    MR_bool             warn;
+    MR_Spy_Print_List   print_list;
+
+    if (! MR_trace_options_break_print(&format, &at_start, &warn,
+        &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count > 2 && MR_trace_is_natural_number(words[1], &n)) {
+        if (word_count == 3 && MR_streq(words[2], "none")) {
+            MR_clear_spy_point_print_list(n);
+            MR_print_spy_point(MR_mdb_out, n, MR_TRUE);
+        } else if (0 <= n && n < MR_spy_point_next
+            && MR_spy_points[n]->spy_exists)
+        {
+            print_list = NULL;
+            for (i = 2; i < word_count; i++) {
+                print_list = MR_add_to_print_list_end(format, words[i], warn,
+                    print_list);
+            }
+
+            if (at_start) {
+                MR_add_spy_point_print_list_start(n, print_list);
+            } else {
+                MR_add_spy_point_print_list_end(n, print_list);
+            }
+
+            MR_print_spy_point(MR_mdb_out, n, MR_TRUE);
+        } else {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: break point #%d does not exist.\n", n);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_enable(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int n;
+
+    if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+        if (0 <= n && n < MR_spy_point_next && MR_spy_points[n]->spy_exists) {
+            MR_spy_points[n]->spy_enabled = MR_TRUE;
+            MR_print_spy_point(MR_mdb_out, n, MR_FALSE);
+        } else {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: break point #%d does not exist.\n", n);
+        }
+    } else if (word_count == 2 && MR_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) {
+                MR_spy_points[i]->spy_enabled = MR_TRUE;
+                MR_print_spy_point(MR_mdb_out, i, MR_FALSE);
+                count++;
+            }
+        }
+
+        if (count == 0) {
+            fprintf(MR_mdb_err, "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)
+        {
+            MR_spy_points[MR_most_recent_spy_point]->spy_enabled = MR_TRUE;
+            MR_print_spy_point(MR_mdb_out, MR_most_recent_spy_point, MR_FALSE);
+        } else {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: there is no most recent break point.\n");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_disable(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int n;
+
+    if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+        if (0 <= n && n < MR_spy_point_next && MR_spy_points[n]->spy_exists) {
+            MR_spy_points[n]->spy_enabled = MR_FALSE;
+            MR_print_spy_point(MR_mdb_out, n, MR_FALSE);
+        } else {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: break point #%d does not exist.\n", n);
+        }
+    } else if (word_count == 2 && MR_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) {
+                MR_spy_points[i]->spy_enabled = MR_FALSE;
+                MR_print_spy_point(MR_mdb_out, i, MR_FALSE);
+                count++;
+            }
+        }
+
+        if (count == 0) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "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)
+        {
+            MR_spy_points[MR_most_recent_spy_point]->spy_enabled = MR_FALSE;
+            MR_print_spy_point(MR_mdb_out, MR_most_recent_spy_point, MR_FALSE);
+        } else {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "There is no most recent break point.\n");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_delete(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int n;
+
+    if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+        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);
+            fprintf(MR_mdb_err, "mdb: break point #%d does not exist.\n", n);
+        }
+    } else if (word_count == 2 && MR_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) {
+                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++;
+            }
+        }
+
+        if (count == 0) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "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)
+        {
+            int slot;
+
+            slot = MR_most_recent_spy_point;
+            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);
+            fprintf(MR_mdb_err, "mdb: there is no most recent break point.\n");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_register(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_bool verbose;
+
+    verbose = MR_TRUE;
+
+    if (! MR_trace_options_register(&verbose, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 1) {
+        MR_register_all_modules_and_procs(MR_mdb_out, verbose);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_modules(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 1) {
+        MR_register_all_modules_and_procs(MR_mdb_out, MR_TRUE);
+        MR_dump_module_list(MR_mdb_out);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_procedures(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 2) {
+        MR_register_all_modules_and_procs(MR_mdb_out, MR_TRUE);
+        MR_dump_module_procs(MR_mdb_out, words[1]);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+/****************************************************************************/
+
+static MR_Spy_Print_List
+MR_add_to_print_list_end(MR_Browse_Format format, char *word, MR_bool warn,
+    MR_Spy_Print_List print_list)
+{
+    MR_Spy_Print_List   list;
+    MR_Spy_Print_List   new_list;
+    MR_Spy_Print        new_node;
+
+    new_node = MR_malloc(sizeof(struct MR_Spy_Print_Struct));
+    new_node->p_format = format;
+    new_node->p_warn = warn;
+    if (MR_streq(word, "*")) {
+        new_node->p_what = MR_SPY_PRINT_ALL;
+        new_node->p_name = NULL;
+    } else if (MR_streq(word, "goal")) {
+        new_node->p_what = MR_SPY_PRINT_GOAL;
+        new_node->p_name = NULL;
+    } else {
+        new_node->p_what = MR_SPY_PRINT_ONE;
+        new_node->p_name = MR_copy_string(word);
+    }
+
+    new_list = MR_malloc(sizeof(struct MR_Spy_Print_List_Struct));
+    new_list->pl_cur = new_node;
+    new_list->pl_next = NULL;
+
+    list = print_list;
+    if (list == NULL) {
+        return new_list;
+    }
+
+    while (list->pl_next != NULL) {
+        list = list->pl_next;
+    }
+
+    list->pl_next = new_list;
+    return print_list;
+}
+
+static 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, MR_TRUE);
+    }
+}
+
+static MR_bool
+MR_parse_source_locn(char *word, const char **file, int *line)
+{
+    char        *s;
+    const char  *t;
+
+    if ((s = strrchr(word, ':')) != NULL) {
+        for (t = s+1; *t != '\0'; t++) {
+            if (! MR_isdigit(*t)) {
+                return MR_FALSE;
+            }
+        }
+
+        *s = '\0';
+        *file = word;
+        *line = atoi(s+1);
+        return MR_TRUE;
+    }
+
+    return MR_FALSE;
+}
+
+/****************************************************************************/
+
+const char *const    MR_trace_break_cmd_args[] =
+    { "-A", "-E", "-I", "-O", "-P", "-S", "-a", "-e", "-i",
+    "--all", "--entry", "--ignore-entry", "--ignore-interface",
+    "--interface", "--print", "--select-all", "--select-one",
+    "--stop", "here", "info", NULL };
+
+const char *const    MR_trace_ignore_cmd_args[] =
+    { "-E", "-I", "--ignore-entry", "--ignore-interface", NULL };
+
+/****************************************************************************/
+
+static struct MR_option MR_trace_when_action_multi_ignore_opts[] =
+{
+    { "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-list",         MR_required_argument,   NULL,   'p' },
+    { "no-warn",            MR_no_argument,         NULL,   'n' },
+    { "print",              MR_no_argument,         NULL,   'P' },
+    { "stop",               MR_no_argument,         NULL,   'S' },
+    { "select-all",         MR_no_argument,         NULL,   'A' },
+    { "select-one",         MR_no_argument,         NULL,   'O' },
+    { NULL,                 MR_no_argument,         NULL,   0 }
+};
+
+static MR_bool
+MR_trace_options_when_action_multi_ignore(MR_Spy_When *when,
+    MR_Spy_Action *action, MR_MultiMatch *multi_match,
+    MR_Spy_Ignore_When*ignore_when, int *ignore_count,
+    MR_Spy_Print_List *print_list,
+    char ***words, int *word_count)
+{
+    int                 c;
+    MR_Spy_Print        node;
+    MR_Spy_Print_List   list;
+    MR_bool             warn;
+
+    warn = MR_TRUE;
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "AE:I:OPSaeinp:",
+        MR_trace_when_action_multi_ignore_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'a':
+                *when = MR_SPY_ALL;
+                break;
+
+            case 'e':
+                *when = MR_SPY_ENTRY;
+                break;
+
+            case 'i':
+                *when = MR_SPY_INTERFACE;
+                break;
+
+            case 'n':
+                warn = MR_FALSE;
+                break;
+
+            case 'p':
+                *print_list = MR_add_to_print_list_end(MR_BROWSE_FORMAT_FLAT,
+                    MR_optarg, warn, *print_list);
+                break;
+
+            case 'E':
+                if (! MR_trace_is_natural_number(MR_optarg, ignore_count)) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+                *ignore_when = MR_SPY_IGNORE_ENTRY;
+                break;
+
+            case 'I':
+                if (! MR_trace_is_natural_number(MR_optarg, ignore_count)) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+                *ignore_when = MR_SPY_IGNORE_INTERFACE;
+                break;
+
+            case 'A':
+                *multi_match = MR_MULTIMATCH_ALL;
+                break;
+
+            case 'O':
+                *multi_match = MR_MULTIMATCH_ONE;
+                break;
+
+            case 'P':
+                *action = MR_SPY_PRINT;
+                break;
+
+            case 'S':
+                *action = MR_SPY_STOP;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    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)
+{
+    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_cur_cmd();
+                    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_cur_cmd();
+                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' },
+    { "ignore-interface",   MR_required_argument,   NULL,   'I' },
+    { NULL,                 MR_no_argument,         NULL,   0 }
+};
+
+static MR_bool
+MR_trace_options_ignore_count(MR_Spy_Ignore_When *ignore_when,
+    int *ignore_count, char ***words, int *word_count)
+{
+    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 (! MR_trace_is_natural_number(MR_optarg, ignore_count)) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+                *ignore_when = MR_SPY_IGNORE_ENTRY;
+                break;
+
+            case 'I':
+                if (! MR_trace_is_natural_number(MR_optarg, ignore_count)) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+                *ignore_when = MR_SPY_IGNORE_INTERFACE;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+static struct MR_option MR_trace_break_print_opts[] =
+{
+    { "end",        MR_no_argument, NULL,   'e' },
+    { "no-warn",    MR_no_argument, NULL,   'n' },
+    { "flat",       MR_no_argument, NULL,   'f' },
+    { "raw-pretty", MR_no_argument, NULL,   'r' },
+    { "verbose",    MR_no_argument, NULL,   'v' },
+    { "pretty",     MR_no_argument, NULL,   'p' },
+    { NULL,         MR_no_argument, NULL,   0 }
+};
+
+static MR_bool
+MR_trace_options_break_print(MR_Browse_Format *format, MR_bool *at_start,
+    MR_bool *warn, char ***words, int *word_count)
+{
+    int c;
+
+    *format = MR_BROWSE_FORMAT_FLAT;
+    *at_start = MR_TRUE;
+    *warn = MR_TRUE;
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "enfrvp",
+        MR_trace_break_print_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'e':
+                *at_start = MR_FALSE;
+                break;
+
+            case 'n':
+                *warn = MR_FALSE;
+                break;
+
+            case 'f':
+                *format = MR_BROWSE_FORMAT_FLAT;
+                break;
+
+            case 'r':
+                *format = MR_BROWSE_FORMAT_RAW_PRETTY;
+                break;
+
+            case 'v':
+                *format = MR_BROWSE_FORMAT_VERBOSE;
+                break;
+
+            case 'p':
+                *format = MR_BROWSE_FORMAT_PRETTY;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+static struct MR_option MR_trace_register_opts[] =
+{
+    { "quiet",      MR_no_argument, NULL,   'q' },
+    { "verbose",    MR_no_argument, NULL,   'v' },
+    { NULL,         MR_no_argument, NULL,   0 }
+};
+
+static MR_bool
+MR_trace_options_register(MR_bool *verbose, char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "qv",
+        MR_trace_register_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'q':
+                *verbose = MR_FALSE;
+                break;
+
+            case 'v':
+                *verbose = MR_TRUE;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
Index: trace/mercury_trace_cmd_breakpoint.h
===================================================================
RCS file: trace/mercury_trace_cmd_breakpoint.h
diff -N trace/mercury_trace_cmd_breakpoint.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_breakpoint.h	3 Apr 2006 11:46:21 -0000
@@ -0,0 +1,26 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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.
+*/
+
+#include "mercury_imp.h"
+
+#include "mercury_trace_cmds.h"
+
+extern  MR_TraceCmdFunc     MR_trace_cmd_break;
+extern  MR_TraceCmdFunc     MR_trace_cmd_condition;
+extern  MR_TraceCmdFunc     MR_trace_cmd_ignore;
+extern  MR_TraceCmdFunc     MR_trace_cmd_break_print;
+extern  MR_TraceCmdFunc     MR_trace_cmd_enable;
+extern  MR_TraceCmdFunc     MR_trace_cmd_disable;
+extern  MR_TraceCmdFunc     MR_trace_cmd_delete;
+extern  MR_TraceCmdFunc     MR_trace_cmd_register;
+extern  MR_TraceCmdFunc     MR_trace_cmd_modules;
+extern  MR_TraceCmdFunc     MR_trace_cmd_procedures;
+
+extern  const char *const   MR_trace_break_cmd_args[];
+extern  const char *const   MR_trace_ignore_cmd_args[];
Index: trace/mercury_trace_cmd_browsing.c
===================================================================
RCS file: trace/mercury_trace_cmd_browsing.c
diff -N trace/mercury_trace_cmd_browsing.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_browsing.c	3 Apr 2006 12:50:24 -0000
@@ -0,0 +1,1278 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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 module implements the mdb commands in the "browsing" category.
+**
+** The structure of these files is:
+**
+** - all the #includes
+** - local macros and declarations of local static functions
+** - one function for each command in the category
+** - any auxiliary functions
+** - any command argument strings
+** - option processing functions.
+*/
+
+#include "mercury_std.h"
+#include "mercury_getopt.h"
+
+#include "mercury_trace_internal.h"
+#include "mercury_trace_cmds.h"
+#include "mercury_trace_cmd_browsing.h"
+#include "mercury_trace_cmd_parameter.h"
+#include "mercury_trace_vars.h"
+#include "mercury_trace_hold_vars.h"
+#include "mercury_trace_browse.h"
+#include "mercury_trace_util.h"
+
+#include "mdb.listing.mh"
+#include "mdb.diff.mh"
+#include "mdb.declarative_execution.mh"
+#include "mdbcomp.program_representation.mh"
+
+/****************************************************************************/
+
+static  void        MR_trace_set_level_and_report(int ancestor_level,
+                        MR_bool detailed, MR_bool print_optionals);
+static  const char  *MR_trace_browse_exception(MR_Event_Info *event_info,
+                        MR_Browser browser, MR_Browse_Caller_Type caller,
+                        MR_Browse_Format format);
+static  const char  *MR_trace_browse_proc_body(MR_Event_Info *event_info,
+                        MR_Browser browser, MR_Browse_Caller_Type caller,
+                        MR_Browse_Format format);
+                        
+/* Functions to invoke the user's XML browser on terms or goals */
+static  void        MR_trace_browse_xml(MR_Word type_info, MR_Word value,
+                        MR_Browse_Caller_Type caller, MR_Browse_Format format);
+static  void        MR_trace_browse_goal_xml(MR_ConstString name,
+                        MR_Word arg_list, MR_Word is_func,
+                        MR_Browse_Caller_Type caller, MR_Browse_Format format);
+
+static  void        MR_trace_cmd_stack_2(MR_Event_Info *event_info,
+                        MR_bool detailed, int frame_limit, int line_limit);
+
+static  const char  *MR_trace_new_source_window(const char *window_cmd,
+                        const char *server_cmd, const char *server_name,
+                        int timeout, MR_bool force, MR_bool verbose,
+                        MR_bool split);
+
+static  MR_bool     MR_trace_options_detailed(MR_bool *detailed, char ***words,
+                        int *word_count);
+static  MR_bool     MR_trace_options_stack_trace(MR_bool *detailed,
+                        int *frame_limit, char ***words, int *word_count);
+static  MR_bool     MR_trace_options_format(MR_Browse_Format *format,
+                        MR_bool *xml, char ***words, int *word_count);
+static  MR_bool     MR_trace_options_view(const char **window_cmd,
+                        const char **server_cmd, const char **server_name,
+                        int *timeout, MR_bool *force, MR_bool *verbose,
+                        MR_bool *split, MR_bool *close_window, char ***words,
+                        int *word_count);
+static  MR_bool     MR_trace_options_diff(int *start, int *max,
+                        char ***words, int *word_count);
+static  MR_bool     MR_trace_options_dump(MR_bool *xml,
+                        char ***words, int *word_count);
+
+/****************************************************************************/
+
+MR_Next
+MR_trace_cmd_level(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int n;
+    MR_bool detailed;
+
+    detailed = MR_FALSE;
+    if (! MR_trace_options_detailed(&detailed, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+        MR_trace_set_level_and_report(n, detailed, MR_print_optionals);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_up(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int     n;
+    MR_bool detailed;
+
+    detailed = MR_FALSE;
+    if (! MR_trace_options_detailed(&detailed, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+        MR_trace_set_level_and_report(MR_trace_current_level() + n, detailed,
+            MR_print_optionals);
+    } else if (word_count == 1) {
+        MR_trace_set_level_and_report(MR_trace_current_level() + 1, detailed,
+            MR_print_optionals);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_down(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int     n;
+    MR_bool detailed;
+
+    detailed = MR_FALSE;
+    if (! MR_trace_options_detailed(&detailed, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+        MR_trace_set_level_and_report(MR_trace_current_level() - n, detailed,
+            MR_print_optionals);
+    } else if (word_count == 1) {
+        MR_trace_set_level_and_report(MR_trace_current_level() - 1, detailed,
+            MR_print_optionals);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_vars(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 1) {
+        const char  *problem;
+
+        problem = MR_trace_list_vars(MR_mdb_out);
+        if (problem != NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_held_vars(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 1) {
+        MR_trace_list_held_vars(MR_mdb_out);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_print(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_Browse_Format    format;
+    MR_bool             xml;
+    int             n;
+
+    if (! MR_trace_options_format(&format, &xml, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (xml) {
+        /* the --xml option is not valid for print */
+        MR_trace_usage_cur_cmd();
+    } else if (word_count == 1) {
+        const char  *problem;
+
+        problem = MR_trace_browse_one_goal(MR_mdb_out,
+            MR_trace_browse_goal_internal,
+            MR_BROWSE_CALLER_PRINT, format);
+
+        if (problem != NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+        }
+    } else if (word_count == 2) {
+        const char  *problem;
+
+        if (MR_streq(words[1], "*")) {
+            problem = MR_trace_browse_all(MR_mdb_out,
+                MR_trace_browse_internal, format);
+        } else if (MR_streq(words[1], "goal")) {
+            problem = MR_trace_browse_one_goal(MR_mdb_out,
+                MR_trace_browse_goal_internal, MR_BROWSE_CALLER_PRINT, format);
+        } else if (MR_streq(words[1], "exception")) {
+            problem = MR_trace_browse_exception(event_info,
+                MR_trace_browse_internal, MR_BROWSE_CALLER_PRINT, format);
+        } else if (MR_streq(words[1], "proc_body")) {
+            problem = MR_trace_browse_proc_body(event_info,
+                MR_trace_browse_internal, MR_BROWSE_CALLER_PRINT, format);
+        } else {
+            problem = MR_trace_parse_browse_one(MR_mdb_out, MR_TRUE, words[1],
+                MR_trace_browse_internal, MR_BROWSE_CALLER_PRINT, format,
+                MR_FALSE);
+        }
+
+        if (problem != NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+        }
+    } else if (word_count == 3 && MR_streq(words[1], "action")
+        && MR_trace_is_natural_number(words[2], &n))
+    {
+        const char  *problem;
+
+        problem = MR_trace_browse_action(MR_mdb_out, n,
+            MR_trace_browse_goal_internal,
+            MR_BROWSE_CALLER_PRINT, format);
+
+        if (problem != NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_browse(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_Browse_Format    format;
+    MR_bool             xml;
+    int                 n;
+    MR_GoalBrowser      goal_browser;
+    MR_Browser          browser;
+
+    if (! MR_trace_options_format(&format, &xml, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else {
+        if (xml) {
+            goal_browser = MR_trace_browse_goal_xml;
+            browser = MR_trace_browse_xml;
+        } else {
+            goal_browser = MR_trace_browse_goal_internal;
+            browser = MR_trace_browse_internal;
+        }
+
+        if (word_count == 1) {
+            const char  *problem;
+
+            problem = MR_trace_browse_one_goal(MR_mdb_out, goal_browser,
+                MR_BROWSE_CALLER_BROWSE, format);
+
+            if (problem != NULL) {
+                fflush(MR_mdb_out);
+                fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+            }
+        } else if (word_count == 2) {
+            const char  *problem;
+
+            if (MR_streq(words[1], "goal")) {
+                problem = MR_trace_browse_one_goal(MR_mdb_out, goal_browser,
+                    MR_BROWSE_CALLER_BROWSE, format);
+            } else if (MR_streq(words[1], "exception")) {
+                problem = MR_trace_browse_exception(event_info, browser,
+                    MR_BROWSE_CALLER_BROWSE, format);
+            } else if (MR_streq(words[1], "proc_body")) {
+                problem = MR_trace_browse_proc_body(event_info, browser,
+                    MR_BROWSE_CALLER_BROWSE, format);
+            } else {
+                problem = MR_trace_parse_browse_one(MR_mdb_out, MR_FALSE,
+                    words[1], browser, MR_BROWSE_CALLER_BROWSE, format,
+                    MR_TRUE);
+            }
+
+            if (problem != NULL) {
+                fflush(MR_mdb_out);
+                fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+            }
+        } else if (word_count == 3 && MR_streq(words[1], "action")
+            && MR_trace_is_natural_number(words[2], &n))
+        {
+            const char  *problem;
+
+            problem = MR_trace_browse_action(MR_mdb_out, n, goal_browser,
+                MR_BROWSE_CALLER_BROWSE, format);
+
+            if (problem != NULL) {
+                fflush(MR_mdb_out);
+                fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+            }
+        } else {
+            MR_trace_usage_cur_cmd();
+        }
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_bool     detailed;
+    int         frame_limit = 0;
+    int         line_limit = MR_stack_default_line_limit;
+    int         spec_line_limit;
+
+    detailed = MR_FALSE;
+    if (! MR_trace_options_stack_trace(&detailed, &frame_limit,
+        &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 1) {
+        MR_trace_cmd_stack_2(event_info, detailed, frame_limit, line_limit);
+    } else if (word_count == 2 &&
+        MR_trace_is_natural_number(words[1], &spec_line_limit))
+    {
+        MR_trace_cmd_stack_2(event_info, detailed, frame_limit,
+            spec_line_limit);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_current(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 1) {
+        MR_trace_event_print_internal_report(event_info);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_view(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    const char      *window_cmd = NULL;
+    const char      *server_cmd = NULL;
+    const char      *server_name = NULL;
+    int             timeout = 8;    /* seconds */
+    MR_bool         force = MR_FALSE;
+    MR_bool         verbose = MR_FALSE;
+    MR_bool         split = MR_FALSE;
+    MR_bool         close_window = MR_FALSE;
+    const char      *msg;
+
+    if (! MR_trace_options_view(&window_cmd, &server_cmd, &server_name,
+        &timeout, &force, &verbose, &split, &close_window,
+        &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count != 1) {
+        MR_trace_usage_cur_cmd();
+    } else if (close_window) {
+        MR_trace_maybe_close_source_window(verbose);
+    } else {
+        msg = MR_trace_new_source_window(window_cmd, server_cmd, server_name,
+            timeout, force, verbose, split);
+        if (msg != NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: %s.\n", msg);
+        }
+
+        MR_trace_maybe_sync_source_window(event_info, verbose);
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_hold(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    char        *event_var_name;
+    char        *held_var_name;
+    MR_TypeInfo type_info;
+    MR_Word     value;
+    const char  *ignored_name;
+    const char  *problem;
+    MR_bool     bad_subterm;
+
+    if (word_count == 2) {
+        event_var_name = words[1];
+        held_var_name = words[1];
+    } else if (word_count == 3) {
+        event_var_name = words[1];
+        held_var_name = words[2];
+    } else {
+        MR_trace_usage_cur_cmd();
+        return KEEP_INTERACTING;
+    }
+
+    if (strpbrk(held_var_name, "^/") != NULL) {
+        /* Don't allow path separators in variable names. */
+        MR_trace_usage_cur_cmd();
+        return KEEP_INTERACTING;
+    }
+
+    if (held_var_name[0] == '$') {
+        /* Ignore any unneeded initial $ signs. */
+        held_var_name = &held_var_name[1];
+    }
+
+    problem = MR_trace_parse_lookup_var_path(event_var_name, &type_info,
+        &value, &bad_subterm);
+    if (problem != NULL) {
+        fflush(MR_mdb_out);
+        fprintf(MR_mdb_err, "mdb: %s%s.\n",
+            (bad_subterm? "there is no path " : ""), problem);
+        return KEEP_INTERACTING;
+    }
+
+    if (! MR_add_hold_var(held_var_name, type_info, value)) {
+        fflush(MR_mdb_out);
+        fprintf(MR_mdb_err, "mdb: there is already a held variable $%s\n",
+            held_var_name);
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_diff(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int         start;
+    int         max;
+    char        *name1;
+    char        *name2;
+    MR_TypeInfo type_info1;
+    MR_TypeInfo type_info2;
+    MR_Word     value1;
+    MR_Word     value2;
+    MR_Word     univ1;
+    MR_Word     univ2;
+    const char  *problem1;
+    const char  *problem2;
+    MR_bool     bad_subterm1;
+    MR_bool     bad_subterm2;
+
+    start = 0;
+    max = 20;
+    if (! MR_trace_options_diff(&start, &max, &words, &word_count)) {
+        /* the usage message has already been printed */
+        return KEEP_INTERACTING;
+    } else if (word_count != 3) {
+        MR_trace_usage_cur_cmd();
+        return KEEP_INTERACTING;
+    }
+
+    name1 = words[1];
+    name2 = words[2];
+    problem1 = MR_trace_parse_lookup_var_path(name1, &type_info1, &value1,
+        &bad_subterm1);
+    problem2 = MR_trace_parse_lookup_var_path(name2, &type_info2, &value2,
+        &bad_subterm2);
+    if (problem1 != NULL) {
+        fflush(MR_mdb_out);
+        fprintf(MR_mdb_err, "mdb: %s%s.\n",
+            (bad_subterm1? "arg1: there is no path " : ""), problem1);
+        return KEEP_INTERACTING;
+    }
+    if (problem2 != NULL) {
+        fflush(MR_mdb_out);
+        fprintf(MR_mdb_err, "mdb: %s%s.\n",
+            (bad_subterm2? "arg2: there is no path " : ""), problem2);
+        return KEEP_INTERACTING;
+    }
+
+    MR_TRACE_CALL_MERCURY(
+        MR_new_univ_on_hp(univ1, type_info1, value1);
+        MR_new_univ_on_hp(univ2, type_info2, value2);
+        ML_report_diffs(start, max, univ1, univ2);
+    );
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_dump(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_bool         verbose = MR_FALSE;
+    MR_Word         browser_term;
+    const char      *problem = NULL;
+    MR_bool         xml = MR_FALSE;
+
+    /*
+    ** Set this to NULL to avoid uninitialization warnings.
+    */
+    browser_term = (MR_Word) NULL;
+
+    if (! MR_trace_options_dump(&xml, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count != 3) {
+        MR_trace_usage_cur_cmd();
+    } else {
+        if (MR_streq(words[1], "goal")) {
+            const char  *name;
+            MR_Word     arg_list;
+            MR_bool     is_func;
+
+            problem = NULL;
+            MR_convert_goal_to_synthetic_term(&name, &arg_list, &is_func);
+            browser_term = MR_synthetic_to_browser_term(name, arg_list,
+                is_func);
+        } else if (MR_streq(words[1], "exception")) {
+            MR_Word exception;
+
+            exception = MR_trace_get_exception_value();
+            if (exception == (MR_Word) NULL) {
+                problem = "missing exception value";
+            } else {
+                browser_term = MR_univ_to_browser_term(exception);
+            }
+        } else if (MR_streq(words[1], "proc_body")) {
+            const MR_Proc_Layout    *entry;
+            MR_Word                 rep;
+
+            entry = event_info->MR_event_sll->MR_sll_entry;
+
+            if (entry->MR_sle_body_bytes == NULL) {
+                problem = "current procedure has no body bytecodes";
+            } else {
+                MR_TRACE_CALL_MERCURY(
+                    MR_DD_trace_read_rep(entry->MR_sle_body_bytes,
+                        event_info->MR_event_sll, &rep);
+                );
+
+                browser_term = MR_type_value_to_browser_term(
+                    (MR_TypeInfo) ML_proc_rep_type(), rep);
+            }
+        } else {
+            MR_Var_Spec var_spec;
+            MR_TypeInfo type_info;
+            MR_Word     value;
+            const char  *name;
+
+            MR_convert_arg_to_var_spec(words[1], &var_spec);
+            problem = MR_lookup_unambiguous_var_spec(var_spec,
+                &type_info, &value, &name);
+            if (problem == NULL) {
+                browser_term = MR_type_value_to_browser_term(type_info, value);
+            }
+        }
+
+        if (problem != NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+        } else {
+            if (xml) {
+                MR_trace_save_term_xml(words[2], browser_term);
+            } else {
+                MR_trace_save_term(words[2], browser_term);
+            }
+        }
+    }
+
+    return KEEP_INTERACTING;
+}
+
+/*
+** list [num]
+**  List num lines of context around the line number of the context of the
+**  current point (i.e., level in the call stack).  If num is not given,
+**  the number of context lines defaults to the value of the context_lines
+**  setting.
+**
+** TODO: add the following (use MR_parse_source_locn()):
+** list filename:num[-num]
+**  List a range of lines from a given file.  If only one number is
+**  given, the default number of lines of context is used.
+*/
+
+MR_Next
+MR_trace_cmd_list(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    const MR_Proc_Layout    *entry_ptr;
+    const char              *filename;
+    int                     lineno;
+    MR_Word                 *base_sp_ptr;
+    MR_Word                 *base_curfr_ptr;
+    MR_bool                 num = MR_num_context_lines;
+    MR_String               aligned_filename;
+
+    if (word_count > 2) {
+        MR_trace_usage_cur_cmd();
+        return KEEP_INTERACTING;
+    }
+
+    if (word_count == 2 && !MR_trace_is_natural_number(words[1], &num)) {
+        MR_trace_usage_cur_cmd();
+        return KEEP_INTERACTING;
+    }
+
+    MR_trace_current_level_details(&entry_ptr, &filename, &lineno,
+        &base_sp_ptr, &base_curfr_ptr);
+
+    MR_TRACE_USE_HP(
+        MR_make_aligned_string(aligned_filename, (MR_String) filename);
+    );
+
+    MR_TRACE_CALL_MERCURY(
+        ML_LISTING_list_file(MR_mdb_out, MR_mdb_err, (char *) aligned_filename,
+            lineno - num, lineno + num, lineno, MR_listing_path);
+    );
+
+    return KEEP_INTERACTING;
+}
+
+/****************************************************************************/
+
+static void
+MR_trace_set_level_and_report(int ancestor_level, MR_bool detailed,
+    MR_bool print_optionals)
+{
+    const char              *problem;
+    const MR_Proc_Layout    *entry;
+    MR_Word                 *base_sp;
+    MR_Word                 *base_curfr;
+    const char              *filename;
+    int                     lineno;
+    int                     indent;
+
+    problem = MR_trace_set_level(ancestor_level, print_optionals);
+    if (problem == NULL) {
+        fprintf(MR_mdb_out, "Ancestor level set to %d:\n",
+            ancestor_level);
+        MR_trace_current_level_details(&entry, &filename, &lineno,
+            &base_sp, &base_curfr);
+        fprintf(MR_mdb_out, "%4d ", ancestor_level);
+        if (detailed) {
+            /*
+            ** We want to print the trace info first regardless
+            ** of the value of MR_context_position.
+            */
+
+            MR_print_call_trace_info(MR_mdb_out, entry, base_sp, base_curfr);
+            indent = 26;
+        } else {
+            indent = 5;
+        }
+
+        MR_print_proc_id_trace_and_context(MR_mdb_out, MR_FALSE,
+            MR_context_position, entry, base_sp, base_curfr, "",
+            filename, lineno, MR_FALSE, "", 0, indent);
+    } else {
+        fflush(MR_mdb_out);
+        fprintf(MR_mdb_err, "%s.\n", problem);
+    }
+}
+
+void
+MR_trace_browse_internal(MR_Word type_info, MR_Word value,
+    MR_Browse_Caller_Type caller, MR_Browse_Format format)
+{
+    switch (caller) {
+
+        case MR_BROWSE_CALLER_BROWSE:
+            MR_trace_browse(type_info, value, format);
+            break;
+
+        case MR_BROWSE_CALLER_PRINT:
+        case MR_BROWSE_CALLER_PRINT_ALL:
+            fprintf(MR_mdb_out, "\t");
+            fflush(MR_mdb_out);
+            MR_trace_print(type_info, value, caller, format);
+            break;
+
+        default:
+            MR_fatal_error("MR_trace_browse_internal: unknown caller type");
+    }
+}
+
+void
+MR_trace_browse_goal_internal(MR_ConstString name, MR_Word arg_list,
+    MR_Word is_func, MR_Browse_Caller_Type caller, MR_Browse_Format format)
+{
+    switch (caller) {
+
+        case MR_BROWSE_CALLER_BROWSE:
+            MR_trace_browse_goal(name, arg_list, is_func, format);
+            break;
+
+        case MR_BROWSE_CALLER_PRINT:
+            MR_trace_print_goal(name, arg_list, is_func, caller, format);
+            break;
+
+        case MR_BROWSE_CALLER_PRINT_ALL:
+            MR_fatal_error("MR_trace_browse_goal_internal: bad caller type");
+
+        default:
+            MR_fatal_error("MR_trace_browse_goal_internal:"
+                " unknown caller type");
+    }
+}
+
+static const char *
+MR_trace_browse_exception(MR_Event_Info *event_info, MR_Browser browser,
+    MR_Browse_Caller_Type caller, MR_Browse_Format format)
+{
+    MR_TypeInfo type_info;
+    MR_Word     value;
+    MR_Word     exception;
+
+    if (event_info->MR_trace_port != MR_PORT_EXCEPTION) {
+        return "command only available from EXCP ports";
+    }
+
+    exception = MR_trace_get_exception_value();
+    if (exception == (MR_Word) NULL) {
+        return "missing exception value";
+    }
+
+    MR_unravel_univ(exception, type_info, value);
+
+    (*browser)((MR_Word) type_info, value, caller, format);
+
+    return (const char *) NULL;
+}
+
+static const char *
+MR_trace_browse_proc_body(MR_Event_Info *event_info, MR_Browser browser,
+    MR_Browse_Caller_Type caller, MR_Browse_Format format)
+{
+    const MR_Proc_Layout    *entry;
+    MR_Word                 rep;
+
+    entry = event_info->MR_event_sll->MR_sll_entry;
+
+    if (entry->MR_sle_body_bytes == NULL) {
+        return "current procedure has no body info";
+    }
+
+    MR_TRACE_CALL_MERCURY(
+        MR_DD_trace_read_rep(entry->MR_sle_body_bytes,
+            event_info->MR_event_sll, &rep);
+    );
+
+    (*browser)(ML_proc_rep_type(), rep, caller, format);
+    return (const char *) NULL;
+}
+
+static void
+MR_trace_browse_xml(MR_Word type_info, MR_Word value,
+    MR_Browse_Caller_Type caller, MR_Browse_Format format)
+{
+    MR_Word     browser_term;
+
+    browser_term = MR_type_value_to_browser_term((MR_TypeInfo) type_info,
+        value);
+
+    MR_trace_save_and_invoke_xml_browser(browser_term);
+}
+
+static void
+MR_trace_browse_goal_xml(MR_ConstString name, MR_Word arg_list,
+    MR_Word is_func, MR_Browse_Caller_Type caller, MR_Browse_Format format)
+{
+    MR_Word     browser_term;
+
+    browser_term = MR_synthetic_to_browser_term(name, arg_list, is_func);
+    MR_trace_save_and_invoke_xml_browser(browser_term);
+}
+
+static void
+MR_trace_cmd_stack_2(MR_Event_Info *event_info, MR_bool detailed,
+    int frame_limit, int line_limit)
+{
+    const MR_Label_Layout   *layout;
+    MR_Word                 *saved_regs;
+    const char              *msg;
+
+    layout = event_info->MR_event_sll;
+    saved_regs = event_info->MR_saved_regs;
+
+    MR_trace_init_modules();
+    msg = MR_dump_stack_from_layout(MR_mdb_out, layout,
+        MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs),
+        detailed, MR_context_position != MR_CONTEXT_NOWHERE,
+        frame_limit, line_limit, &MR_dump_stack_record_print);
+
+    if (msg != NULL) {
+        fflush(MR_mdb_out);
+        fprintf(MR_mdb_err, "%s.\n", msg);
+    }
+}
+
+/*
+** Implement the `view' command. First, check if there is a server attached.
+** If so, either stop it or abort the command, depending on whether '-f'
+** was given. Then, if a server name was not supplied, start a new server
+** with a unique name (which has been MR_malloc'd), otherwise attach to the
+** server with the supplied name (and make a MR_malloc'd copy of the name).
+*/
+
+static const char *
+MR_trace_new_source_window(const char *window_cmd, const char *server_cmd,
+    const char *server_name, int timeout, MR_bool force,
+    MR_bool verbose, MR_bool split)
+{
+    const char  *msg;
+
+    if (MR_trace_source_server.server_name != NULL) {
+        /*
+        ** We are already attached to a server.
+        */
+        if (force) {
+            MR_trace_maybe_close_source_window(verbose);
+        } else {
+            return "error: server already open (use '-f' to force)";
+        }
+    }
+
+    MR_trace_source_server.split = split;
+    if (server_cmd != NULL) {
+        MR_trace_source_server.server_cmd = MR_copy_string(server_cmd);
+    } else {
+        MR_trace_source_server.server_cmd = NULL;
+    }
+
+    if (server_name == NULL) {
+        msg = MR_trace_source_open_server(&MR_trace_source_server,
+                window_cmd, timeout, verbose);
+    } else {
+        MR_trace_source_server.server_name = MR_copy_string(server_name);
+        msg = MR_trace_source_attach(&MR_trace_source_server, timeout,
+            verbose);
+        if (msg != NULL) {
+            /*
+            ** Something went wrong, so we should free the
+            ** strings we allocated just above.
+            */
+            MR_free(MR_trace_source_server.server_name);
+            MR_trace_source_server.server_name = NULL;
+            MR_free(MR_trace_source_server.server_cmd);
+            MR_trace_source_server.server_cmd = NULL;
+        }
+    }
+
+    return msg;
+}
+
+void
+MR_trace_maybe_sync_source_window(MR_Event_Info *event_info, MR_bool verbose)
+{
+    const MR_Label_Layout   *parent;
+    const char              *filename;
+    int                     lineno;
+    const char              *parent_filename;
+    int                     parent_lineno;
+    const char              *problem; /* not used */
+    MR_Word                 *base_sp, *base_curfr;
+    const char              *msg;
+
+    if (MR_trace_source_server.server_name != NULL) {
+        lineno = 0;
+        filename = "";
+        parent_lineno = 0;
+        parent_filename = "";
+
+        /*
+        ** At interface ports we send both the parent context and
+        ** the current context.  Otherwise, we just send the current
+        ** context.
+        */
+        if (MR_port_is_interface(event_info->MR_trace_port)) {
+            base_sp = MR_saved_sp(event_info->MR_saved_regs);
+            base_curfr = MR_saved_curfr(event_info->MR_saved_regs);
+            parent = MR_find_nth_ancestor(event_info->MR_event_sll, 1,
+                &base_sp, &base_curfr, &problem);
+            if (parent != NULL) {
+                (void) MR_find_context(parent, &parent_filename,
+                   &parent_lineno);
+            }
+        }
+
+        if (filename[0] == '\0') {
+            (void) MR_find_context(event_info->MR_event_sll,
+                    &filename, &lineno);
+        }
+
+        msg = MR_trace_source_sync(&MR_trace_source_server, filename, lineno,
+            parent_filename, parent_lineno, verbose);
+        if (msg != NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: %s.\n", msg);
+        }
+    }
+}
+
+void
+MR_trace_maybe_close_source_window(MR_bool verbose)
+{
+    const char  *msg;
+
+    if (MR_trace_source_server.server_name != NULL) {
+        msg = MR_trace_source_close(&MR_trace_source_server, verbose);
+        if (msg != NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: %s.\n", msg);
+        }
+
+        MR_free(MR_trace_source_server.server_name);
+        MR_trace_source_server.server_name = NULL;
+        MR_free(MR_trace_source_server.server_cmd);
+        MR_trace_source_server.server_cmd = NULL;
+    }
+}
+
+/****************************************************************************/
+
+const char *const    MR_trace_print_cmd_args[] =
+    { "-f", "-p", "-v", "--flat", "--pretty", "--verbose",
+    "exception", "goal", "*", NULL };
+    
+/*
+** It is better to have a single completion where possible,
+** so don't include `-d' here.
+*/  
+
+const char *const    MR_trace_stack_cmd_args[] =
+    { "--detailed", NULL };
+    
+const char *const    MR_trace_view_cmd_args[] =
+    { "-c", "-f", "-n", "-s", "-t", "-v", "-w", "-2",
+    "--close", "--verbose", "--force", "--split-screen", 
+    "--window-command", "--server-command", "--server-name",
+    "--timeout", NULL };
+
+/****************************************************************************/
+
+static struct MR_option MR_trace_detailed_opts[] =
+{
+    { "detailed",   MR_no_argument, NULL,   'd' },
+    { NULL,         MR_no_argument, NULL,   0   }
+};
+
+static MR_bool
+MR_trace_options_detailed(MR_bool *detailed, char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "d",
+        MR_trace_detailed_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'd':
+                *detailed = MR_TRUE;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+static MR_bool
+MR_trace_options_stack_trace(MR_bool *detailed, int *frame_limit,
+    char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "df:",
+        MR_trace_detailed_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'd':
+                *detailed = MR_TRUE;
+                break;
+
+            case 'f':
+                if (! MR_trace_is_natural_number(MR_optarg, frame_limit)) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+static struct MR_option MR_trace_format_opts[] =
+{
+    { "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' },
+    { "xml",        MR_no_argument, NULL,   'x' },
+    { NULL,         MR_no_argument, NULL,   0   }
+};
+
+static MR_bool
+MR_trace_options_format(MR_Browse_Format *format, MR_bool *xml, char ***words,
+    int *word_count)
+{
+    int c;
+
+    *format = MR_BROWSE_DEFAULT_FORMAT;
+    *xml = MR_FALSE;
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "frvpx",
+        MR_trace_format_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'f':
+                *format = MR_BROWSE_FORMAT_FLAT;
+                break;
+
+            case 'r':
+                *format = MR_BROWSE_FORMAT_RAW_PRETTY;
+                break;
+
+            case 'v':
+                *format = MR_BROWSE_FORMAT_VERBOSE;
+                break;
+
+            case 'p':
+                *format = MR_BROWSE_FORMAT_PRETTY;
+                break;
+
+            case 'x':
+                *xml = MR_TRUE;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+static struct MR_option MR_trace_view_opts[] =
+{
+    { "close",          MR_no_argument,         NULL,   'c' },
+    { "window-command", MR_required_argument,   NULL,   'w' },
+    { "server-command", MR_required_argument,   NULL,   's' },
+    { "server-name",    MR_required_argument,   NULL,   'n' },
+    { "timeout",        MR_required_argument,   NULL,   't' },
+    { "force",          MR_no_argument,         NULL,   'f' },
+    { "verbose",        MR_no_argument,         NULL,   'v' },
+    { "split-screen",   MR_no_argument,         NULL,   '2' },
+    { NULL,             MR_no_argument,         NULL,   0   }
+};
+
+static MR_bool
+MR_trace_options_view(const char **window_cmd, const char **server_cmd,
+    const char **server_name, int *timeout, MR_bool *force,
+    MR_bool *verbose, MR_bool *split, MR_bool *close_window,
+    char ***words, int *word_count)
+{
+    int c;
+    MR_bool no_close = MR_FALSE;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "cw:s:n:t:fv2",
+        MR_trace_view_opts, NULL)) != EOF)
+    {
+        /*
+        ** Option '-c' is mutually incompatible with '-f', '-t',
+        ** '-s', '-n', '-w' and '-2'.
+        */
+        switch (c) {
+
+            case 'c':
+                if (no_close) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+
+                *close_window = MR_TRUE;
+                break;
+
+            case 'w':
+                if (*close_window) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+
+                *window_cmd = MR_optarg;
+                no_close = MR_TRUE;
+                break;
+
+            case 's':
+                if (*close_window) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+
+                *server_cmd = MR_optarg;
+                no_close = MR_TRUE;
+                break;
+
+            case 'n':
+                if (*close_window) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+
+                *server_name = MR_optarg;
+                no_close = MR_TRUE;
+                break;
+
+            case 't':
+                if (*close_window ||
+                    ! MR_trace_is_natural_number(MR_optarg, timeout))
+                {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+
+                no_close = MR_TRUE;
+                break;
+
+            case 'f':
+                if (*close_window) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+
+                *force = MR_TRUE;
+                no_close = MR_TRUE;
+                break;
+
+            case 'v':
+                *verbose = MR_TRUE;
+                break;
+
+            case '2':
+                if (*close_window) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+
+                *split = MR_TRUE;
+                no_close = MR_TRUE;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+static struct MR_option MR_trace_diff_opts[] =
+{
+    { "start",      MR_required_argument,   NULL,   's' },
+    { "max",        MR_required_argument,   NULL,   'm' },
+    { NULL,         MR_no_argument,         NULL,   0   }
+};
+
+static MR_bool
+MR_trace_options_diff(int *start, int *max, char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "m:s:",
+        MR_trace_diff_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'm':
+                if (! MR_trace_is_natural_number(MR_optarg, max)) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+                break;
+
+            case 's':
+                if (! MR_trace_is_natural_number(MR_optarg, start)) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+static struct MR_option MR_trace_dump_opts[] =
+{
+    { "xml",        MR_no_argument,     NULL,   'x' },
+    { NULL,         MR_no_argument,     NULL,   0   }
+};
+
+static MR_bool
+MR_trace_options_dump(MR_bool *xml, char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "x",
+        MR_trace_dump_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'x':
+                *xml = MR_TRUE;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+/****************************************************************************/
Index: trace/mercury_trace_cmd_browsing.h
===================================================================
RCS file: trace/mercury_trace_cmd_browsing.h
diff -N trace/mercury_trace_cmd_browsing.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_browsing.h	3 Apr 2006 12:37:21 -0000
@@ -0,0 +1,50 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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.
+*/
+
+#include "mercury_std.h"
+#include "mercury_types.h"
+
+#include "mercury_trace.h"
+#include "mercury_trace_cmds.h"
+#include "mercury_trace_browse.h"
+
+extern  MR_TraceCmdFunc     MR_trace_cmd_level;
+extern  MR_TraceCmdFunc     MR_trace_cmd_up;
+extern  MR_TraceCmdFunc     MR_trace_cmd_down;
+extern  MR_TraceCmdFunc     MR_trace_cmd_vars;
+extern  MR_TraceCmdFunc     MR_trace_cmd_held_vars;
+extern  MR_TraceCmdFunc     MR_trace_cmd_print;
+extern  MR_TraceCmdFunc     MR_trace_cmd_browse;
+extern  MR_TraceCmdFunc     MR_trace_cmd_stack;
+extern  MR_TraceCmdFunc     MR_trace_cmd_current;
+extern  MR_TraceCmdFunc     MR_trace_cmd_view;
+extern  MR_TraceCmdFunc     MR_trace_cmd_hold;
+extern  MR_TraceCmdFunc     MR_trace_cmd_diff;
+extern  MR_TraceCmdFunc     MR_trace_cmd_dump;
+extern  MR_TraceCmdFunc     MR_trace_cmd_list;
+
+/*
+** If we are attached to a source server, then find the appropriate
+** context and ask the server to point to it, otherwise do nothing.
+*/
+
+extern  void                MR_trace_maybe_sync_source_window(
+                                MR_Event_Info *event_info, MR_bool verbose);
+
+extern  void                MR_trace_browse_internal(MR_Word type_info,
+                                MR_Word value, MR_Browse_Caller_Type caller,
+                                MR_Browse_Format format);
+extern  void                MR_trace_browse_goal_internal(MR_ConstString name,
+                                MR_Word arg_list, MR_Word is_func,
+                                MR_Browse_Caller_Type caller,
+                                MR_Browse_Format format);
+
+extern  const char *const   MR_trace_print_cmd_args[];
+extern  const char *const   MR_trace_stack_cmd_args[];
+extern  const char *const   MR_trace_view_cmd_args[];
Index: trace/mercury_trace_cmd_dd.c
===================================================================
RCS file: trace/mercury_trace_cmd_dd.c
diff -N trace/mercury_trace_cmd_dd.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_dd.c	3 Apr 2006 12:50:30 -0000
@@ -0,0 +1,353 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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 module implements the mdb commands in the "dd" category.
+**
+** The structure of these files is:
+**
+** - all the #includes
+** - local macros and declarations of local static functions
+** - one function for each command in the category
+** - any auxiliary functions
+** - any command argument strings
+** - option processing functions.
+*/
+
+#include "mercury_std.h"
+#include "mercury_getopt.h"
+
+#include "mercury_trace_internal.h"
+#include "mercury_trace_cmds.h"
+#include "mercury_trace_cmd_dd.h"
+#include "mercury_trace_cmd_parameter.h"
+#include "mercury_trace_declarative.h"
+#include "mercury_trace_tables.h"
+#include "mercury_trace_util.h"
+
+/****************************************************************************/
+
+static  MR_bool     MR_trace_options_dd(MR_bool *assume_all_io_is_tabled,
+                        MR_Unsigned *default_depth, MR_Unsigned *num_nodes,
+                        MR_Decl_Search_Mode *search_mode,
+                        MR_bool *search_mode_was_set,
+                        MR_bool *search_mode_requires_trace_counts,
+                        char **pass_trace_counts_file,
+                        char **fail_trace_counts_file,
+                        MR_bool *new_session, MR_bool *testing, MR_bool *debug,
+                        char ***words, int *word_count);
+
+/****************************************************************************/
+
+MR_Next
+MR_trace_cmd_dd(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_Decl_Search_Mode search_mode;
+    MR_bool             search_mode_was_set = MR_FALSE;
+    MR_bool             new_session = MR_TRUE;
+    MR_bool             search_mode_requires_trace_counts = MR_FALSE;
+    char                *pass_trace_counts_file;
+    char                *fail_trace_counts_file;
+    MR_String           problem;
+    MR_bool             testing = MR_FALSE;
+    MR_bool             debug = MR_FALSE;
+    const char          *filename;
+    MR_Decl_Mode        decl_mode;
+
+    MR_trace_decl_assume_all_io_is_tabled = MR_FALSE;
+    MR_edt_default_depth_limit = MR_TRACE_DECL_INITIAL_DEPTH;
+    search_mode = MR_trace_get_default_search_mode();
+    pass_trace_counts_file = MR_dice_pass_trace_counts_file;
+    fail_trace_counts_file = MR_dice_fail_trace_counts_file;
+    MR_trace_decl_debug_debugger_mode = MR_FALSE;
+
+    if (! MR_trace_options_dd(&MR_trace_decl_assume_all_io_is_tabled,
+        &MR_edt_default_depth_limit, &MR_edt_desired_nodes_in_subtree,
+        &search_mode, &search_mode_was_set,
+        &search_mode_requires_trace_counts,
+        &pass_trace_counts_file, &fail_trace_counts_file, &new_session,
+        &testing, &MR_trace_decl_debug_debugger_mode, &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count <= 2) {
+        if (word_count == 2 && MR_trace_decl_debug_debugger_mode) {
+            decl_mode = MR_DECL_DUMP;
+            filename = (const char *) words[1];
+        } else {
+            decl_mode = MR_DECL_NODUMP;
+            filename = (const char *) NULL;
+        }
+        if (MR_trace_have_unhid_events) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err,
+                "mdb: dd doesn't work after `unhide_events on'.\n");
+            return KEEP_INTERACTING;
+        }
+        if (search_mode_requires_trace_counts && (
+            pass_trace_counts_file == NULL || fail_trace_counts_file == NULL))
+        {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err,
+                "mdb: you need to supply passing and failing trace count "
+                "files\nbefore using the specified search mode.\n");
+            return KEEP_INTERACTING;
+        }
+        if (pass_trace_counts_file != NULL && fail_trace_counts_file != NULL) {
+            if (! MR_trace_decl_init_suspicion_table(pass_trace_counts_file,
+                fail_trace_counts_file, &problem))
+            {
+                fflush(MR_mdb_out);
+                fprintf(MR_mdb_err, "mdb: %s\n", problem);
+                return KEEP_INTERACTING;
+            }
+        }
+
+        MR_trace_decl_set_testing_flag(testing);
+
+        if (search_mode_was_set || new_session) {
+            MR_trace_decl_set_fallback_search_mode(search_mode);
+        }
+
+        if (MR_trace_start_decl_debug(decl_mode, filename, new_session, cmd,
+            event_info, jumpaddr))
+        {
+            return STOP_INTERACTING;
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_trust(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_Proc_Spec        spec;
+    MR_Matches_Info     matches;
+
+    if (word_count == 2) {
+        spec.MR_proc_module = NULL;
+        spec.MR_proc_name   = NULL;
+        spec.MR_proc_arity  = -1;
+        spec.MR_proc_mode   = -1;
+        spec.MR_proc_prefix = (MR_Proc_Prefix) -1;
+
+        MR_register_all_modules_and_procs(MR_mdb_out, MR_TRUE);
+
+        /* First see if the argument is a module name */
+        spec.MR_proc_module = words[1];
+        matches = MR_search_for_matching_procedures(&spec);
+        if (matches.match_proc_next > 0) {
+            MR_decl_add_trusted_module(words[1]);
+            fprintf(MR_mdb_out, "Trusting module %s\n", words[1]);
+        } else if (MR_parse_proc_spec(words[1], &spec)) {
+            /* Check to see if the argument is a pred/func */
+            matches = MR_search_for_matching_procedures(&spec);
+            MR_filter_user_preds(&matches);
+            if (matches.match_proc_next == 0) {
+                fprintf(MR_mdb_err,
+                    "mdb: there is no such module, predicate or function.\n");
+            } else if (matches.match_proc_next == 1) {
+                MR_decl_add_trusted_pred_or_func(matches.match_procs[0]);
+                fprintf(MR_mdb_out, "Trusting ");
+                MR_print_pred_id_and_nl(MR_mdb_out, matches.match_procs[0]);
+            } else {
+                int     i;
+                char    buf[80];
+                char    *line2;
+
+                fprintf(MR_mdb_out, "Ambiguous predicate or function"
+                    " specification. The matches are:\n");
+                for (i = 0; i < matches.match_proc_next; i++) {
+                    fprintf(MR_mdb_out, "%d: ", i);
+                    MR_print_pred_id_and_nl(MR_mdb_out,
+                        matches.match_procs[i]);
+                }
+                sprintf(buf, "\nWhich predicate or function "
+                    "do you want to trust (0-%d or *)? ",
+                    matches.match_proc_next - 1);
+                line2 = MR_trace_getline(buf, MR_mdb_in, MR_mdb_out);
+                if (line2 == NULL) {
+                    /* This means the user input EOF. */
+                    fprintf(MR_mdb_out, "none of them\n");
+                } else if (MR_streq(line2, "*")) {
+                    for (i = 0; i < matches.match_proc_next; i++) {
+                        MR_decl_add_trusted_pred_or_func(
+                            matches.match_procs[i]);
+
+                        fprintf(MR_mdb_out, "Trusting ");
+                        MR_print_pred_id_and_nl(MR_mdb_out,
+                            matches.match_procs[i]);
+                    }
+                    MR_free(line2);
+                } else if(MR_trace_is_natural_number(line2, &i)) {
+                    if (0 <= i && i < matches.match_proc_next) {
+                        MR_decl_add_trusted_pred_or_func(
+                            matches.match_procs[i]);
+
+                        fprintf(MR_mdb_out, "Trusting ");
+                        MR_print_pred_id_and_nl(MR_mdb_out,
+                            matches.match_procs[i]);
+                    } else {
+                        fprintf(MR_mdb_out, "no such match\n");
+                    }
+                    MR_free(line2);
+                } else {
+                    fprintf(MR_mdb_out, "none of them\n");
+                    MR_free(line2);
+                }
+            }
+        }
+    } else if (word_count == 3 &&
+        ((MR_streq(words[1], "std") && MR_streq(words[2], "lib"))
+        || (MR_streq(words[1], "standard") && MR_streq(words[2], "library"))))
+    {
+        MR_decl_trust_standard_library();
+        fprintf(MR_mdb_out, "Trusting the Mercury standard library\n");
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_untrust(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int i;
+
+    if (word_count == 2 && MR_trace_is_natural_number(words[1], &i)) {
+        if (!MR_decl_remove_trusted(i)) {
+            fprintf(MR_mdb_err, "mdb: no such trusted object\n");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_trusted(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 1) {
+        MR_decl_print_all_trusted(MR_mdb_out, MR_FALSE);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+    return KEEP_INTERACTING;
+}
+
+/****************************************************************************/
+
+const char *const    MR_trace_dd_cmd_args[] =
+    { "-s", "-a", "-d", "-n", "--search-mode",
+    "--assume-all-io-is-tabled", "--depth", "--nodes",
+    "td", "top_down", "dq" "divide_and_query", "sdq",
+    "suspicion_divide_and_query", NULL };
+
+/****************************************************************************/
+
+static struct MR_option MR_trace_dd_opts[] =
+{
+    { "assume-all-io-is-tabled",    MR_no_argument,         NULL,   'a' },
+    { "debug",                      MR_no_argument,         NULL,   'z' },
+    { "depth",                      MR_required_argument,   NULL,   'd' },
+    { "nodes",                      MR_required_argument,   NULL,   'n' },
+    { "resume",                     MR_no_argument,         NULL,   'r' },
+    { "search-mode",                MR_required_argument,   NULL,   's' },
+    { "pass-trace-counts",          MR_required_argument,   NULL,   'p' },
+    { "pass-trace-count",           MR_required_argument,   NULL,   'p' },
+    { "fail-trace-counts",          MR_required_argument,   NULL,   'f' },
+    { "fail-trace-count",           MR_required_argument,   NULL,   'f' },
+    { "resume",                     MR_no_argument,         NULL,   'r' },
+    { "test",                       MR_no_argument,         NULL,   't' },
+    { NULL,                         MR_no_argument,         NULL,   0 }
+};
+
+static MR_bool
+MR_trace_options_dd(MR_bool *assume_all_io_is_tabled,
+    MR_Unsigned *default_depth, MR_Unsigned *num_nodes,
+    MR_Decl_Search_Mode *search_mode, MR_bool *search_mode_was_set,
+    MR_bool *search_mode_requires_trace_counts,
+    char **pass_trace_counts_file, char **fail_trace_counts_file,
+    MR_bool *new_session, MR_bool *testing,  MR_bool *debug,
+    char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "ad:f:n:p:rs:tz",
+        MR_trace_dd_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'a':
+                *assume_all_io_is_tabled = MR_TRUE;
+                break;
+
+            case 'd':
+                if (! MR_trace_is_unsigned(MR_optarg, default_depth)) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+                break;
+
+            case 'f':
+                *fail_trace_counts_file = MR_copy_string(MR_optarg);
+                break;
+
+            case 'n':
+                if (! MR_trace_is_unsigned(MR_optarg, num_nodes)) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+                break;
+
+            case 'p':
+                *pass_trace_counts_file = MR_copy_string(MR_optarg);
+                break;
+
+            case 'r':
+                *new_session = MR_FALSE;
+                break;
+
+            case 's':
+                if (MR_trace_is_valid_search_mode_string(MR_optarg,
+                    search_mode, search_mode_requires_trace_counts))
+                {
+                    *search_mode_was_set = MR_TRUE;
+                } else {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+                break;
+
+            case 't':
+                *testing = MR_TRUE;
+                break;
+
+            case 'z':
+                *debug = MR_TRUE;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
Index: trace/mercury_trace_cmd_dd.h
===================================================================
RCS file: trace/mercury_trace_cmd_dd.h
diff -N trace/mercury_trace_cmd_dd.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_dd.h	3 Apr 2006 09:51:05 -0000
@@ -0,0 +1,20 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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.
+*/
+
+#include "mercury_imp.h"
+#include "mercury_stack_trace.h" /* for MR_Context_Position  */
+
+#include "mercury_trace_cmds.h"
+
+extern  MR_TraceCmdFunc     MR_trace_cmd_dd;
+extern  MR_TraceCmdFunc     MR_trace_cmd_trust;
+extern  MR_TraceCmdFunc     MR_trace_cmd_untrust;
+extern  MR_TraceCmdFunc     MR_trace_cmd_trusted;
+
+extern  const char *const   MR_trace_dd_cmd_args[];
Index: trace/mercury_trace_cmd_developer.c
===================================================================
RCS file: trace/mercury_trace_cmd_developer.c
diff -N trace/mercury_trace_cmd_developer.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_developer.c	3 Apr 2006 12:50:37 -0000
@@ -0,0 +1,2243 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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 module implements the mdb commands in the "developer" category.
+**
+** The structure of these files is:
+**
+** - all the #includes
+** - local macros and declarations of local static functions
+** - one function for each command in the category
+** - any auxiliary functions
+** - any command argument strings
+** - option processing functions.
+*/
+
+#include "mercury_std.h"
+#include "mercury_getopt.h"
+#include "mercury_types.h"
+#include "mercury_trace_base.h"
+
+#include "mercury_trace_internal.h"
+#include "mercury_trace_cmds.h"
+#include "mercury_trace_cmd_developer.h"
+#include "mercury_trace_cmd_parameter.h"
+#include "mercury_trace_tables.h"
+#include "mercury_trace_util.h"
+
+#include <stdio.h>
+
+/****************************************************************************/
+
+static  void        MR_trace_cmd_nondet_stack_2(MR_Event_Info *event_info,
+                        MR_bool detailed, int frame_limit, int line_limit);
+
+static  const MR_Proc_Layout
+                    *MR_find_single_matching_proc(MR_Proc_Spec *spec,
+                        MR_bool verbose);
+
+/*
+** The following data structures describe the information we have about the
+** input arguments of tabled procedures. We use them to decode the call tables
+** of such procedures.
+**
+** We use one MR_Call_Table_Arg structure for each input argument.
+**
+** The step field specifies what data structure the tabling system uses to
+** implement the trie nodes at the level of the call table corresponding to
+** the relevant argument. At the moment, we support only four values of this
+** field, MR_TABLE_STEP_INT, MR_TABLE_STEP_FLOAT, MR_TABLE_STEP_STRING and
+** MR_TABLE_STEP_PROMISE_IMPLIED. The first three of these implicitly select
+** the corresponding alternative in the arg_values union; the last one
+** indicates the absence of a step.
+**
+** The start_node field specifies the start node of the relevant trie. For the
+** first input argument, this will be the tabling pointer variable for the
+** given procedure. For later input arguments, it will be the trie node you
+** reach after following the current values of the previous arguments through
+** the call table.
+**
+** The MR_{Int,Float,String}_Table_Arg_Values structs have the same fields and
+** the same meanings, differing only in the types of the values they store.
+** Each struct is used for one of two things.
+**
+** 1. To describe a value supplied by the user on the mdb command line.
+**    In this case, the only field that matters is the cur_value field.
+**
+** 2. To describe the set of values you can find in a trie node, the one given
+**    by the start_node field, and to specify which is the current one.
+**    In this case, all the fields matter.
+**
+** The code that manipulates these structures distinguishes between the two
+** uses based on argument number.
+**
+** The values array is managed with the macros in mercury_array_macros.h,
+** so its size is given by the value_next field. The cur_index field gives the
+** index of the current value, while the cur_value field gives the current
+** value itself. (The contents of the cur_value field can be deduced from the
+** contents of the other fields with use 2, but not with use 1.)
+**
+** The valid field in the MR_Call_Table_Arg structure gives the validity
+** of the values subfield of its arg_values field; if it is false, then the
+** array is logically considered empty.
+*/
+
+typedef struct {
+    MR_Integer                  *MR_ctai_values;
+    int                         MR_ctai_value_next;
+    int                         MR_ctai_cur_index;
+    MR_Integer                  MR_ctai_cur_value;
+} MR_Int_Table_Arg_Values;
+
+typedef struct {
+    MR_Float                    *MR_ctaf_values;
+    int                         MR_ctaf_value_next;
+    int                         MR_ctaf_cur_index;
+    MR_Float                    MR_ctaf_cur_value;
+} MR_Float_Table_Arg_Values;
+
+typedef struct {
+    MR_ConstString              *MR_ctas_values;
+    int                         MR_ctas_value_next;
+    int                         MR_ctas_cur_index;
+    MR_ConstString              MR_ctas_cur_value;
+} MR_String_Table_Arg_Values;
+
+typedef union {
+    MR_Int_Table_Arg_Values     MR_cta_values_int;
+    MR_Float_Table_Arg_Values   MR_cta_values_float;
+    MR_String_Table_Arg_Values  MR_cta_values_string;
+} MR_Table_Arg_Values;
+
+typedef struct {
+    MR_Table_Trie_Step          MR_cta_step;
+    int                         MR_cta_unfiltered_arg_num;
+    MR_TrieNode                 MR_cta_start_node;
+    MR_bool                     MR_cta_valid;
+    MR_Table_Arg_Values         MR_cta_arg_values;
+} MR_Call_Table_Arg;
+
+#define MR_cta_int_values       MR_cta_arg_values.MR_cta_values_int.\
+                                    MR_ctai_values
+#define MR_cta_int_value_next   MR_cta_arg_values.MR_cta_values_int.\
+                                    MR_ctai_value_next
+#define MR_cta_int_cur_index    MR_cta_arg_values.MR_cta_values_int.\
+                                    MR_ctai_cur_index
+#define MR_cta_int_cur_value    MR_cta_arg_values.MR_cta_values_int.\
+                                    MR_ctai_cur_value
+
+#define MR_cta_float_values     MR_cta_arg_values.MR_cta_values_float.\
+                                    MR_ctaf_values
+#define MR_cta_float_value_next MR_cta_arg_values.MR_cta_values_float.\
+                                    MR_ctaf_value_next
+#define MR_cta_float_cur_index  MR_cta_arg_values.MR_cta_values_float.\
+                                    MR_ctaf_cur_index
+#define MR_cta_float_cur_value  MR_cta_arg_values.MR_cta_values_float.\
+                                    MR_ctaf_cur_value
+
+#define MR_cta_string_values    MR_cta_arg_values.MR_cta_values_string.\
+                                    MR_ctas_values
+#define MR_cta_string_value_next MR_cta_arg_values.MR_cta_values_string.\
+                                    MR_ctas_value_next
+#define MR_cta_string_cur_index MR_cta_arg_values.MR_cta_values_string.\
+                                    MR_ctas_cur_index
+#define MR_cta_string_cur_value MR_cta_arg_values.MR_cta_values_string.\
+                                    MR_ctas_cur_value
+
+/*
+** These functions fill in the data structure describing one input argument
+** of a tabled procedure with a constant value given on the mdb command line.
+** They return true if they succeed, and false if they fail (e.g. because the
+** string given on the mdb command line does not describe a value of the
+** required type).
+*/
+
+static  MR_bool     MR_trace_fill_in_int_table_arg_slot(
+                        MR_TrieNode *table_cur_ptr,
+                        int arg_num, MR_ConstString given_arg,
+                        MR_Call_Table_Arg *call_table_arg_ptr);
+static  MR_bool     MR_trace_fill_in_float_table_arg_slot(
+                        MR_TrieNode *table_cur_ptr,
+                        int arg_num, MR_ConstString given_arg,
+                        MR_Call_Table_Arg *call_table_arg_ptr);
+static  MR_bool     MR_trace_fill_in_string_table_arg_slot(
+                        MR_TrieNode *table_cur_ptr,
+                        int arg_num, MR_ConstString given_arg,
+                        MR_Call_Table_Arg *call_table_arg_ptr);
+
+/*
+** These functions fill in the data structure describing one input argument
+** of a tabled procedure with the next value taken from the given trie node.
+** They return true if there are no more values in the trie node, and false
+** otherwise.
+*/
+
+static  MR_bool     MR_update_int_table_arg_slot(MR_TrieNode *table_cur_ptr,
+                        MR_Call_Table_Arg *call_table_arg_ptr);
+static  MR_bool     MR_update_float_table_arg_slot(MR_TrieNode *table_cur_ptr,
+                        MR_Call_Table_Arg *call_table_arg_ptr);
+static  MR_bool     MR_update_string_table_arg_slot(MR_TrieNode *table_cur_ptr,
+                        MR_Call_Table_Arg *call_table_arg_ptr);
+
+/* Prints the given subgoal of the given procedure to MR_mdb_out. */
+static  void        MR_trace_cmd_table_print_tip(const MR_Proc_Layout *proc,
+                        int filtered_num_inputs,
+                        MR_Call_Table_Arg *call_table_args, MR_TrieNode table);
+
+/* Prints the given subgoal of the given procedure to MR_mdb_out. */
+static  void        MR_trace_print_subgoal(const MR_Proc_Layout *proc,
+                        MR_Subgoal *subgoal);
+static  void        MR_trace_print_subgoal_debug(const MR_Proc_Layout *proc,
+                        MR_SubgoalDebug *subgoal_debug);
+
+/* Prints the given generator of the given procedure to MR_mdb_out. */
+static  void        MR_trace_print_generator(const MR_Proc_Layout *proc,
+                        MR_Generator *generator);
+static  void        MR_trace_print_generator_debug(const MR_Proc_Layout *proc,
+                        MR_GenDebug *generator_debug);
+
+/* Prints the given consumer of the given procedure to MR_mdb_out. */
+static  void        MR_trace_print_consumer(const MR_Proc_Layout *proc,
+                        MR_Consumer *consumer);
+static  void        MR_trace_print_consumer_debug(const MR_Proc_Layout *proc,
+                        MR_ConsumerDebug *consumer_debug);
+
+/* Prints the requested information inside the given MR_TypeCtorInfo. */
+static  void        MR_print_type_ctor_info(FILE *fp,
+                        MR_TypeCtorInfo type_ctor_info,
+                        MR_bool print_rep, MR_bool print_functors);
+
+/* Prints the requested information inside the given MR_TypeClassDeclInfo. */
+static  void        MR_print_class_decl_info(FILE *fp,
+                        MR_TypeClassDeclInfo *type_class_decl_info,
+                        MR_bool print_methods, MR_bool print_instances);
+
+/* Print the given pseudo-typeinfo. */
+static  void        MR_print_pseudo_type_info(FILE *fp,
+                        MR_PseudoTypeInfo pseudo);
+
+/****************************************************************************/
+
+static  MR_bool     MR_trace_options_nondet_stack(MR_bool *detailed,
+                        int *frame_limit, char ***words, int *word_count);
+static  MR_bool     MR_trace_options_stats(char **filename, char ***words,
+                        int *word_count);
+static  MR_bool     MR_trace_options_type_ctor(MR_bool *print_rep,
+                        MR_bool *print_functors, char ***words,
+                        int *word_count);
+static  MR_bool     MR_trace_options_class_decl(MR_bool *print_methods,
+                        MR_bool *print_instances, char ***words,
+                        int *word_count);
+static  MR_bool     MR_trace_options_all_procedures(MR_bool *separate,
+                        MR_bool *uci, char **module, char ***words,
+                        int *word_count);
+static  MR_bool     MR_trace_options_ambiguity(const char **outfile,
+                        char ***words, int *word_count);
+
+/****************************************************************************/
+
+MR_Next
+MR_trace_cmd_var_details(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int n;
+
+    if (word_count == 1) {
+        const char  *problem;
+
+        problem = MR_trace_list_var_details(MR_mdb_out);
+        if (problem != NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_term_size(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int n;
+
+    if (word_count == 2) {
+        const char  *problem;
+
+        if (MR_streq(words[1], "*")) {
+            problem = MR_trace_print_size_all(MR_mdb_out);
+        } else {
+            problem = MR_trace_print_size_one(MR_mdb_out, words[1]);
+        }
+
+        if (problem != NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: %s.\n", problem);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_flag(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    const char  *name;
+    MR_bool     *flagptr;
+    int         i;
+    MR_bool     found;
+    const char  *set_word;
+
+    /* Set this to NULL to avoid uninitialization warnings. */
+    flagptr = NULL;
+
+    if (word_count == 1) {
+        for (i = 0; i < MR_MAXFLAG; i++) {
+            /*
+            ** The true values of the debugging flags are stored in
+            ** MR_saved_debug_state inside the call tree of MR_trace_event.
+            */
+
+            flagptr = &MR_saved_debug_state.MR_sds_debugflags[
+                MR_debug_flag_info[i].MR_debug_flag_index];
+            name = MR_debug_flag_info[i].MR_debug_flag_name;
+            if (*flagptr) {
+                fprintf(MR_mdb_out, "Flag %s is set.\n", name);
+            } else {
+                fprintf(MR_mdb_out, "Flag %s is clear.\n", name);
+            }
+        }
+
+        return KEEP_INTERACTING;
+    } else if (word_count == 2) {
+        name = words[1];
+        set_word = NULL;
+    } else if (word_count == 3) {
+        name = words[1];
+        set_word = words[2];
+    } else {
+        MR_trace_usage_cur_cmd();
+        return KEEP_INTERACTING;
+    }
+
+    found = MR_FALSE;
+    for (i = 0; i < MR_MAXFLAG; i++) {
+        if (MR_streq(MR_debug_flag_info[i].MR_debug_flag_name, name)) {
+            /*
+            ** The true values of the debugging flags are stored in
+            ** MR_saved_debug_state inside the call tree of MR_trace_event.
+            */
+
+            flagptr = &MR_saved_debug_state.MR_sds_debugflags[
+                MR_debug_flag_info[i].MR_debug_flag_index];
+            found = MR_TRUE;
+            break;
+        }
+    }
+
+    if (!found) {
+        fprintf(MR_mdb_out, "There is no flag named %s.\n", name);
+        return KEEP_INTERACTING;
+    }
+
+    if (set_word != NULL) {
+        if (MR_streq(set_word, "on")) {
+            *flagptr = MR_TRUE;
+            fprintf(MR_mdb_out, "Flag %s is now set.\n", name);
+        } else if (MR_streq(set_word, "off")) {
+            *flagptr = MR_FALSE;
+            fprintf(MR_mdb_out, "Flag %s is now clear.\n", name);
+        } else {
+            MR_trace_usage_cur_cmd();
+        }
+    } else {
+        if (*flagptr) {
+            fprintf(MR_mdb_out, "Flag %s is set.\n", name);
+        } else {
+            fprintf(MR_mdb_out, "Flag %s is clear.\n", name);
+        }
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_subgoal(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
+
+    MR_SubgoalDebug *subgoal_debug;
+    MR_Subgoal  *subgoal;
+    int     n;
+
+    if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+        MR_trace_init_modules();
+
+        subgoal_debug = MR_lookup_subgoal_debug_num(n);
+        if (subgoal_debug == NULL) {
+            fprintf(MR_mdb_out, "no such subgoal\n");
+        } else {
+            MR_trace_print_subgoal_debug(NULL, subgoal_debug);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+#else   /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+    fprintf(MR_mdb_out, "mdb: the `subgoal' command is available "
+        "only in stack copy minimal model tabling grades.\n");
+
+#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_consumer(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
+
+    MR_ConsumerDebug    *consumer_debug;
+    MR_Consumer         *consumer;
+    int                 n;
+
+    if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+        MR_trace_init_modules();
+
+        consumer_debug = MR_lookup_consumer_debug_num(n);
+        if (consumer_debug == NULL) {
+            fprintf(MR_mdb_out, "no such consumer\n");
+        } else {
+            MR_trace_print_consumer_debug(NULL, consumer_debug);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+#else   /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+    fprintf(MR_mdb_out, "mdb: the `consumer' command is available "
+        "only in stack copy minimal model tabling grades.\n");
+
+#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_gen_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
+
+    if (word_count == 1) {
+        MR_bool saved_tabledebug;
+
+        MR_trace_init_modules();
+        saved_tabledebug = MR_tabledebug;
+        MR_tabledebug = MR_TRUE;
+        MR_print_gen_stack(MR_mdb_out);
+        MR_tabledebug = saved_tabledebug;
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+#else   /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+    fprintf(MR_mdb_out, "mdb: the `gen_stack' command is available "
+        "only in stack copy minimal model tabling grades.\n");
+
+#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_cut_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
+
+    if (word_count == 1) {
+        MR_bool saved_tabledebug;
+
+        MR_trace_init_modules();
+        saved_tabledebug = MR_tabledebug;
+        MR_tabledebug = MR_TRUE;
+        MR_print_cut_stack(MR_mdb_out);
+        MR_tabledebug = saved_tabledebug;
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+#else   /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+    fprintf(MR_mdb_out, "mdb: the `cut_stack' command is available "
+        "only in stack copy minimal model tabling grades.\n");
+
+#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_pneg_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
+
+    if (word_count == 1) {
+        MR_bool saved_tabledebug;
+
+        MR_trace_init_modules();
+        saved_tabledebug = MR_tabledebug;
+        MR_tabledebug = MR_TRUE;
+        MR_print_pneg_stack(MR_mdb_out);
+        MR_tabledebug = saved_tabledebug;
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+#else   /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+    fprintf(MR_mdb_out, "mdb: the `pneg_stack' command is available "
+        "only in stack copy minimal model tabling grades.\n");
+
+#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_mm_stacks(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
+
+    if (word_count == 1) {
+        MR_bool saved_tabledebug;
+
+        MR_trace_init_modules();
+        saved_tabledebug = MR_tabledebug;
+        MR_tabledebug = MR_TRUE;
+        MR_print_gen_stack(MR_mdb_out);
+        fprintf(MR_mdb_out, "\n");
+        MR_print_cut_stack(MR_mdb_out);
+        fprintf(MR_mdb_out, "\n");
+        MR_print_pneg_stack(MR_mdb_out);
+        MR_tabledebug = saved_tabledebug;
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+#else   /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+    fprintf(MR_mdb_out, "mdb: the `pneg_stack' command is available "
+        "only in stack copy minimal model tabling grades.\n");
+
+#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_nondet_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_bool     detailed;
+    int         frame_limit = 0;
+    int         line_limit = MR_stack_default_line_limit;
+    int         spec_line_limit;
+
+    detailed = MR_FALSE;
+    if (! MR_trace_options_nondet_stack(&detailed, &frame_limit,
+        &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 1) {
+        MR_trace_cmd_nondet_stack_2(event_info, detailed, frame_limit,
+            line_limit);
+    } else if (word_count == 2 &&
+        MR_trace_is_natural_number(words[1], &spec_line_limit))
+    {
+        MR_trace_cmd_nondet_stack_2(event_info, detailed, frame_limit,
+            spec_line_limit);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_stack_regs(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_Word     *saved_regs;
+
+    saved_regs = event_info->MR_saved_regs;
+
+    if (word_count == 1) {
+        MR_print_stack_regs(MR_mdb_out, saved_regs);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_all_regs(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_Word     *saved_regs;
+
+    saved_regs = event_info->MR_saved_regs;
+
+    if (word_count == 1) {
+        MR_print_stack_regs(MR_mdb_out, saved_regs);
+        MR_print_heap_regs(MR_mdb_out, saved_regs);
+        MR_print_tabling_regs(MR_mdb_out, saved_regs);
+        MR_print_succip_reg(MR_mdb_out, saved_regs);
+        MR_print_r_regs(MR_mdb_out, saved_regs);
+#ifdef  MR_DEEP_PROFILING
+        MR_print_deep_prof_vars(MR_mdb_out, "mdb all_regs");
+#endif
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_debug_vars(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 1) {
+        MR_print_debug_vars(MR_mdb_out, event_info);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_stats(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    char    *filename;
+    FILE    *fp;
+    MR_bool should_close;
+
+    filename = NULL;
+    if (! MR_trace_options_stats(&filename, &words, &word_count)) {
+        /* the usage message has already been printed */
+        return KEEP_INTERACTING;
+    }
+
+    if (word_count != 2) {
+        MR_trace_usage_cur_cmd();
+    }
+
+    if (filename != NULL) {
+        fp = fopen(filename, "w");
+        if (fp == NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: error opening `%s': %s.\n",
+                filename, strerror(errno));
+            return KEEP_INTERACTING;
+        }
+
+        should_close = MR_TRUE;
+    } else {
+        fp = MR_mdb_out;
+        should_close = MR_FALSE;
+    }
+
+    if (MR_streq(words[1], "procs")) {
+        MR_proc_layout_stats(fp);
+    } else if (MR_streq(words[1], "labels")) {
+        MR_label_layout_stats(fp);
+    } else if (MR_streq(words[1], "var_names")) {
+        MR_var_name_stats(fp);
+    } else if (MR_streq(words[1], "io_tabling")) {
+        MR_io_tabling_stats(fp);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    if (should_close) {
+        (void) fclose(fp);
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_print_optionals(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 2 && MR_streq(words[1], "off")) {
+        MR_print_optionals = MR_FALSE;
+        MR_trace_set_level(MR_trace_current_level(), MR_print_optionals);
+    } else if (word_count == 2 && MR_streq(words[1], "on")) {
+        MR_print_optionals = MR_TRUE;
+        MR_trace_set_level(MR_trace_current_level(), MR_print_optionals);
+    } else if (word_count == 1) {
+        fprintf(MR_mdb_out, "optional values are %sbeing printed\n",
+            MR_print_optionals? "" : "not ");
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_unhide_events(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 2 && MR_streq(words[1], "off")) {
+        MR_trace_unhide_events = MR_FALSE;
+        fprintf(MR_mdb_out, "Hidden events are hidden.\n");
+    } else if (word_count == 2 && MR_streq(words[1], "on")) {
+        MR_trace_unhide_events = MR_TRUE;
+        MR_trace_have_unhid_events = MR_TRUE;
+        fprintf(MR_mdb_out, "Hidden events are exposed.\n");
+    } else if (word_count == 1) {
+        fprintf(MR_mdb_out, "Hidden events are %s.\n",
+            MR_trace_unhide_events? "exposed" : "hidden");
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_table(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_Call_Table_Arg       *call_table_args;
+    const MR_Proc_Layout    *proc;
+    MR_Proc_Spec            spec;
+    const MR_Table_Gen      *table_gen;
+    MR_TrieNode             table_cur;
+    int                     num_inputs;
+    int                     filtered_num_inputs;
+    int                     cur_arg;
+    int                     filtered_cur_arg;
+    int                     num_tips;
+
+    if (word_count < 2) {
+        MR_trace_usage_cur_cmd();
+        return KEEP_INTERACTING;
+    }
+
+    if (! MR_parse_proc_spec(words[1], &spec)) {
+        fflush(MR_mdb_out);
+        fprintf(MR_mdb_err, "mdb: invalid procedure specification.\n");
+        return KEEP_INTERACTING;
+    }
+
+    proc = MR_find_single_matching_proc(&spec, MR_TRUE);
+    if (proc == NULL) {
+        return KEEP_INTERACTING;
+    }
+
+    switch (MR_sle_eval_method(proc)) {
+        case MR_EVAL_METHOD_NORMAL:
+            MR_print_proc_id(MR_mdb_out, proc);
+            fprintf(MR_mdb_out, " isn't tabled.\n");
+            return KEEP_INTERACTING;
+
+        case MR_EVAL_METHOD_LOOP_CHECK:
+        case MR_EVAL_METHOD_MEMO_STRICT:
+        case MR_EVAL_METHOD_MEMO_FAST_LOOSE:
+        case MR_EVAL_METHOD_MEMO_SPECIFIED:
+        case MR_EVAL_METHOD_MINIMAL_STACK_COPY:
+        case MR_EVAL_METHOD_MINIMAL_OWN_STACKS:
+            break;
+
+        case MR_EVAL_METHOD_TABLE_IO:
+        case MR_EVAL_METHOD_TABLE_IO_DECL:
+        case MR_EVAL_METHOD_TABLE_IO_UNITIZE:
+        case MR_EVAL_METHOD_TABLE_IO_UNITIZE_DECL:
+            fprintf(MR_mdb_out,
+                "IO tabled predicates do not have their own tables.\n");
+            return KEEP_INTERACTING;
+    }
+
+    /*
+    ** words[0] is the command, words[1] is the procedure spec;
+    ** words[2] is the first argument. We step over the command and the
+    ** procedure spec, to leave words[] containing only the argument
+    ** values.
+    */
+
+    words += 2;
+    word_count -= 2;
+
+    table_gen = proc->MR_sle_table_info.MR_table_gen;
+    num_inputs = table_gen->MR_table_gen_num_inputs;
+
+    if (word_count > num_inputs) {
+        fprintf(MR_mdb_out, "There are only %d input arguments.\n",
+            num_inputs);
+        return KEEP_INTERACTING;
+    }
+
+    call_table_args = MR_GC_NEW_ARRAY(MR_Call_Table_Arg, num_inputs);
+    if (call_table_args == NULL) {
+        MR_fatal_error("MR_trace_cmd_table: "
+            "couldn't allocate call_table_args");
+    }
+
+    table_cur = proc->MR_sle_tabling_pointer;
+    for (cur_arg = 0, filtered_cur_arg = 0; cur_arg < num_inputs; cur_arg++) {
+        switch (table_gen->MR_table_gen_input_steps[cur_arg]) {
+            case MR_TABLE_STEP_INT:
+            case MR_TABLE_STEP_FLOAT:
+            case MR_TABLE_STEP_STRING:
+                /* these are OK */
+                call_table_args[filtered_cur_arg].MR_cta_step =
+                    table_gen->MR_table_gen_input_steps[filtered_cur_arg];
+                call_table_args[filtered_cur_arg].MR_cta_valid = MR_FALSE;
+                call_table_args[filtered_cur_arg].MR_cta_unfiltered_arg_num =
+                    cur_arg;
+                filtered_cur_arg++;
+
+            case MR_TABLE_STEP_PROMISE_IMPLIED:
+                /* this argument doesn't exist in the table */
+                break;
+
+            default:
+                fprintf(MR_mdb_out, "Sorry, can handle only "
+                    "integer, float and string arguments for now.\n");
+                MR_GC_free(call_table_args);
+                return KEEP_INTERACTING;
+        }
+    }
+
+    filtered_num_inputs = filtered_cur_arg;
+    if (word_count > filtered_num_inputs) {
+        fprintf(MR_mdb_out,
+            "Sorry, this procedure has only %d tabled arguments\n",
+            filtered_num_inputs);
+        MR_GC_free(call_table_args);
+        return KEEP_INTERACTING;
+    }
+
+    /*
+    ** Set up the values of the input arguments supplied on the command
+    ** line, to enable us to print them out in each call table entry.
+    */
+
+    for (filtered_cur_arg = 0;
+        filtered_cur_arg < word_count;
+        filtered_cur_arg++)
+    {
+        MR_bool success;
+
+        switch (call_table_args[filtered_cur_arg].MR_cta_step) {
+            case MR_TABLE_STEP_INT:
+                success = MR_trace_fill_in_int_table_arg_slot(&table_cur,
+                    filtered_cur_arg + 1, words[filtered_cur_arg],
+                    &call_table_args[filtered_cur_arg]);
+                break;
+
+            case MR_TABLE_STEP_FLOAT:
+                success = MR_trace_fill_in_float_table_arg_slot(&table_cur,
+                    filtered_cur_arg + 1, words[filtered_cur_arg],
+                    &call_table_args[filtered_cur_arg]);
+                break;
+
+            case MR_TABLE_STEP_STRING:
+                success = MR_trace_fill_in_string_table_arg_slot(&table_cur,
+                    filtered_cur_arg + 1, words[filtered_cur_arg],
+                    &call_table_args[filtered_cur_arg]);
+                break;
+
+            default:
+                MR_fatal_error("arg not int, float or string after check");
+        }
+
+        if (! success) {
+            /* the error message has already been printed */
+            MR_GC_free(call_table_args);
+            return KEEP_INTERACTING;
+        }
+    }
+
+    if (word_count == filtered_num_inputs) {
+        /*
+        ** The user specified values for all the input arguments,
+        ** so what we print is a single entry, not a table of entries,
+        ** and we don't need to loop over all the entries.
+        */
+
+        MR_trace_cmd_table_print_tip(proc, filtered_num_inputs,
+            call_table_args, table_cur);
+        MR_GC_free(call_table_args);
+        return KEEP_INTERACTING;
+    }
+
+    /*
+    ** The user left the values of some input arguments unspecified,
+    ** so we print a table of entries. Here we print the header.
+    */
+
+    switch (MR_sle_eval_method(proc)) {
+        case MR_EVAL_METHOD_LOOP_CHECK:
+            fprintf(MR_mdb_out, "loopcheck table for ");
+            MR_print_proc_id(MR_mdb_out, proc);
+            fprintf(MR_mdb_out, ":\n");
+            break;
+
+        case MR_EVAL_METHOD_MEMO_STRICT:
+        case MR_EVAL_METHOD_MEMO_FAST_LOOSE:
+        case MR_EVAL_METHOD_MEMO_SPECIFIED:
+            fprintf(MR_mdb_out, "memo table for ");
+            MR_print_proc_id(MR_mdb_out, proc);
+            fprintf(MR_mdb_out, ":\n");
+            break;
+
+        case MR_EVAL_METHOD_MINIMAL_STACK_COPY:
+        case MR_EVAL_METHOD_MINIMAL_OWN_STACKS:
+            fprintf(MR_mdb_out, "minimal model table for ");
+            MR_print_proc_id(MR_mdb_out, proc);
+            fprintf(MR_mdb_out, ":\n");
+            break;
+
+        case MR_EVAL_METHOD_NORMAL:
+        case MR_EVAL_METHOD_TABLE_IO:
+        case MR_EVAL_METHOD_TABLE_IO_DECL:
+        case MR_EVAL_METHOD_TABLE_IO_UNITIZE:
+        case MR_EVAL_METHOD_TABLE_IO_UNITIZE_DECL:
+            MR_fatal_error("MR_trace_cmd_table: bad eval method");
+    }
+
+    /*
+    ** This loop prints the entries in the table.
+    **
+    ** If we knew in advance that the user left (say) two input argument
+    ** positions unspecified, we could use a loop structure such as:
+    **
+    **  for value1 in <values in the trie at node start_node[0]>
+    **      cur_value[1] = value1
+    **      start_node[1] = follow value1 in start_node[0]
+    **      for value2 in <values in the trie at node start_node[1]>
+    **          cur_value[2] = value2
+    **          start_node[2] = follow value2 in start_node[1]
+    **          print <fixed args>, cur_value[1], cur_value[2]
+    **      end for
+    **  end for
+    **
+    ** However, we don't know in advance how many input arguments the user
+    ** left unspecified. We therefore simulate the above with a single
+    ** loop, which can function as any one of the above nested loops.
+    **
+    ** The value of cur_arg controls which one it is simulating at any
+    ** given time. Initially, cur_arg grows as we enter each of the above
+    ** loops one after another, at each stage recording the set of values
+    ** in the current trie node in the values array of the relevant
+    ** argument.
+    **
+    ** We number the input arguments from 0 to filtered_num_inputs-1.
+    ** When cur_arg becomes equal to filtered_num_inputs, this means that
+    ** we have values for all the tabled input arguments, so we print the
+    ** corresponding call table entry. We then initiate backtracking:
+    ** we decrement cur_arg to get the next value of the last argument.
+    ** We also do this whenever we run out of values in any trie.
+    **
+    ** We stop when we are about to backtrack out of the outermost loop.
+    */
+
+    cur_arg = word_count;
+    num_tips = 0;
+    for (;;) {
+        MR_bool no_more;
+        MR_bool start_backtrack;
+
+        switch (call_table_args[cur_arg].MR_cta_step) {
+            case MR_TABLE_STEP_INT:
+                no_more = MR_update_int_table_arg_slot(&table_cur,
+                    &call_table_args[cur_arg]);
+                break;
+
+            case MR_TABLE_STEP_FLOAT:
+                no_more = MR_update_float_table_arg_slot(&table_cur,
+                    &call_table_args[cur_arg]);
+                break;
+
+            case MR_TABLE_STEP_STRING:
+                no_more = MR_update_string_table_arg_slot(&table_cur,
+                    &call_table_args[cur_arg]);
+                break;
+
+            default:
+                MR_fatal_error("arg not int, float or string after check");
+        }
+
+        if (no_more) {
+            /*
+            ** There aren't any more values in the current trie
+            ** of input argument cur_arg.
+            */
+
+            start_backtrack = MR_TRUE;
+        } else {
+            /*
+            ** There is at least one more value in the current trie
+            ** of input argument cur_arg, so go on to the next trie
+            ** (if there is one).
+            */
+
+            cur_arg++;
+
+            if (cur_arg >= filtered_num_inputs) {
+                MR_trace_cmd_table_print_tip(proc, filtered_num_inputs,
+                    call_table_args, table_cur);
+                num_tips++;
+                start_backtrack = MR_TRUE;
+            } else {
+                start_backtrack = MR_FALSE;
+            }
+        }
+
+        if (start_backtrack) {
+            cur_arg--;
+            table_cur = call_table_args[cur_arg].MR_cta_start_node;
+
+            if (cur_arg < word_count) {
+                break;
+            }
+        }
+    }
+
+    fprintf(MR_mdb_out, "end of table (%d %s)\n",
+        num_tips, (num_tips == 1 ? "entry" : "entries"));
+    MR_GC_free(call_table_args);
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_type_ctor(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    const char      *module_name;
+    const char      *name;
+    int             arity;
+    MR_bool         print_rep;
+    MR_bool         print_functors;
+    MR_TypeCtorInfo type_ctor_info;
+
+    MR_do_init_modules_type_tables();
+
+    print_rep = MR_FALSE;
+    print_functors = MR_FALSE;
+    if (! MR_trace_options_type_ctor(&print_rep, &print_functors,
+        &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 4 &&
+        MR_trace_is_natural_number(words[3], &arity))
+    {
+        module_name = words[1];
+        name = words[2];
+        type_ctor_info = MR_lookup_type_ctor_info(module_name, name, arity);
+        if (type_ctor_info != NULL) {
+            MR_print_type_ctor_info(MR_mdb_out, type_ctor_info, print_rep,
+                print_functors);
+        } else {
+            fprintf(MR_mdb_out, "there is no such type constructor\n");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_class_decl(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    const char              *module_name;
+    const char              *name;
+    int                     arity;
+    MR_bool                 print_methods;
+    MR_bool                 print_instances;
+    MR_TypeClassDeclInfo    *type_class_decl_info;
+
+    MR_do_init_modules_type_tables();
+
+    print_methods = MR_FALSE;
+    print_instances = MR_FALSE;
+    if (! MR_trace_options_class_decl(&print_methods, &print_instances,
+        &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 4 &&
+        MR_trace_is_natural_number(words[3], &arity))
+    {
+        module_name = words[1];
+        name = words[2];
+        type_class_decl_info = MR_lookup_type_class_decl_info(module_name,
+            name, arity);
+        if (type_class_decl_info != NULL) {
+            MR_print_class_decl_info(MR_mdb_out, type_class_decl_info,
+                print_methods, print_instances);
+        } else {
+            fprintf(MR_mdb_out, "there is no such type class\n");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_all_type_ctors(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_bool         print_rep;
+    MR_bool         print_functors;
+    MR_Dlist        *list;
+    MR_Dlist        *element_ptr;
+    MR_TypeCtorInfo type_ctor_info;
+    const char      *module_name;
+    int             count;
+
+    MR_do_init_modules_type_tables();
+
+    print_rep = MR_FALSE;
+    print_functors = MR_FALSE;
+    if (! MR_trace_options_type_ctor(&print_rep, &print_functors,
+        &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 1 || word_count == 2) {
+        if (word_count == 2) {
+            module_name = words[1];
+        } else {
+            module_name = NULL;
+        }
+
+        list = MR_all_type_ctor_infos(NULL);
+        count = 0;
+        MR_for_dlist(element_ptr, list) {
+            type_ctor_info = (MR_TypeCtorInfo) MR_dlist_data(element_ptr);
+            if (module_name != NULL && strcmp(module_name,
+                type_ctor_info->MR_type_ctor_module_name) != 0)
+            {
+                continue;
+            }
+
+            if (count > 0) {
+                fprintf(MR_mdb_out, "\n");
+            }
+            MR_print_type_ctor_info(MR_mdb_out, type_ctor_info, print_rep,
+                print_functors);
+            count++;
+        }
+
+        fprintf(MR_mdb_out, "\nnumber of type constructors ");
+        if (module_name == NULL) {
+            fprintf(MR_mdb_out, "in the program: %d\n", count);
+        } else {
+            fprintf(MR_mdb_out, "in module %s: %d\n", module_name, count);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_all_class_decls(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_bool                 print_methods;
+    MR_bool                 print_instances;
+    MR_Dlist                *list;
+    MR_Dlist                *element_ptr;
+    MR_TypeClassDeclInfo    *type_class_decl_info;
+    const char              *module_name;
+    int                     count;
+
+    MR_do_init_modules_type_tables();
+
+    print_methods = MR_FALSE;
+    print_instances = MR_FALSE;
+    if (! MR_trace_options_class_decl(&print_methods, &print_instances,
+        &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 1 || word_count == 2) {
+        if (word_count == 2) {
+            module_name = words[1];
+        } else {
+            module_name = NULL;
+        }
+        list = MR_all_type_class_decl_infos(NULL);
+        count = 0;
+        MR_for_dlist(element_ptr, list) {
+            type_class_decl_info = (MR_TypeClassDeclInfo *)
+                MR_dlist_data(element_ptr);
+            if (module_name != NULL && strcmp(module_name,
+                type_class_decl_info->MR_tcd_info_decl->
+                MR_tc_decl_id->MR_tc_id_module_name) != 0)
+            {
+                continue;
+            }
+
+            if (count > 0) {
+                fprintf(MR_mdb_out, "\n");
+            }
+            MR_print_class_decl_info(MR_mdb_out, type_class_decl_info,
+                print_methods, print_instances);
+            count++;
+        }
+
+        fprintf(MR_mdb_out, "\nnumber of type classes ");
+        if (module_name == NULL) {
+            fprintf(MR_mdb_out, "in the program: %d\n", count);
+        } else {
+            fprintf(MR_mdb_out, "in module %s: %d\n", module_name, count);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_all_procedures(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    const char      *filename;
+    MR_bool         separate;
+    MR_bool         uci;
+    FILE            *fp;
+    char            *module;
+
+    MR_register_all_modules_and_procs(MR_mdb_out, MR_TRUE);
+
+    separate = MR_FALSE;
+    uci = MR_FALSE;
+    module = NULL;
+    if (! MR_trace_options_all_procedures(&separate, &uci, &module,
+        &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 2) {
+        filename = words[1];
+        fp = fopen(filename, "w");
+        if (fp == NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: error opening `%s': %s.\n",
+                filename, strerror(errno));
+            return KEEP_INTERACTING;
+        }
+
+        MR_dump_module_tables(fp, separate, uci, module);
+        if (fclose(fp) != 0) {
+            fprintf(MR_mdb_err, "mdb: error writing to `%s': %s.\n",
+                filename, strerror(errno));
+            return KEEP_INTERACTING;
+        } else {
+            fprintf(MR_mdb_out, "mdb: wrote table to `%s'.\n", filename);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_ambiguity(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    const char      *filename;
+    FILE            *fp;
+    int             i;
+
+    filename = NULL;
+    if (! MR_trace_options_ambiguity(&filename, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else {
+        MR_register_all_modules_and_procs(MR_mdb_out, MR_TRUE);
+
+        if (filename == NULL) {
+            fp = MR_mdb_out;
+        } else {
+            fp = fopen(filename, "w");
+            if (fp == NULL) {
+                fflush(MR_mdb_out);
+                fprintf(MR_mdb_err, "mdb: error opening `%s': %s.\n",
+                    filename, strerror(errno));
+                return KEEP_INTERACTING;
+            }
+        }
+
+        /*
+        ** The words on the command line after the command name and the already
+        ** processed options are a list of modules names. If this list is not
+        ** empty, then we consider only the modules named here when looking for
+        ** ambiguities.
+        */
+
+        MR_print_ambiguities(fp, &words[1], word_count - 1);
+
+        if (filename != NULL) {
+            fprintf(MR_mdb_out, "mdb: wrote report to `%s'.\n", filename);
+            fclose(fp);
+        }
+    }
+
+    return KEEP_INTERACTING;
+}
+
+/****************************************************************************/
+
+static void
+MR_trace_cmd_nondet_stack_2(MR_Event_Info *event_info, MR_bool detailed,
+    int frame_limit, int line_limit)
+{
+    const MR_Label_Layout   *layout;
+    MR_Word                 *saved_regs;
+
+    layout = event_info->MR_event_sll;
+    saved_regs = event_info->MR_saved_regs;
+
+    MR_trace_init_modules();
+    if (detailed) {
+        int saved_level;
+
+        saved_level = MR_trace_current_level();
+        MR_dump_nondet_stack_from_layout(MR_mdb_out, NULL, frame_limit,
+            line_limit, MR_saved_maxfr(saved_regs), layout,
+            MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs));
+        MR_trace_set_level(saved_level, MR_print_optionals);
+    } else {
+        MR_dump_nondet_stack(MR_mdb_out, NULL, frame_limit, line_limit,
+            MR_saved_maxfr(saved_regs));
+    }
+}
+
+static const MR_Proc_Layout *
+MR_find_single_matching_proc(MR_Proc_Spec *spec, MR_bool verbose)
+{
+    MR_Matches_Info     matches;
+    int                 n;
+    int                 i;
+
+    MR_register_all_modules_and_procs(MR_mdb_out, verbose);
+    matches = MR_search_for_matching_procedures(spec);
+    if (matches.match_proc_next == 0) {
+        fflush(MR_mdb_out);
+        fprintf(MR_mdb_err, "mdb: there is no such procedure.\n");
+        return NULL;
+    } else if (matches.match_proc_next == 1) {
+        return matches.match_procs[0];
+    } else {
+        char    buf[100];
+        char    *line2;
+
+        fflush(MR_mdb_out);
+        fprintf(MR_mdb_err, "Ambiguous procedure specification. "
+            "The matches are:\n");
+        for (i = 0; i < matches.match_proc_next; i++) {
+            fprintf(MR_mdb_out, "%d: ", i);
+            MR_print_proc_id_and_nl(MR_mdb_out, matches.match_procs[i]);
+        }
+
+        sprintf(buf, "\nWhich procedure's table do you want to print (0-%d)? ",
+            matches.match_proc_next - 1);
+        line2 = MR_trace_getline(buf, MR_mdb_in, MR_mdb_out);
+        n = -1;
+        if (line2 == NULL || !MR_trace_is_natural_number(line2, &n)) {
+            n = -1;
+            fprintf(MR_mdb_out, "none of them\n");
+        } else if (n < 0 || n >= matches.match_proc_next) {
+            n = -1;
+            fprintf(MR_mdb_out, "invalid choice\n");
+        }
+
+        if (line2 != NULL) {
+            MR_free(line2);
+        }
+
+        if (n >= 0) {
+            return matches.match_procs[n];
+        } else {
+            return NULL;
+        }
+    }
+}
+
+static MR_bool
+MR_trace_fill_in_int_table_arg_slot(MR_TrieNode *table_cur_ptr,
+    int arg_num, MR_ConstString given_arg,
+    MR_Call_Table_Arg *call_table_arg_ptr)
+{
+    MR_Integer  n;
+    MR_TrieNode table_next;
+
+    if (! MR_trace_is_integer(given_arg, &n)) {
+        fprintf(MR_mdb_out, "argument %d is not an integer.\n", arg_num);
+        return MR_FALSE;
+    }
+
+    table_next = MR_int_hash_lookup(*table_cur_ptr, n);
+    if (table_next == NULL) {
+        fprintf(MR_mdb_out,
+            "call table does not contain %" MR_INTEGER_LENGTH_MODIFIER "d"
+            " in argument position %d.\n", n, arg_num);
+        return MR_FALSE;
+    }
+
+    call_table_arg_ptr->MR_cta_start_node = *table_cur_ptr;
+    call_table_arg_ptr->MR_cta_valid = MR_TRUE;
+    call_table_arg_ptr->MR_cta_int_values = NULL;
+    call_table_arg_ptr->MR_cta_int_value_next = -1;
+    call_table_arg_ptr->MR_cta_int_cur_index = -1;
+    call_table_arg_ptr->MR_cta_int_cur_value = n;
+    *table_cur_ptr = table_next;
+
+    return MR_TRUE;
+}
+
+static MR_bool
+MR_trace_fill_in_float_table_arg_slot(MR_TrieNode *table_cur_ptr,
+    int arg_num, MR_ConstString given_arg,
+    MR_Call_Table_Arg *call_table_arg_ptr)
+{
+    MR_Float    f;
+    MR_TrieNode table_next;
+
+    if (! MR_trace_is_float(given_arg, &f)) {
+        fprintf(MR_mdb_out, "argument %d is not a float.\n", arg_num);
+        return MR_FALSE;
+    }
+
+    table_next = MR_float_hash_lookup(*table_cur_ptr, f);
+    if (table_next == NULL) {
+        fprintf(MR_mdb_out,
+            "call table does not contain %f in argument position %d.\n",
+            f, arg_num);
+        return MR_FALSE;
+    }
+
+    call_table_arg_ptr->MR_cta_start_node = *table_cur_ptr;
+    call_table_arg_ptr->MR_cta_valid = MR_TRUE;
+    call_table_arg_ptr->MR_cta_float_values = NULL;
+    call_table_arg_ptr->MR_cta_float_value_next = -1;
+    call_table_arg_ptr->MR_cta_float_cur_index = -1;
+    call_table_arg_ptr->MR_cta_float_cur_value = f;
+    *table_cur_ptr = table_next;
+
+    return MR_TRUE;
+}
+
+static MR_bool
+MR_trace_fill_in_string_table_arg_slot(MR_TrieNode *table_cur_ptr,
+    int arg_num, MR_ConstString given_arg,
+    MR_Call_Table_Arg *call_table_arg_ptr)
+{
+    MR_ConstString  s;
+    MR_TrieNode table_next;
+
+    s = given_arg;
+
+    table_next = MR_string_hash_lookup(*table_cur_ptr, s);
+    if (table_next == NULL) {
+        fprintf(MR_mdb_out,
+            "call table does not contain %s in argument position %d.\n",
+            s, arg_num);
+        return MR_FALSE;
+    }
+
+    call_table_arg_ptr->MR_cta_start_node = *table_cur_ptr;
+    call_table_arg_ptr->MR_cta_valid = MR_TRUE;
+    call_table_arg_ptr->MR_cta_string_values = NULL;
+    call_table_arg_ptr->MR_cta_string_value_next = -1;
+    call_table_arg_ptr->MR_cta_string_cur_index = -1;
+    call_table_arg_ptr->MR_cta_string_cur_value = s;
+    *table_cur_ptr = table_next;
+
+    return MR_TRUE;
+}
+
+static MR_bool
+MR_update_int_table_arg_slot(MR_TrieNode *table_cur_ptr,
+    MR_Call_Table_Arg *call_table_arg_ptr)
+{
+    MR_TrieNode table_next;
+    MR_Integer  *values;
+    int         value_next;
+
+    if (call_table_arg_ptr->MR_cta_valid
+        && call_table_arg_ptr->MR_cta_int_values != NULL)
+    {
+        call_table_arg_ptr->MR_cta_int_cur_index++;
+    } else {
+        if (! MR_get_int_hash_table_contents(*table_cur_ptr,
+            &values, &value_next))
+        {
+            /* there are no values in this trie node */
+            call_table_arg_ptr->MR_cta_valid = MR_FALSE;
+            return MR_TRUE;
+        }
+
+        call_table_arg_ptr->MR_cta_start_node = *table_cur_ptr;
+        call_table_arg_ptr->MR_cta_valid = MR_TRUE;
+        call_table_arg_ptr->MR_cta_int_values = values;
+        call_table_arg_ptr->MR_cta_int_value_next = value_next;
+        call_table_arg_ptr->MR_cta_int_cur_index = 0;
+    }
+
+    if (call_table_arg_ptr->MR_cta_int_cur_index
+        >= call_table_arg_ptr->MR_cta_int_value_next)
+    {
+        /* we have already returned all the values in this trie node */
+        call_table_arg_ptr->MR_cta_valid = MR_FALSE;
+        return MR_TRUE;
+    }
+
+    call_table_arg_ptr->MR_cta_int_cur_value =
+        call_table_arg_ptr->MR_cta_int_values[
+            call_table_arg_ptr->MR_cta_int_cur_index];
+
+    table_next = MR_int_hash_lookup(call_table_arg_ptr->MR_cta_start_node,
+        call_table_arg_ptr->MR_cta_int_cur_value);
+
+    if (table_next == NULL) {
+        MR_fatal_error("MR_update_int_table_arg_slot: bad lookup");
+    }
+
+    *table_cur_ptr = table_next;
+    return MR_FALSE;
+}
+
+static MR_bool
+MR_update_float_table_arg_slot(MR_TrieNode *table_cur_ptr,
+    MR_Call_Table_Arg *call_table_arg_ptr)
+{
+    MR_TrieNode table_next;
+    MR_Float    *values;
+    int     value_next;
+
+    if (call_table_arg_ptr->MR_cta_valid
+        && call_table_arg_ptr->MR_cta_float_values != NULL)
+    {
+        call_table_arg_ptr->MR_cta_float_cur_index++;
+    } else {
+        if (! MR_get_float_hash_table_contents(*table_cur_ptr,
+            &values, &value_next))
+        {
+            /* there are no values in this trie node */
+            call_table_arg_ptr->MR_cta_valid = MR_FALSE;
+            return MR_TRUE;
+        }
+
+        call_table_arg_ptr->MR_cta_start_node = *table_cur_ptr;
+        call_table_arg_ptr->MR_cta_valid = MR_TRUE;
+        call_table_arg_ptr->MR_cta_float_values = values;
+        call_table_arg_ptr->MR_cta_float_value_next = value_next;
+        call_table_arg_ptr->MR_cta_float_cur_index = 0;
+    }
+
+    if (call_table_arg_ptr->MR_cta_float_cur_index
+        >= call_table_arg_ptr->MR_cta_float_value_next)
+    {
+        /* we have already returned all the values in this trie node */
+        call_table_arg_ptr->MR_cta_valid = MR_FALSE;
+        return MR_TRUE;
+    }
+
+    call_table_arg_ptr->MR_cta_float_cur_value =
+        call_table_arg_ptr->MR_cta_float_values[
+            call_table_arg_ptr->MR_cta_float_cur_index];
+
+    table_next = MR_float_hash_lookup(call_table_arg_ptr->MR_cta_start_node,
+        call_table_arg_ptr->MR_cta_float_cur_value);
+
+    if (table_next == NULL) {
+        MR_fatal_error("MR_update_float_table_arg_slot: bad lookup");
+    }
+
+    *table_cur_ptr = table_next;
+    return MR_FALSE;
+}
+
+static MR_bool
+MR_update_string_table_arg_slot(MR_TrieNode *table_cur_ptr,
+    MR_Call_Table_Arg *call_table_arg_ptr)
+{
+    MR_TrieNode     table_next;
+    MR_ConstString  *values;
+    int             value_next;
+
+    if (call_table_arg_ptr->MR_cta_valid
+        && call_table_arg_ptr->MR_cta_string_values != NULL)
+    {
+        call_table_arg_ptr->MR_cta_string_cur_index++;
+    } else {
+        if (! MR_get_string_hash_table_contents(*table_cur_ptr,
+            &values, &value_next))
+        {
+            /* there are no values in this trie node */
+            call_table_arg_ptr->MR_cta_valid = MR_FALSE;
+            return MR_TRUE;
+        }
+
+        call_table_arg_ptr->MR_cta_start_node = *table_cur_ptr;
+        call_table_arg_ptr->MR_cta_valid = MR_TRUE;
+        call_table_arg_ptr->MR_cta_string_values = values;
+        call_table_arg_ptr->MR_cta_string_value_next = value_next;
+        call_table_arg_ptr->MR_cta_string_cur_index = 0;
+    }
+
+    if (call_table_arg_ptr->MR_cta_string_cur_index
+        >= call_table_arg_ptr->MR_cta_string_value_next)
+    {
+        /* we have already returned all the values in this trie node */
+        call_table_arg_ptr->MR_cta_valid = MR_FALSE;
+        return MR_TRUE;
+    }
+
+    call_table_arg_ptr->MR_cta_string_cur_value =
+        call_table_arg_ptr->MR_cta_string_values[
+            call_table_arg_ptr->MR_cta_string_cur_index];
+
+    table_next = MR_string_hash_lookup(
+        call_table_arg_ptr->MR_cta_start_node,
+        call_table_arg_ptr->MR_cta_string_cur_value);
+
+    if (table_next == NULL) {
+        MR_fatal_error("MR_update_string_table_arg_slot: bad lookup");
+    }
+
+    *table_cur_ptr = table_next;
+    return MR_FALSE;
+}
+
+static void
+MR_trace_cmd_table_print_tip(const MR_Proc_Layout *proc,
+    int num_filtered_inputs, MR_Call_Table_Arg *call_table_args,
+    MR_TrieNode table)
+{
+    int             i;
+    MR_EvalMethod   eval_method;
+
+    fprintf(MR_mdb_out, "<");
+    for (i = 0; i < num_filtered_inputs; i++) {
+        if (i > 0) {
+            fprintf(MR_mdb_out, ", ");
+        }
+
+        switch (call_table_args[i].MR_cta_step) {
+            case MR_TABLE_STEP_INT:
+                fprintf(MR_mdb_out, "%" MR_INTEGER_LENGTH_MODIFIER "d",
+                    call_table_args[i].MR_cta_int_cur_value);
+                break;
+
+            case MR_TABLE_STEP_FLOAT:
+                fprintf(MR_mdb_out, "%f",
+                    call_table_args[i].MR_cta_float_cur_value);
+                break;
+
+            case MR_TABLE_STEP_STRING:
+                fprintf(MR_mdb_out, "\"%s\"",
+                    call_table_args[i].MR_cta_string_cur_value);
+                break;
+
+            default:
+                MR_fatal_error("arg not int, float or string after check");
+        }
+    }
+
+    fprintf(MR_mdb_out, ">: ");
+
+    eval_method = MR_sle_eval_method(proc);
+    switch (eval_method) {
+        case MR_EVAL_METHOD_MINIMAL_STACK_COPY:
+            {
+                MR_Subgoal  *subgoal;
+                int         subgoal_num;
+
+                fprintf(MR_mdb_out, "trie node %p\n", table);
+                subgoal = table->MR_subgoal;
+                if (subgoal == NULL) {
+                    fprintf(MR_mdb_out, "uninitialized\n");
+                } else {
+                    MR_trace_print_subgoal(proc, subgoal);
+                }
+            }
+            break;
+
+        case MR_EVAL_METHOD_MINIMAL_OWN_STACKS:
+            {
+                MR_GeneratorPtr generator;
+
+                fprintf(MR_mdb_out, "trie node %p\n", table);
+                generator = table->MR_generator;
+                if (generator == NULL) {
+                    fprintf(MR_mdb_out, "uninitialized\n");
+                } else {
+                    MR_trace_print_generator(proc, generator);
+                }
+            }
+            break;
+
+        case MR_EVAL_METHOD_MEMO_STRICT:
+        case MR_EVAL_METHOD_MEMO_FAST_LOOSE:
+        case MR_EVAL_METHOD_MEMO_SPECIFIED:
+            {
+                MR_Determinism  detism;
+
+                detism = proc->MR_sle_detism;
+                if (MR_DETISM_DET_STACK(detism)) {
+                    MR_print_memo_tip(MR_mdb_out, proc, table);
+                } else {
+                    MR_MemoNonRecordPtr record;
+
+                    record = table->MR_memo_non_record;
+                    MR_print_memo_non_record(MR_mdb_out, proc, record);
+                }
+            }
+            break;
+
+        case MR_EVAL_METHOD_LOOP_CHECK:
+            MR_print_loopcheck_tip(MR_mdb_out, proc, table);
+            break;
+
+        case MR_EVAL_METHOD_NORMAL:
+        case MR_EVAL_METHOD_TABLE_IO:
+        case MR_EVAL_METHOD_TABLE_IO_DECL:
+        case MR_EVAL_METHOD_TABLE_IO_UNITIZE:
+        case MR_EVAL_METHOD_TABLE_IO_UNITIZE_DECL:
+            MR_fatal_error("MR_trace_cmd_table_print_tip: bad eval method");
+            break;
+    }
+}
+
+static void
+MR_trace_print_subgoal(const MR_Proc_Layout *proc, MR_Subgoal *subgoal)
+{
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
+    MR_print_subgoal(MR_mdb_out, proc, subgoal);
+#else
+    fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
+#endif
+}
+
+static void
+MR_trace_print_subgoal_debug(const MR_Proc_Layout *proc,
+    MR_SubgoalDebug *subgoal_debug)
+{
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
+    MR_print_subgoal_debug(MR_mdb_out, proc, subgoal_debug);
+#else
+    fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
+#endif
+}
+
+static void
+MR_trace_print_generator(const MR_Proc_Layout *proc, MR_Generator *generator)
+{
+#ifdef  MR_USE_MINIMAL_MODEL_OWN_STACKS
+    MR_print_generator(MR_mdb_out, proc, generator);
+#else
+    fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
+#endif
+}
+
+static void
+MR_trace_print_generator_debug(const MR_Proc_Layout *proc,
+    MR_GenDebug *generator_debug)
+{
+#ifdef  MR_USE_MINIMAL_MODEL_OWN_STACKS
+    MR_print_gen_debug(MR_mdb_out, proc, generator_debug);
+#else
+    fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
+#endif
+}
+
+static void
+MR_trace_print_consumer(const MR_Proc_Layout *proc, MR_Consumer *consumer)
+{
+#if defined(MR_USE_MINIMAL_MODEL_STACK_COPY) \
+        || defined(MR_USE_MINIMAL_MODEL_OWN_STACKS)
+    MR_print_consumer(MR_mdb_out, proc, consumer);
+#else
+    fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
+#endif
+}
+
+static void
+MR_trace_print_consumer_debug(const MR_Proc_Layout *proc,
+    MR_ConsumerDebug *consumer_debug)
+{
+#if defined(MR_USE_MINIMAL_MODEL_STACK_COPY)
+    MR_print_consumer_debug(MR_mdb_out, proc, consumer_debug);
+#elif defined(MR_USE_MINIMAL_MODEL_STACK_COPY)
+    MR_print_cons_debug(MR_mdb_out, proc, consumer_debug);
+#else
+    fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
+#endif
+}
+
+static void
+MR_print_type_ctor_info(FILE *fp, MR_TypeCtorInfo type_ctor_info,
+    MR_bool print_rep, MR_bool print_functors)
+{
+    MR_TypeCtorRep              rep;
+    MR_EnumFunctorDesc          *enum_functor;
+    MR_DuFunctorDesc            *du_functor;
+    MR_MaybeResAddrFunctorDesc  *maybe_res_functor;
+    MR_NotagFunctorDesc         *notag_functor;
+    int                         num_functors;
+    int                         i;
+
+    fprintf(fp, "type constructor %s.%s/%d",
+        type_ctor_info->MR_type_ctor_module_name,
+        type_ctor_info->MR_type_ctor_name,
+        (int) type_ctor_info->MR_type_ctor_arity);
+
+    rep = MR_type_ctor_rep(type_ctor_info);
+    if (print_rep) {
+        fprintf(fp, ": %s\n", MR_ctor_rep_name[MR_GET_ENUM_VALUE(rep)]);
+    } else {
+        fprintf(fp, "\n");
+    }
+
+    if (print_functors) {
+        num_functors = type_ctor_info->MR_type_ctor_num_functors;
+        switch (rep) {
+            case MR_TYPECTOR_REP_ENUM:
+            case MR_TYPECTOR_REP_ENUM_USEREQ:
+                for (i = 0; i < num_functors; i++) {
+                    enum_functor = type_ctor_info->MR_type_ctor_functors.
+                        MR_functors_enum[i];
+                    if (i > 0) {
+                        fprintf(fp, ", ");
+                    }
+                    fprintf(fp, "%s/0", enum_functor->MR_enum_functor_name);
+                }
+                fprintf(fp, "\n");
+                break;
+
+            case MR_TYPECTOR_REP_DU:
+            case MR_TYPECTOR_REP_DU_USEREQ:
+                for (i = 0; i < num_functors; i++) {
+                    du_functor = type_ctor_info->MR_type_ctor_functors.
+                        MR_functors_du[i];
+                    if (i > 0) {
+                        fprintf(fp, ", ");
+                    }
+                    fprintf(fp, "%s/%d", du_functor->MR_du_functor_name,
+                        du_functor-> MR_du_functor_orig_arity);
+                }
+                fprintf(fp, "\n");
+                break;
+
+            case MR_TYPECTOR_REP_RESERVED_ADDR:
+            case MR_TYPECTOR_REP_RESERVED_ADDR_USEREQ:
+                for (i = 0; i < num_functors; i++) {
+                    maybe_res_functor = &type_ctor_info->MR_type_ctor_functors.
+                        MR_functors_res[i];
+                    if (i > 0) {
+                        fprintf(fp, ", ");
+                    }
+                    fprintf(fp, "%s/%d", maybe_res_functor->MR_maybe_res_name,
+                        (int) maybe_res_functor-> MR_maybe_res_arity);
+                }
+                fprintf(fp, "\n");
+                break;
+
+            case MR_TYPECTOR_REP_NOTAG:
+            case MR_TYPECTOR_REP_NOTAG_USEREQ:
+            case MR_TYPECTOR_REP_NOTAG_GROUND:
+            case MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ:
+                notag_functor = type_ctor_info->MR_type_ctor_functors.
+                    MR_functors_notag;
+                fprintf(fp, "%s/1\n", notag_functor->MR_notag_functor_name);
+                break;
+
+            default:
+                break;
+        }
+    }
+}
+
+static void
+MR_print_class_decl_info(FILE *fp, MR_TypeClassDeclInfo *type_class_decl_info,
+    MR_bool print_methods, MR_bool print_instances)
+{
+    MR_TypeClassDecl            type_class_decl;
+    const MR_TypeClassId        *type_class_id;
+    const MR_TypeClassMethod    *method;
+    MR_Instance                 instance;
+    MR_Dlist                    *list;
+    MR_Dlist                    *element_ptr;
+    int                         num_methods;
+    int                         i;
+
+    type_class_decl = type_class_decl_info->MR_tcd_info_decl;
+    type_class_id = type_class_decl->MR_tc_decl_id;
+    fprintf(fp, "type class %s.%s/%d\n",
+        type_class_id->MR_tc_id_module_name,
+        type_class_id->MR_tc_id_name,
+        type_class_id->MR_tc_id_arity);
+
+    if (print_methods) {
+        num_methods = type_class_id->MR_tc_id_num_methods;
+        fprintf(fp, "methods: ");
+
+        for (i = 0; i < num_methods; i++) {
+            if (i > 0) {
+                fprintf(fp, ", ");
+            }
+
+            method = &type_class_id->MR_tc_id_methods[i];
+            if (method->MR_tc_method_pred_func == MR_FUNCTION) {
+                fprintf(fp, "func ");
+            } else {
+                fprintf(fp, "pred ");
+            }
+
+            fprintf(fp, "%s/%d", method->MR_tc_method_name,
+                method->MR_tc_method_arity);
+        }
+
+        fprintf(fp, "\n");
+    }
+
+    if (print_instances) {
+        list = type_class_decl_info->MR_tcd_info_instances;
+        MR_for_dlist (element_ptr, list) {
+            instance = (MR_Instance) MR_dlist_data(element_ptr);
+
+            if (instance->MR_tc_inst_type_class != type_class_decl) {
+                MR_fatal_error("instance/type class mismatch");
+            }
+
+            fprintf(fp, "instance ");
+
+            for (i = 0; i < type_class_id->MR_tc_id_arity; i++) {
+                if (i > 0) {
+                    fprintf(fp, ", ");
+                }
+
+                MR_print_pseudo_type_info(fp,
+                    instance->MR_tc_inst_type_args[i]);
+            }
+
+            fprintf(fp, "\n");
+        }
+    }
+}
+
+static void
+MR_print_pseudo_type_info(FILE *fp, MR_PseudoTypeInfo pseudo)
+{
+    MR_TypeCtorInfo     type_ctor_info;
+    MR_PseudoTypeInfo   *pseudo_args;
+    MR_Integer          tvar_num;
+    int                 arity;
+    int                 i;
+
+    if (MR_PSEUDO_TYPEINFO_IS_VARIABLE(pseudo)) {
+        tvar_num = (MR_Integer) pseudo;
+        fprintf(fp, "T%d", (int) tvar_num);
+    } else {
+        type_ctor_info = MR_PSEUDO_TYPEINFO_GET_TYPE_CTOR_INFO(pseudo);
+        fprintf(fp, "%s.%s",
+            type_ctor_info->MR_type_ctor_module_name,
+            type_ctor_info->MR_type_ctor_name);
+        if (MR_type_ctor_has_variable_arity(type_ctor_info)) {
+            arity = MR_PSEUDO_TYPEINFO_GET_VAR_ARITY_ARITY(pseudo);
+            pseudo_args = (MR_PseudoTypeInfo *)
+                &pseudo->MR_pti_var_arity_arity;
+        } else {
+            arity = type_ctor_info->MR_type_ctor_arity;
+            pseudo_args = (MR_PseudoTypeInfo *) &pseudo->MR_pti_type_ctor_info;
+        }
+
+        if (type_ctor_info->MR_type_ctor_arity > 0) {
+            fprintf(fp, "(");
+            for (i = 1; i <= arity; i++) {
+                if (i > 1) {
+                    fprintf(fp, ", ");
+                }
+
+                MR_print_pseudo_type_info(fp, pseudo_args[i]);
+            }
+            fprintf(fp, ")");
+        }
+    }
+}
+
+/****************************************************************************/
+
+/*
+** It is better to have a single completion where possible,
+** so don't include `-d' here.
+*/
+
+const char *const    MR_trace_nondet_stack_cmd_args[] =
+    { "--detailed", NULL };
+
+const char *const    MR_trace_stats_cmd_args[] =
+    { "procs", "labels", "var_names", "io_tabling", NULL };
+
+/****************************************************************************/
+
+static struct MR_option MR_trace_nondet_stack_opts[] =
+{
+    { "detailed",       MR_no_argument,         NULL,   'd' },
+    { "frame-limit",    MR_required_argument,   NULL,   'f' },
+    { NULL,             MR_no_argument,         NULL,   0   }
+};
+
+static MR_bool
+MR_trace_options_nondet_stack(MR_bool *detailed, int *frame_limit,
+    char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "df:",
+        MR_trace_nondet_stack_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'd':
+                *detailed = MR_TRUE;
+                break;
+
+            case 'f':
+                if (! MR_trace_is_natural_number(MR_optarg, frame_limit)) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+static struct MR_option MR_trace_stats_opts[] =
+{
+    { "file",      MR_required_argument,    NULL,   'f' },
+    { NULL,        MR_no_argument,          NULL,   0   }
+};
+
+static MR_bool
+MR_trace_options_stats(char **filename, char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "f:",
+        MR_trace_stats_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'f':
+                *filename = MR_optarg;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+static struct MR_option MR_trace_type_ctor_opts[] =
+{
+    { "print-rep",      MR_no_argument,     NULL,   'r' },
+    { "print-functors", MR_no_argument,     NULL,   'f' },
+    { NULL,             MR_no_argument,     NULL,   0   }
+};
+
+static MR_bool
+MR_trace_options_type_ctor(MR_bool *print_rep, MR_bool *print_functors,
+    char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "rf",
+        MR_trace_type_ctor_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'f':
+                *print_functors = MR_TRUE;
+                break;
+
+            case 'r':
+                *print_rep = MR_TRUE;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+static struct MR_option MR_trace_class_decl_opts[] =
+{
+    { "print-methods",      MR_no_argument,     NULL,   'm' },
+    { "print-instances",    MR_no_argument,     NULL,   'i' },
+    { NULL,                 MR_no_argument,     NULL,   0   }
+};
+
+static MR_bool
+MR_trace_options_class_decl(MR_bool *print_methods, MR_bool *print_instances,
+    char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "mi",
+        MR_trace_class_decl_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'm':
+                *print_methods = MR_TRUE;
+                break;
+
+            case 'i':
+                *print_instances = MR_TRUE;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+static struct MR_option MR_trace_all_procedures_opts[] =
+{
+    { "separate",   MR_no_argument,         NULL,   's' },
+    { "uci",        MR_no_argument,         NULL,   'u' },
+    { "module",     MR_required_argument,   NULL,   'm' },
+    { NULL,         MR_no_argument,         NULL,   0   }
+};
+
+static MR_bool
+MR_trace_options_all_procedures(MR_bool *separate, MR_bool *uci, char **module,
+    char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "sum:",
+        MR_trace_all_procedures_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 's':
+                *separate = MR_TRUE;
+                break;
+
+            case 'u':
+                *uci = MR_TRUE;
+                break;
+
+            case 'm':
+                *module = MR_optarg;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+static struct MR_option MR_trace_ambiguity_opts[] =
+{
+    { "outputfile", MR_required_argument,   NULL,   'o' },
+    { NULL,         MR_no_argument,         NULL,   0   }
+};
+
+static MR_bool
+MR_trace_options_ambiguity(const char **outfile,
+    char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "o:",
+        MR_trace_ambiguity_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'o':
+                *outfile = MR_optarg;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
Index: trace/mercury_trace_cmd_developer.h
===================================================================
RCS file: trace/mercury_trace_cmd_developer.h
diff -N trace/mercury_trace_cmd_developer.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_developer.h	3 Apr 2006 11:26:29 -0000
@@ -0,0 +1,40 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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.
+*/
+
+#include "mercury_imp.h"
+
+#include "mercury_trace_cmds.h"
+
+extern  MR_TraceCmdFunc     MR_trace_cmd_var_details;
+extern  MR_TraceCmdFunc     MR_trace_cmd_term_size;
+extern  MR_TraceCmdFunc     MR_trace_cmd_flag;
+extern  MR_TraceCmdFunc     MR_trace_cmd_subgoal;
+extern  MR_TraceCmdFunc     MR_trace_cmd_consumer;
+extern  MR_TraceCmdFunc     MR_trace_cmd_gen_stack;
+extern  MR_TraceCmdFunc     MR_trace_cmd_cut_stack;
+extern  MR_TraceCmdFunc     MR_trace_cmd_pneg_stack;
+extern  MR_TraceCmdFunc     MR_trace_cmd_mm_stacks;
+extern  MR_TraceCmdFunc     MR_trace_cmd_nondet_stack;
+extern  MR_TraceCmdFunc     MR_trace_cmd_stack_regs;
+extern  MR_TraceCmdFunc     MR_trace_cmd_all_regs;
+extern  MR_TraceCmdFunc     MR_trace_cmd_debug_vars;
+extern  MR_TraceCmdFunc     MR_trace_cmd_stats;
+extern  MR_TraceCmdFunc     MR_trace_cmd_print_optionals;
+extern  MR_TraceCmdFunc     MR_trace_cmd_unhide_events;
+extern  MR_TraceCmdFunc     MR_trace_cmd_table;
+extern  MR_TraceCmdFunc     MR_trace_cmd_type_ctor;
+extern  MR_TraceCmdFunc     MR_trace_cmd_class_decl;
+extern  MR_TraceCmdFunc     MR_trace_cmd_all_type_ctors;
+extern  MR_TraceCmdFunc     MR_trace_cmd_all_class_decls;
+extern  MR_TraceCmdFunc     MR_trace_cmd_all_procedures;
+extern  MR_TraceCmdFunc     MR_trace_cmd_ambiguity;
+extern  MR_TraceCmdFunc     MR_trace_cmd_dice;
+
+extern  const char *const   MR_trace_nondet_stack_cmd_args[];
+extern  const char *const   MR_trace_stats_cmd_args[];
Index: trace/mercury_trace_cmd_exp.c
===================================================================
RCS file: trace/mercury_trace_cmd_exp.c
diff -N trace/mercury_trace_cmd_exp.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_exp.c	3 Apr 2006 12:50:42 -0000
@@ -0,0 +1,363 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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 module implements the mdb commands in the "exp" category.
+**
+** The structure of these files is:
+**
+** - all the #includes
+** - local macros and declarations of local static functions
+** - one function for each command in the category
+** - any auxiliary functions
+** - any command argument strings
+** - option processing functions.
+*/
+
+#include "mercury_std.h"
+#include "mercury_getopt.h"
+
+#include "mercury_trace_internal.h"
+#include "mercury_trace_cmds.h"
+#include "mercury_trace_cmd_exp.h"
+#include "mercury_trace_cmd_parameter.h"
+#include "mercury_trace_util.h"
+
+#include "mdbcomp.slice_and_dice.mh"
+
+#include <stdio.h>
+
+/****************************************************************************/
+
+/*
+** The default number of lines to display for a dice.
+*/
+
+#define MR_DEFAULT_DICE_LINES   50
+
+static  void        MR_trace_print_dice(char *pass_trace_counts_file,
+                        char *fail_trace_counts_file, char *sort_str,
+                        int number_of_lines, char *out_str, char *module);
+
+static  MR_bool     MR_trace_options_dice(char **pass_trace_counts_file,
+                        char **fail_trace_count_file, char **sort_str,
+                        int *number_of_lines, char **out_file, char **module,
+                        char ***words, int *word_count);
+
+/****************************************************************************/
+
+MR_Next
+MR_trace_cmd_histogram_all(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+#ifdef  MR_TRACE_HISTOGRAM
+
+    if (word_count == 2) {
+        FILE    *fp;
+
+        fp = fopen(words[1], "w");
+        if (fp == NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: cannot open file `%s' for output: %s.\n",
+                words[1], strerror(errno));
+        } else {
+            MR_trace_print_histogram(fp, "All-inclusive",
+                MR_trace_histogram_all,
+                MR_trace_histogram_hwm);
+            if (fclose(fp) != 0) {
+                fflush(MR_mdb_out);
+                fprintf(MR_mdb_err, "mdb: error closing file `%s': %s.\n",
+                    words[1], strerror(errno));
+            }
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+#else   /* MR_TRACE_HISTOGRAM */
+
+    fprintf(MR_mdb_out, "mdb: the `histogram_all' command is available "
+        "only when histogram gathering is enabled.\n");
+
+#endif  /* MR_TRACE_HISTOGRAM */
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_histogram_exp(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+#ifdef  MR_TRACE_HISTOGRAM
+
+    if (word_count == 2) {
+        FILE    *fp;
+
+        fp = fopen(words[1], "w");
+        if (fp == NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: cannot open file `%s' for output: %s.\n",
+                words[1], strerror(errno));
+        } else {
+            MR_trace_print_histogram(fp, "Experimental",
+                MR_trace_histogram_exp,
+                MR_trace_histogram_hwm);
+            if (fclose(fp) != 0) {
+                fflush(MR_mdb_out);
+                fprintf(MR_mdb_err, "mdb: error closing file `%s': %s.\n",
+                    words[1], strerror(errno));
+            }
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+#else   /* MR_TRACE_HISTOGRAM */
+
+    fprintf(MR_mdb_out, "mdb: the `histogram_exp' command is available "
+        "only when histogram gathering is enabled.\n");
+
+#endif  /* MR_TRACE_HISTOGRAM */
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_clear_histogram(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+#ifdef  MR_TRACE_HISTOGRAM
+
+    if (word_count == 1) {
+        int i;
+
+        for (i = 0; i <= MR_trace_histogram_hwm; i++) {
+            MR_trace_histogram_exp[i] = 0;
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+#else   /* MR_TRACE_HISTOGRAM */
+
+    fprintf(MR_mdb_out, "mdb: the `clear_histogram' command is available "
+        "only when histogram gathering is enabled.\n");
+
+#endif  /* MR_TRACE_HISTOGRAM */
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_dice(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    char    *pass_trace_counts_file;
+    char    *fail_trace_counts_file;
+    char    *sort_str;
+    char    *out_file;
+    char    *module;
+    int     number_of_lines;
+
+    sort_str = NULL;
+    out_file = NULL;
+    module = NULL;
+    number_of_lines = MR_DEFAULT_DICE_LINES;
+
+    pass_trace_counts_file = MR_dice_pass_trace_counts_file;
+    fail_trace_counts_file = MR_dice_fail_trace_counts_file;
+
+    if (! MR_trace_options_dice(&pass_trace_counts_file,
+        &fail_trace_counts_file, &sort_str, &number_of_lines, &out_file,
+        &module, &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 1) {
+        if (pass_trace_counts_file == NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: No passing trace counts file specified."
+                "\nmdb: Specify one with the -p option or using the `set' "
+                "command.\n");
+        } else if (fail_trace_counts_file == NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: No failing trace counts file specified."
+                "\nmdb: Specify one with the -f option or using the `set' "
+                "command.\n");
+        } else {
+            if (sort_str == NULL) {
+                sort_str = MR_copy_string("");
+            }
+
+            if (module == NULL) {
+                module = MR_copy_string("");
+            }
+            MR_trace_print_dice(pass_trace_counts_file, fail_trace_counts_file,
+                sort_str, number_of_lines, out_file, module);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    if (out_file != NULL) {
+        free(out_file);
+    }
+
+    if (sort_str != NULL) {
+        free(sort_str);
+    }
+
+    if (module != NULL) {
+        free(module);
+    }
+
+    return KEEP_INTERACTING;
+}
+
+/****************************************************************************/
+
+static  void
+MR_trace_print_dice(char *pass_trace_counts_file,
+    char *fail_trace_count_file, char *sort_str, int number_of_lines,
+    char *out_file, char *module)
+{
+    MR_String   dice;
+    MR_String   problem;
+    MR_String   aligned_pass_trace_counts_file;
+    MR_String   aligned_fail_trace_count_file;
+    MR_String   aligned_sort_str;
+    MR_String   aligned_module;
+    FILE        *fp;
+
+    MR_TRACE_USE_HP(
+        MR_make_aligned_string(aligned_pass_trace_counts_file,
+            (MR_String) pass_trace_counts_file);
+        MR_make_aligned_string(aligned_fail_trace_count_file,
+            (MR_String) fail_trace_count_file);
+        MR_make_aligned_string(aligned_sort_str, (MR_String) sort_str);
+        if (module == NULL) {
+            MR_make_aligned_string(aligned_module, (MR_String) "");
+        } else {
+            MR_make_aligned_string(aligned_module, (MR_String) module);
+        }
+    );
+
+    MR_TRACE_CALL_MERCURY(
+        MR_MDB_read_dice_to_string(aligned_pass_trace_counts_file,
+            aligned_fail_trace_count_file, aligned_sort_str,
+            number_of_lines, aligned_module, &dice, &problem);
+    );
+
+    /* The string in dice is a sequence of complete lines */
+    if (MR_streq(problem, "")) {
+        if (out_file == NULL) {
+            fprintf(MR_mdb_out, "%s", dice);
+        } else {
+            fp = fopen(out_file, "w");
+            if (fp != NULL) {
+                fprintf(fp, "%s", dice);
+                if (fclose(fp) != 0) {
+                    fflush(MR_mdb_out);
+                    fprintf(MR_mdb_err, "mdb: Error closing file `%s': %s\n",
+                        out_file, strerror(errno));
+                }
+            } else {
+                fflush(MR_mdb_out);
+                fprintf(MR_mdb_err, "mdb: Error opening file `%s': %s\n",
+                    out_file, strerror(errno));
+            }
+        }
+    } else {
+        fflush(MR_mdb_out);
+        fprintf(MR_mdb_err, "mdb: %s\n", problem);
+    }
+}
+
+/****************************************************************************/
+
+static struct MR_option MR_trace_dice_opts[] =
+{
+    { "pass-trace-counts",      MR_required_argument,   NULL,   'p' },
+    { "pass-trace-count",       MR_required_argument,   NULL,   'p' },
+    { "fail-trace-counts",      MR_required_argument,   NULL,   'f' },
+    { "fail-trace-count",       MR_required_argument,   NULL,   'f' },
+    { "sort",                   MR_required_argument,   NULL,   's' },
+    { "top",                    MR_required_argument,   NULL,   'n' },
+    { "output-to-file",         MR_required_argument,   NULL,   'o' },
+    { "module",                 MR_required_argument,   NULL,   'm' },
+    { NULL,                     MR_no_argument,         NULL,   0   }
+};
+
+static MR_bool
+MR_trace_options_dice(char **pass_trace_counts_file,
+    char **fail_trace_counts_file, char **sort_str, int *n, char **out_file,
+    char **module, char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "p:f:s:n:o:m:",
+        MR_trace_dice_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'p':
+                /*
+                ** Don't free *pass_trace_counts_file even if non-NULL,
+                ** since its initial value comes from a global variable,
+                ** and thus will still be used after the dice command.
+                ** The waste of not freeing of the string allocated by
+                ** MR_copy_string if this option is duplicated can be
+                ** easily lived with.
+                */
+
+                *pass_trace_counts_file = MR_copy_string(MR_optarg);
+                break;
+
+            case 'f':
+                /*
+                ** Don't free *fail_trace_counts_file even if non-NULL,
+                ** since its initial value comes from a global variable,
+                ** and thus will still be used after the dice command.
+                ** The waste of not freeing of the string allocated by
+                ** MR_copy_string if this option is duplicated can be
+                ** easily lived with.
+                */
+
+                *fail_trace_counts_file = MR_copy_string(MR_optarg);
+                break;
+
+            case 's':
+                *sort_str = MR_copy_string(MR_optarg);
+                break;
+
+            case 'n':
+                if (! MR_trace_is_natural_number(MR_optarg, n)) {
+                    MR_trace_usage_cur_cmd();
+                    return MR_FALSE;
+                }
+                break;
+
+            case 'o':
+                *out_file = MR_copy_string(MR_optarg);
+                break;
+
+            case 'm':
+                *module = MR_copy_string(MR_optarg);
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
Index: trace/mercury_trace_cmd_exp.h
===================================================================
RCS file: trace/mercury_trace_cmd_exp.h
diff -N trace/mercury_trace_cmd_exp.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_exp.h	3 Apr 2006 11:16:03 -0000
@@ -0,0 +1,17 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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.
+*/
+
+#include "mercury_imp.h"
+
+#include "mercury_trace_cmds.h"
+
+extern  MR_TraceCmdFunc     MR_trace_cmd_histogram_all;
+extern  MR_TraceCmdFunc     MR_trace_cmd_histogram_exp;
+extern  MR_TraceCmdFunc     MR_trace_cmd_clear_histogram;
+extern  MR_TraceCmdFunc     MR_trace_cmd_dice;
Index: trace/mercury_trace_cmd_forward.c
===================================================================
RCS file: trace/mercury_trace_cmd_forward.c
diff -N trace/mercury_trace_cmd_forward.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_forward.c	3 Apr 2006 12:50:48 -0000
@@ -0,0 +1,443 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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 module implements the mdb commands in the "forward" category.
+**
+** The structure of these files is:
+**
+** - all the #includes
+** - local macros and declarations of local static functions
+** - one function for each command in the category
+** - any auxiliary functions
+** - any command argument strings
+** - option processing functions.
+*/
+
+#include "mercury_std.h"
+#include "mercury_getopt.h"
+
+#include "mercury_trace_internal.h"
+#include "mercury_trace_cmds.h"
+#include "mercury_trace_cmd_forward.h"
+#include "mercury_trace_cmd_parameter.h"
+#include "mercury_trace_util.h"
+
+/****************************************************************************/
+
+static  MR_bool     MR_trace_options_movement_cmd(MR_Trace_Cmd_Info *cmd,
+                        char ***words, int *word_count);
+
+/****************************************************************************/
+
+MR_Next
+MR_trace_cmd_step(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int n;
+
+    cmd->MR_trace_strict = MR_FALSE;
+    cmd->MR_trace_print_level = MR_default_print_level;
+    MR_init_trace_check_integrity(cmd);
+    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 1) {
+        cmd->MR_trace_cmd = MR_CMD_GOTO;
+        cmd->MR_trace_stop_event = MR_trace_event_number + 1;
+        return STOP_INTERACTING;
+    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+        cmd->MR_trace_cmd = MR_CMD_GOTO;
+        cmd->MR_trace_stop_event = MR_trace_event_number + n;
+        return STOP_INTERACTING;
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_goto(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_Unsigned n;
+
+    cmd->MR_trace_strict = MR_TRUE;
+    cmd->MR_trace_print_level = MR_default_print_level;
+    MR_init_trace_check_integrity(cmd);
+    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 2 && MR_trace_is_unsigned(words[1], &n)) {
+        if (MR_trace_event_number < n) {
+            cmd->MR_trace_cmd = MR_CMD_GOTO;
+            cmd->MR_trace_stop_event = n;
+            return STOP_INTERACTING;
+        } else {
+            /* XXX this message is misleading */
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "The debugger cannot go to a past event.\n");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_next(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_Unsigned depth;
+    int         stop_depth;
+    int         n;
+
+    depth = event_info->MR_call_depth;
+    cmd->MR_trace_strict = MR_TRUE;
+    cmd->MR_trace_print_level = MR_default_print_level;
+    MR_init_trace_check_integrity(cmd);
+    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+        return KEEP_INTERACTING;
+    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+        stop_depth = depth - n;
+    } else if (word_count == 1) {
+        stop_depth = depth;
+    } else {
+        MR_trace_usage_cur_cmd();
+        return KEEP_INTERACTING;
+    }
+
+    if (depth == stop_depth && MR_port_is_final(event_info->MR_trace_port)) {
+        MR_trace_do_noop();
+    } else {
+        cmd->MR_trace_cmd = MR_CMD_NEXT;
+        cmd->MR_trace_stop_depth = stop_depth;
+        return STOP_INTERACTING;
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_finish(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_Unsigned depth;
+    int         stop_depth;
+    int         n;
+
+    depth = event_info->MR_call_depth;
+    cmd->MR_trace_strict = MR_TRUE;
+    cmd->MR_trace_print_level = MR_default_print_level;
+    MR_init_trace_check_integrity(cmd);
+    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+        return KEEP_INTERACTING;
+    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+        stop_depth = depth - n;
+    } else if (word_count == 1) {
+        stop_depth = depth;
+    } else {
+        MR_trace_usage_cur_cmd();
+        return KEEP_INTERACTING;
+    }
+
+    if (depth == stop_depth && MR_port_is_final(event_info->MR_trace_port)) {
+        MR_trace_do_noop();
+    } else {
+        cmd->MR_trace_cmd = MR_CMD_FINISH;
+        cmd->MR_trace_stop_depth = stop_depth;
+        return STOP_INTERACTING;
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_fail(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_Determinism  detism;
+    MR_Unsigned     depth;
+    int             stop_depth;
+    int             n;
+
+    detism = event_info->MR_event_sll->MR_sll_entry->MR_sle_detism;
+    depth = event_info->MR_call_depth;
+
+    cmd->MR_trace_strict = MR_TRUE;
+    cmd->MR_trace_print_level = MR_default_print_level;
+    MR_init_trace_check_integrity(cmd);
+    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+        return KEEP_INTERACTING;
+    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+        stop_depth = depth - n;
+    } else if (word_count == 1) {
+        stop_depth = depth;
+    } else {
+        MR_trace_usage_cur_cmd();
+        return KEEP_INTERACTING;
+    }
+
+    if (MR_DETISM_DET_STACK(detism)) {
+        fflush(MR_mdb_out);
+        fprintf(MR_mdb_err, "mdb: cannot continue until failure: "
+            "selected procedure has determinism %s.\n",
+            MR_detism_names[detism]);
+        return KEEP_INTERACTING;
+    }
+
+    if (depth == stop_depth && event_info->MR_trace_port == MR_PORT_FAIL) {
+        MR_trace_do_noop();
+    } else if (depth == stop_depth &&
+        event_info->MR_trace_port == MR_PORT_EXCEPTION)
+    {
+        fflush(MR_mdb_out);
+        fprintf(MR_mdb_err, "mdb: cannot continue until failure: "
+            "the call has raised an exception.\n");
+    } else {
+        cmd->MR_trace_cmd = MR_CMD_FAIL;
+        cmd->MR_trace_stop_depth = stop_depth;
+        return STOP_INTERACTING;
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_exception(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    cmd->MR_trace_strict = MR_TRUE;
+    cmd->MR_trace_print_level = MR_default_print_level;
+    MR_init_trace_check_integrity(cmd);
+    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 1) {
+        if (event_info->MR_trace_port != MR_PORT_EXCEPTION) {
+            cmd->MR_trace_cmd = MR_CMD_EXCP;
+            return STOP_INTERACTING;
+        } else {
+            MR_trace_do_noop();
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_return(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    cmd->MR_trace_strict = MR_TRUE;
+    cmd->MR_trace_print_level = MR_default_print_level;
+    MR_init_trace_check_integrity(cmd);
+    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 1) {
+        if (event_info->MR_trace_port == MR_PORT_EXIT) {
+            cmd->MR_trace_cmd = MR_CMD_RETURN;
+            return STOP_INTERACTING;
+        } else {
+            MR_trace_do_noop();
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_forward(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    cmd->MR_trace_strict = MR_TRUE;
+    cmd->MR_trace_print_level = MR_default_print_level;
+    MR_init_trace_check_integrity(cmd);
+    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 1) {
+        MR_Trace_Port   port;
+
+        port = event_info->MR_trace_port;
+        if (port == MR_PORT_FAIL ||
+            port == MR_PORT_REDO ||
+            port == MR_PORT_EXCEPTION)
+        {
+            cmd->MR_trace_cmd = MR_CMD_RESUME_FORWARD;
+            return STOP_INTERACTING;
+        } else {
+            MR_trace_do_noop();
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_mindepth(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int newdepth;
+
+    cmd->MR_trace_strict = MR_TRUE;
+    cmd->MR_trace_print_level = MR_default_print_level;
+    MR_init_trace_check_integrity(cmd);
+    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 2 &&
+        MR_trace_is_natural_number(words[1], &newdepth))
+    {
+        cmd->MR_trace_cmd = MR_CMD_MIN_DEPTH;
+        cmd->MR_trace_stop_depth = newdepth;
+        return STOP_INTERACTING;
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_maxdepth(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int newdepth;
+
+    cmd->MR_trace_strict = MR_TRUE;
+    cmd->MR_trace_print_level = MR_default_print_level;
+    MR_init_trace_check_integrity(cmd);
+    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 2 &&
+        MR_trace_is_natural_number(words[1], &newdepth))
+    {
+        cmd->MR_trace_cmd = MR_CMD_MAX_DEPTH;
+        cmd->MR_trace_stop_depth = newdepth;
+        return STOP_INTERACTING;
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_continue(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    cmd->MR_trace_strict = MR_FALSE;
+    cmd->MR_trace_print_level = (MR_Trace_Cmd_Type) -1;
+    MR_init_trace_check_integrity(cmd);
+    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 1) {
+        cmd->MR_trace_cmd = MR_CMD_TO_END;
+        if (cmd->MR_trace_print_level == (MR_Trace_Cmd_Type) -1) {
+            /*
+            ** The user did not specify the print level;
+            ** select the intelligent default.
+            */
+            if (cmd->MR_trace_strict) {
+                cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE;
+            } else {
+                cmd->MR_trace_print_level = MR_PRINT_LEVEL_SOME;
+            }
+        }
+        return STOP_INTERACTING;
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+/****************************************************************************/
+
+const char *const    MR_trace_movement_cmd_args[] =
+    { "-N", "-S", "-a", "-i", "-n", "-s",
+    "--none", "--some", "--all", "--integrity",
+    "--strict", "--no-strict", NULL };
+
+/****************************************************************************/
+
+static struct MR_option MR_trace_movement_cmd_opts[] =
+{
+    { "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' },
+#ifdef  MR_TRACE_CHECK_INTEGRITY
+    { "integrity",  MR_no_argument, NULL,   'i' },
+#endif
+    { NULL,         MR_no_argument, NULL,   0 }
+};
+
+static MR_bool
+MR_trace_options_movement_cmd(MR_Trace_Cmd_Info *cmd,
+    char ***words, int *word_count)
+{
+    int c;
+
+#ifdef  MR_TRACE_CHECK_INTEGRITY
+  #define   MR_TRACE_MOVEMENT_OPTS  "NSains"
+#else
+  #define   MR_TRACE_MOVEMENT_OPTS  "NSans"
+#endif
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, MR_TRACE_MOVEMENT_OPTS,
+        MR_trace_movement_cmd_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'N':
+                cmd->MR_trace_strict = MR_FALSE;
+                break;
+
+            case 'S':
+                cmd->MR_trace_strict = MR_TRUE;
+                break;
+
+            case 'a':
+                cmd->MR_trace_print_level = MR_PRINT_LEVEL_ALL;
+                break;
+
+            case 'n':
+                cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE;
+                break;
+
+            case 's':
+                cmd->MR_trace_print_level = MR_PRINT_LEVEL_SOME;
+                break;
+
+#ifdef  MR_TRACE_CHECK_INTEGRITY
+            case 'i':
+                cmd->MR_trace_check_integrity = MR_TRUE;
+                break;
+#endif
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
Index: trace/mercury_trace_cmd_forward.h
===================================================================
RCS file: trace/mercury_trace_cmd_forward.h
diff -N trace/mercury_trace_cmd_forward.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_forward.h	3 Apr 2006 10:01:11 -0000
@@ -0,0 +1,26 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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.
+*/
+
+#include "mercury_imp.h"
+
+#include "mercury_trace.h"
+
+extern  MR_TraceCmdFunc     MR_trace_cmd_step;
+extern  MR_TraceCmdFunc     MR_trace_cmd_goto;
+extern  MR_TraceCmdFunc     MR_trace_cmd_next;
+extern  MR_TraceCmdFunc     MR_trace_cmd_finish;
+extern  MR_TraceCmdFunc     MR_trace_cmd_fail;
+extern  MR_TraceCmdFunc     MR_trace_cmd_exception;
+extern  MR_TraceCmdFunc     MR_trace_cmd_return;
+extern  MR_TraceCmdFunc     MR_trace_cmd_forward;
+extern  MR_TraceCmdFunc     MR_trace_cmd_mindepth;
+extern  MR_TraceCmdFunc     MR_trace_cmd_maxdepth;
+extern  MR_TraceCmdFunc     MR_trace_cmd_continue;
+
+extern  const char *const   MR_trace_movement_cmd_args[];
Index: trace/mercury_trace_cmd_help.c
===================================================================
RCS file: trace/mercury_trace_cmd_help.c
diff -N trace/mercury_trace_cmd_help.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_help.c	3 Apr 2006 12:50:51 -0000
@@ -0,0 +1,152 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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 module implements the mdb commands in the "help" category.
+**
+** The structure of these files is:
+**
+** - all the #includes
+** - local macros and declarations of local static functions
+** - one function for each command in the category
+** - any auxiliary functions
+** - any command argument strings
+** - option processing functions.
+*/
+
+#include "mercury_std.h"
+#include "mercury_getopt.h"
+
+#include "mercury_array_macros.h"
+#include "mercury_trace_internal.h"
+#include "mercury_trace_cmds.h"
+#include "mercury_trace_cmd_help.h"
+#include "mercury_trace_help.h"
+#include "mercury_trace_util.h"
+
+/****************************************************************************/
+
+/* The initial number of lines in documentation entries. */
+#define MR_INIT_DOC_CHARS   800
+
+static  const char  *MR_trace_read_help_text(void);
+
+/****************************************************************************/
+
+MR_Next
+MR_trace_cmd_document_category(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int         slot;
+    const char  *msg;
+    const char  *help_text;
+
+    help_text = MR_trace_read_help_text();
+    if (word_count != 3) {
+        MR_trace_usage_cur_cmd();
+    } else if (! MR_trace_is_natural_number(words[1], &slot)) {
+        MR_trace_usage_cur_cmd();
+    } else {
+        msg = MR_trace_add_cat(words[2], slot, help_text);
+        if (msg != NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err,
+                "Document category `%s' not added: %s.\n", words[2], msg);
+        }
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_document(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int         slot;
+    const char  *msg;
+    const char  *help_text;
+
+    help_text = MR_trace_read_help_text();
+    if (word_count != 4) {
+        MR_trace_usage_cur_cmd();
+    } else if (! MR_trace_is_natural_number(words[2], &slot)) {
+        MR_trace_usage_cur_cmd();
+    } else {
+        msg = MR_trace_add_item(words[1], words[3], slot, help_text);
+        if (msg != NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err,
+                "Document item `%s' in category `%s' not added: %s.\n",
+                words[3], words[1], msg);
+        }
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_help(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 1) {
+        MR_trace_help();
+    } else if (word_count == 2) {
+        MR_trace_help_word(words[1]);
+    } else if (word_count == 3) {
+        MR_trace_help_cat_item(words[1], words[2]);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+/****************************************************************************/
+
+/*
+** Read lines until we find one that contains only "end".
+** Return the lines concatenated together.
+** The memory returned is allocated with MR_malloc();
+** it is the caller's responsibility to MR_free() it when appropriate.
+*/
+
+static const char *
+MR_trace_read_help_text(void)
+{
+    char    *text;
+    char    *doc_chars = NULL;
+    int     doc_char_max = 0;
+    int     next_char_slot;
+    int     line_len;
+    int     i;
+
+    next_char_slot = 0;
+    while ((text = MR_trace_getline("cat> ", MR_mdb_in, MR_mdb_out)) != NULL) {
+        if (MR_streq(text, "end")) {
+            MR_free(text);
+            break;
+        }
+
+        line_len = strlen(text);
+        MR_ensure_big_enough(next_char_slot + line_len + 2, doc_char, char,
+            MR_INIT_DOC_CHARS);
+        for (i = 0; i < line_len; i++) {
+            doc_chars[next_char_slot + i] = text[i];
+        }
+
+        next_char_slot += line_len;
+        doc_chars[next_char_slot] = '\n';
+        next_char_slot += 1;
+        MR_free(text);
+    }
+
+    MR_ensure_big_enough(next_char_slot, doc_char, char, MR_INIT_DOC_CHARS);
+    doc_chars[next_char_slot] = '\0';
+    return doc_chars;
+}
Index: trace/mercury_trace_cmd_help.h
===================================================================
RCS file: trace/mercury_trace_cmd_help.h
diff -N trace/mercury_trace_cmd_help.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_help.h	3 Apr 2006 10:38:26 -0000
@@ -0,0 +1,16 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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.
+*/
+
+#include "mercury_imp.h"
+
+#include "mercury_trace_cmds.h"
+
+extern  MR_TraceCmdFunc     MR_trace_cmd_document_category;
+extern  MR_TraceCmdFunc     MR_trace_cmd_document;
+extern  MR_TraceCmdFunc     MR_trace_cmd_help;
Index: trace/mercury_trace_cmd_misc.c
===================================================================
RCS file: trace/mercury_trace_cmd_misc.c
diff -N trace/mercury_trace_cmd_misc.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_misc.c	3 Apr 2006 12:50:55 -0000
@@ -0,0 +1,328 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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 module implements the mdb commands in the "misc" category.
+**
+** The structure of these files is:
+**
+** - all the #includes
+** - local macros and declarations of local static functions
+** - one function for each command in the category
+** - any auxiliary functions
+** - any command argument strings
+** - option processing functions.
+*/
+
+#include "mercury_std.h"
+#include "mercury_getopt.h"
+
+#include "mercury_trace_internal.h"
+#include "mercury_trace_cmds.h"
+#include "mercury_trace_cmd_misc.h"
+#include "mercury_trace_cmd_parameter.h"
+#include "mercury_trace_alias.h"
+#include "mercury_trace_declarative.h"
+#include "mercury_trace_spy.h"
+
+#include "mdb.listing.mh"
+
+/****************************************************************************/
+
+static  MR_bool     MR_trace_options_ignore(MR_bool *ignore_errors,
+                        char ***words, int *word_count);
+static  MR_bool     MR_trace_options_confirmed(MR_bool *confirmed,
+                        char ***words, int *word_count);
+
+/****************************************************************************/
+
+MR_Next
+MR_trace_cmd_source(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_bool ignore_errors;
+
+    ignore_errors = MR_FALSE;
+    if (! MR_trace_options_ignore(&ignore_errors, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 2) {
+        /*
+        ** If the source fails, the error message
+        ** will have already been printed by MR_trace_source
+        ** (unless ignore_errors suppresses the message).
+        */
+        (void) MR_trace_source(words[1], ignore_errors);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_save(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 2) {
+        FILE    *fp;
+        MR_bool found_error;
+        MR_Word path_list;
+
+        fp = fopen(words[1], "w");
+        if (fp == NULL) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: error opening `%s': %s.\n",
+                words[1], strerror(errno));
+            return KEEP_INTERACTING;
+        }
+
+        MR_trace_print_all_aliases(fp, MR_TRUE);
+        switch (MR_default_print_level) {
+            case MR_PRINT_LEVEL_NONE:
+                fprintf(fp, "printlevel none\n");
+                break;
+
+            case MR_PRINT_LEVEL_SOME:
+                fprintf(fp, "printlevel some\n");
+                break;
+
+            case MR_PRINT_LEVEL_ALL:
+                fprintf(fp, "printlevel all\n");
+                break;
+        }
+
+        if (MR_echo_commands) {
+            fprintf(fp, "echo on\n");
+        } else {
+            fprintf(fp, "echo off\n");
+        }
+
+        if (MR_scroll_control) {
+            fprintf(fp, "scroll on\n");
+        } else {
+            fprintf(fp, "scroll off\n");
+        }
+
+        fprintf(fp, "scroll %d\n", MR_scroll_limit);
+        fprintf(fp, "stack_default_limit %d\n", MR_stack_default_line_limit);
+
+        switch (MR_context_position) {
+            case MR_CONTEXT_NOWHERE:
+                fprintf(fp, "context nowhere\n");
+                break;
+
+            case MR_CONTEXT_AFTER:
+                fprintf(fp, "context after\n");
+                break;
+
+            case MR_CONTEXT_BEFORE:
+                fprintf(fp, "context before\n");
+                break;
+
+            case MR_CONTEXT_PREVLINE:
+                fprintf(fp, "context prevline\n");
+                break;
+
+            case MR_CONTEXT_NEXTLINE:
+                fprintf(fp, "context nextline\n");
+                break;
+        }
+
+        if (MR_print_goal_paths) {
+            fprintf(fp, "goal_paths on\n");
+        } else {
+            fprintf(fp, "goal_paths off\n");
+        }
+
+        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;
+
+            case MR_SPY_LINENO:
+            case MR_SPY_SPECIFIC:
+                MR_fatal_error("save cmd: invalid default scope");
+        }
+
+        MR_trace_print_all_browser_params(fp, MR_TRUE);
+        MR_decl_print_all_trusted(fp, MR_TRUE);
+
+        if (MR_dice_fail_trace_counts_file != NULL) {
+            fprintf(fp, "fail_trace_counts %s\n",
+                MR_dice_fail_trace_counts_file);
+        }
+        if (MR_dice_pass_trace_counts_file != NULL) {
+            fprintf(fp, "pass_trace_counts %s\n",
+                MR_dice_pass_trace_counts_file);
+        }
+
+        fprintf(fp, "list_context_lines %d\n", MR_num_context_lines);
+        MR_TRACE_CALL_MERCURY(
+            path_list = ML_LISTING_get_list_path(MR_listing_path);
+            if (! MR_list_is_empty(path_list)) {
+                fprintf(fp, "list_path");
+                while (! MR_list_is_empty(path_list)) {
+                    fprintf(fp, " %s", (const char *) MR_list_head(path_list));
+                    path_list = MR_list_tail(path_list);
+                }
+                fprintf(fp, "\n");
+            }
+        );
+
+        if (found_error) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: could not save debugger state to %s.\n",
+                words[1]);
+            (void) fclose(fp);
+        } else if (fclose(fp) != 0) {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err, "mdb: error closing `%s': %s.\n",
+                words[1], strerror(errno));
+        } else {
+            fprintf(MR_mdb_out, "Debugger state saved to %s.\n", words[1]);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_quit(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_bool confirmed;
+
+    confirmed = MR_FALSE;
+    if (! MR_trace_options_confirmed(&confirmed, &words, &word_count)) {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 1) {
+        if (! confirmed) {
+            char    *line2;
+
+            line2 = MR_trace_getline("mdb: are you sure you want to quit? ",
+                MR_mdb_in, MR_mdb_out);
+            if (line2 == NULL) {
+                /* This means the user input EOF. */
+                confirmed = MR_TRUE;
+            } else {
+                int i = 0;
+                while (line2[i] != '\0' && MR_isspace(line2[i])) {
+                    i++;
+                }
+
+                if (line2[i] == 'y' || line2[i] == 'Y') {
+                    confirmed = MR_TRUE;
+                }
+
+                MR_free(line2);
+            }
+        }
+
+        if (confirmed) {
+            MR_trace_maybe_close_source_window(MR_FALSE);
+            exit(EXIT_SUCCESS);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+/****************************************************************************/
+
+/*
+** It's better to have a single completion where possible,
+** so don't include `-i' here.
+*/
+
+const char *const    MR_trace_source_cmd_args[] =
+    { "--ignore-errors", NULL };
+
+const char *const    MR_trace_quit_cmd_args[] =
+    { "-y", NULL };
+
+/****************************************************************************/
+
+static struct MR_option MR_trace_ignore_opts[] =
+{                       
+    { "ignore-errors",  MR_no_argument, NULL,   'i' },
+    { NULL,             MR_no_argument, NULL,   0   }
+};
+                        
+static MR_bool          
+MR_trace_options_ignore(MR_bool *ignore_errors, char ***words, int *word_count)
+{                       
+    int c;              
+
+    MR_optind = 0;      
+    while ((c = MR_getopt_long(*word_count, *words, "i",
+        MR_trace_ignore_opts, NULL)) != EOF)
+    {                   
+        switch (c) {
+                        
+            case 'i':
+                *ignore_errors = MR_TRUE; 
+                break;
+                        
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }               
+    }                   
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;     
+}                       
+
+
+static MR_bool
+MR_trace_options_confirmed(MR_bool *confirmed, char ***words, int *word_count)
+{
+    int c;
+
+    MR_optind = 0;
+    while ((c = MR_getopt(*word_count, *words, "NYny")) != EOF) {
+        switch (c) {
+
+            case 'n':
+            case 'N':
+                *confirmed = MR_FALSE;
+                break;
+
+            case 'y':
+            case 'Y':
+                *confirmed = MR_TRUE;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+/****************************************************************************/
Index: trace/mercury_trace_cmd_misc.h
===================================================================
RCS file: trace/mercury_trace_cmd_misc.h
diff -N trace/mercury_trace_cmd_misc.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_misc.h	3 Apr 2006 10:31:24 -0000
@@ -0,0 +1,18 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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.
+*/
+
+#include "mercury_trace_cmds.h"
+
+extern  MR_TraceCmdFunc     MR_trace_cmd_source;
+extern  MR_TraceCmdFunc     MR_trace_cmd_save;
+extern  MR_TraceCmdFunc     MR_trace_cmd_quit;
+
+extern	const char *const   MR_trace_source_cmd_args[];
+extern	const char *const   MR_trace_quit_cmd_args[];
+
Index: trace/mercury_trace_cmd_parameter.c
===================================================================
RCS file: trace/mercury_trace_cmd_parameter.c
diff -N trace/mercury_trace_cmd_parameter.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_parameter.c	3 Apr 2006 12:51:00 -0000
@@ -0,0 +1,997 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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 module implements the mdb commands in the "parameter" category.
+**
+** The structure of these files is:
+**
+** - all the #includes
+** - local macros and declarations of local static functions
+** - one function for each command in the category
+** - any auxiliary functions
+** - any command argument strings
+** - option processing functions.
+*/
+
+#include "mercury_std.h"
+#include "mercury_getopt.h"
+#include "mercury_stack_trace.h"    /* for MR_Context_Position  */
+
+#include "mercury_trace.h"
+#include "mercury_trace_internal.h"
+#include "mercury_trace_cmds.h"
+#include "mercury_trace_cmd_parameter.h"
+#include "mercury_trace_spy.h"
+#include "mercury_trace_alias.h"
+#include "mercury_trace_util.h"
+
+#include "mdb.browser_info.mh"      /* for ML_BROWSE_get_num_io_actions etc */
+#include "mdb.listing.mh"           /* for ML_LISTING_get_list_path etc     */
+
+/****************************************************************************/
+
+char                    *MR_mmc_options = NULL;
+
+MR_Trace_Print_Level    MR_default_print_level = MR_PRINT_LEVEL_SOME;
+
+MR_bool                 MR_scroll_control = MR_TRUE;
+int                     MR_scroll_limit = 24;
+int                     MR_scroll_next = 0;
+
+int                     MR_stack_default_line_limit = 0;
+
+MR_bool                 MR_echo_commands = MR_FALSE;
+
+MR_bool                 MR_print_optionals = MR_FALSE;
+
+char                    *MR_dice_pass_trace_counts_file = NULL;
+char                    *MR_dice_fail_trace_counts_file = NULL;
+
+MR_Context_Position     MR_context_position = MR_CONTEXT_AFTER;
+
+MR_bool                 MR_print_goal_paths = MR_TRUE;
+
+MR_Word                 MR_listing_path;
+
+int                     MR_num_context_lines = 2;
+
+MR_Spy_When             MR_default_breakpoint_scope = MR_SPY_INTERFACE;
+
+/****************************************************************************/
+
+static  MR_bool     MR_trace_options_cmd_format(MR_Word *print_set,
+                        MR_Word *browse_set, MR_Word *print_all_set,
+                        char ***words, int *word_count);
+static  MR_bool     MR_trace_options_cmd_format_param(MR_Word *print_set,
+                        MR_Word *browse_set, MR_Word *print_all_set,
+                        MR_Word *flat_format, MR_Word *raw_pretty_format,
+                        MR_Word *verbose_format, MR_Word *pretty_format,
+                        char ***words, int *word_count);
+
+/****************************************************************************/
+
+MR_Next
+MR_trace_cmd_mmc_options(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    size_t len;
+    size_t i;
+
+    /* allocate the right amount of space */
+    len = 0;
+    for (i = 1; i < word_count; i++) {
+        len += strlen(words[i]) + 1;
+    }
+    len++;
+    MR_mmc_options = MR_realloc(MR_mmc_options, len);
+
+    /* copy the arguments to MR_mmc_options */
+    MR_mmc_options[0] = '\0';
+    for (i = 1; i < word_count; i++) {
+        strcat(MR_mmc_options, words[i]);
+        strcat(MR_mmc_options, " ");
+    }
+    MR_mmc_options[len - 1] = '\0';
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_printlevel(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 2) {
+        if (MR_streq(words[1], "none")) {
+            MR_default_print_level = MR_PRINT_LEVEL_NONE;
+            if (MR_trace_internal_interacting) {
+                fprintf(MR_mdb_out, "Default print level set to `none'.\n");
+            }
+        } else if (MR_streq(words[1], "some")) {
+            MR_default_print_level = MR_PRINT_LEVEL_SOME;
+            if (MR_trace_internal_interacting) {
+                fprintf(MR_mdb_out, "Default print level set to `some'.\n");
+            }
+        } else if (MR_streq(words[1], "all")) {
+            MR_default_print_level = MR_PRINT_LEVEL_ALL;
+            if (MR_trace_internal_interacting) {
+                fprintf(MR_mdb_out, "Default print level set to `all'.\n");
+            }
+        } else {
+            MR_trace_usage_cur_cmd();
+        }
+    } else if (word_count == 1) {
+        fprintf(MR_mdb_out, "The default print level is ");
+        switch (MR_default_print_level) {
+            case MR_PRINT_LEVEL_NONE:
+                fprintf(MR_mdb_out, "`none'.\n");
+                break;
+            case MR_PRINT_LEVEL_SOME:
+                fprintf(MR_mdb_out, "`some'.\n");
+                break;
+            case MR_PRINT_LEVEL_ALL:
+                fprintf(MR_mdb_out, "`all'.\n");
+                break;
+            default:
+                MR_default_print_level = MR_PRINT_LEVEL_SOME;
+                fprintf(MR_mdb_out, "invalid (now set to `some').\n");
+                break;
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_scroll(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int n;
+
+    if (word_count == 2) {
+        if (MR_streq(words[1], "off")) {
+            MR_scroll_control = MR_FALSE;
+            if (MR_trace_internal_interacting) {
+                fprintf(MR_mdb_out, "Scroll control disabled.\n");
+            }
+        } else if (MR_streq(words[1], "on")) {
+            MR_scroll_control = MR_TRUE;
+            if (MR_trace_internal_interacting) {
+                fprintf(MR_mdb_out, "Scroll control enabled.\n");
+            }
+        } else if (MR_trace_is_natural_number(words[1], &n)) {
+            MR_scroll_limit = n;
+            if (MR_trace_internal_interacting) {
+                fprintf(MR_mdb_out,
+                    "Scroll window size set to %d.\n", MR_scroll_limit);
+            }
+        } else {
+            MR_trace_usage_cur_cmd();
+        }
+    } else if (word_count == 1) {
+        fprintf(MR_mdb_out, "Scroll control is ");
+        if (MR_scroll_control) {
+            fprintf(MR_mdb_out, "on");
+        } else {
+            fprintf(MR_mdb_out, "off");
+        }
+        fprintf(MR_mdb_out, ", scroll window size is %d.\n", MR_scroll_limit);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_stack_default_limit(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int n;
+
+    if (word_count == 2) {
+        if (MR_trace_is_natural_number(words[1], &n)) {
+            MR_stack_default_line_limit = n;
+            if (! MR_trace_internal_interacting) {
+                return KEEP_INTERACTING;
+            }
+
+            if (MR_stack_default_line_limit > 0) {
+                fprintf(MR_mdb_out,
+                    "Default stack dump size limit set to %d.\n",
+                    MR_stack_default_line_limit);
+            } else {
+                fprintf(MR_mdb_out,
+                    "Default stack dump size limit set to none.\n");
+            }
+        } else {
+            MR_trace_usage_cur_cmd();
+        }
+    } else if (word_count == 1) {
+        if (MR_stack_default_line_limit > 0) {
+            fprintf(MR_mdb_out, "Default stack dump size limit is %d.\n",
+                MR_stack_default_line_limit);
+        } else {
+            fprintf(MR_mdb_out,
+                "There is no default stack dump size limit.\n");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+static const char   *MR_context_set_msg[] = {
+    "Contexts will not be printed.",
+    "Contexts will be printed before, on the same line.",
+    "Contexts will be printed after, on the same line.",
+    "Contexts will be printed on the previous line.",
+    "Contexts will be printed on the next line.",
+};
+
+static const char   *MR_context_report_msg[] = {
+    "Contexts are not printed.",
+    "Contexts are printed before, on the same line.",
+    "Contexts are printed after, on the same line.",
+    "Contexts are printed on the previous line.",
+    "Contexts are printed on the next line.",
+};
+
+MR_Next
+MR_trace_cmd_context(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 2) {
+        if (MR_streq(words[1], "none")) {
+            MR_context_position = MR_CONTEXT_NOWHERE;
+        } else if (MR_streq(words[1], "before")) {
+            MR_context_position = MR_CONTEXT_BEFORE;
+        } else if (MR_streq(words[1], "after")) {
+            MR_context_position = MR_CONTEXT_AFTER;
+        } else if (MR_streq(words[1], "prevline")) {
+            MR_context_position = MR_CONTEXT_PREVLINE;
+        } else if (MR_streq(words[1], "nextline")) {
+            MR_context_position = MR_CONTEXT_NEXTLINE;
+        } else {
+            MR_trace_usage_cur_cmd();
+            return KEEP_INTERACTING;
+        }
+
+        if (MR_trace_internal_interacting) {
+            fprintf(MR_mdb_out, "%s\n",
+                MR_context_set_msg[MR_context_position]);
+        }
+    } else if (word_count == 1) {
+        switch (MR_context_position) {
+        case MR_CONTEXT_NOWHERE:
+        case MR_CONTEXT_BEFORE:
+        case MR_CONTEXT_AFTER:
+        case MR_CONTEXT_PREVLINE:
+        case MR_CONTEXT_NEXTLINE:
+            fprintf(MR_mdb_out, "%s\n",
+                MR_context_report_msg[MR_context_position]);
+            break;
+
+        default:
+            MR_fatal_error("invalid MR_context_position");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_goal_paths(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 2) {
+        if (MR_streq(words[1], "off")) {
+            MR_print_goal_paths = MR_FALSE;
+            fprintf(MR_mdb_out, "Goal path printing is now off.\n");
+        } else if (MR_streq(words[1], "on")) {
+            MR_print_goal_paths = MR_TRUE;
+            fprintf(MR_mdb_out, "Goal path printing is now on.\n");
+        } else {
+            MR_trace_usage_cur_cmd();
+            return KEEP_INTERACTING;
+        }
+    } else if (word_count == 1) {
+        if (MR_print_goal_paths) {
+            fprintf(MR_mdb_out, "Goal path printing is on.\n");
+        } else {
+            fprintf(MR_mdb_out, "Goal path printing is off.\n");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+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",
+};
+
+MR_Next
+MR_trace_cmd_scope(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 2) {
+        if (MR_streq(words[1], "all")) {
+            MR_default_breakpoint_scope = MR_SPY_ALL;
+        } else if (MR_streq(words[1], "interface")) {
+            MR_default_breakpoint_scope = MR_SPY_INTERFACE;
+        } else if (MR_streq(words[1], "entry")) {
+            MR_default_breakpoint_scope = MR_SPY_ENTRY;
+        } else {
+            MR_trace_usage_cur_cmd();
+            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_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_echo(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 2) {
+        if (MR_streq(words[1], "off")) {
+            MR_echo_commands = MR_FALSE;
+            if (MR_trace_internal_interacting) {
+                fprintf(MR_mdb_out, "Command echo disabled.\n");
+            }
+        } else if (MR_streq(words[1], "on")) {
+            if (!MR_echo_commands) {
+                /*
+                ** Echo the `echo on' command. This is needed for historical
+                ** reasons (compatibility with our existing test suite).
+                */
+                fprintf(MR_mdb_out, "echo on\n");
+                MR_echo_commands = MR_TRUE;
+            }
+            if (MR_trace_internal_interacting) {
+                fprintf(MR_mdb_out, "Command echo enabled.\n");
+            }
+        } else {
+            MR_trace_usage_cur_cmd();
+        }
+    } else if (word_count == 1) {
+        fprintf(MR_mdb_out, "Command echo is ");
+        if (MR_echo_commands) {
+            fprintf(MR_mdb_out, "on.\n");
+        } else {
+            fprintf(MR_mdb_out, "off.\n");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_list_context_lines(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int                 n;
+
+    if (word_count == 2 && MR_trace_is_natural_number(words[2], &n)) {
+        MR_num_context_lines = n;
+    } else if (word_count == 1) {
+        fprintf(MR_mdb_out,
+            "Printing %d lines around each context listing\n",
+            MR_num_context_lines);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_list_path(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count < 2) {
+        MR_Word list;
+
+        list = ML_LISTING_get_list_path(MR_listing_path);
+        if (MR_list_is_empty(list)) {
+            fprintf(MR_mdb_out, "Context search path is empty\n");
+        } else {
+            fprintf(MR_mdb_out, "Context search path:");
+            while (! MR_list_is_empty(list)) {
+                fprintf(MR_mdb_out, " %s", (const char *) MR_list_head(list));
+                list = MR_list_tail(list);
+            }
+            fprintf(MR_mdb_out, "\n");
+        }
+    } else {
+        int       i;
+        MR_String aligned_word;
+
+        MR_TRACE_CALL_MERCURY(
+            ML_LISTING_clear_list_path(MR_listing_path, &MR_listing_path);
+            for(i = word_count - 1; i >= 1; i--) {
+                MR_TRACE_USE_HP(
+                    MR_make_aligned_string(aligned_word, (MR_String) words[i]);
+                );
+                ML_LISTING_push_list_path(aligned_word,
+                    MR_listing_path, &MR_listing_path);
+            }
+        );
+
+        MR_listing_path =
+            MR_make_permanent(MR_listing_path, ML_LISTING_listing_type);
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_push_list_dir(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int       i;
+    MR_String aligned_word;
+
+    if (word_count < 2) {
+        MR_trace_usage_cur_cmd();
+        return KEEP_INTERACTING;
+    }
+
+    MR_TRACE_CALL_MERCURY(
+        for(i = word_count - 1; i >= 1; i--) {
+            MR_TRACE_USE_HP(
+                MR_make_aligned_string(aligned_word, (MR_String) words[i]);
+            );
+            ML_LISTING_push_list_path(aligned_word,
+                MR_listing_path, &MR_listing_path);
+        }
+    );
+
+    MR_listing_path =
+        MR_make_permanent(MR_listing_path, ML_LISTING_listing_type);
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_pop_list_dir(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count > 1) {
+        MR_trace_usage_cur_cmd();
+        return KEEP_INTERACTING;
+    }
+
+    MR_TRACE_CALL_MERCURY(
+        ML_LISTING_pop_list_path(MR_listing_path, &MR_listing_path);
+    );
+
+    MR_listing_path =
+        MR_make_permanent(MR_listing_path, ML_LISTING_listing_type);
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_fail_trace_counts(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 2) {
+        if (MR_dice_fail_trace_counts_file != NULL) {
+            free(MR_dice_fail_trace_counts_file);
+        }
+
+        MR_dice_fail_trace_counts_file = MR_copy_string(words[1]);
+    } else if (word_count == 1) {
+        if (MR_dice_fail_trace_counts_file == NULL) {
+            fprintf(MR_mdb_out,
+                "The failing tests trace counts file has not been set.\n");
+        } else {
+            fprintf(MR_mdb_out,
+                "The failing tests trace counts file is %s\n",
+                MR_dice_fail_trace_counts_file);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_pass_trace_counts(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 2) {
+        if (MR_dice_pass_trace_counts_file != NULL) {
+            free(MR_dice_pass_trace_counts_file);
+        }
+
+        MR_dice_pass_trace_counts_file = MR_copy_string(words[1]);
+    } else if (word_count == 1) {
+        if (MR_dice_pass_trace_counts_file == NULL) {
+            fprintf(MR_mdb_out,
+                "The passing tests trace counts file has not been set.\n");
+        } else {
+            fprintf(MR_mdb_out,
+                "The passing tests trace counts file is %s\n",
+                MR_dice_pass_trace_counts_file);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_max_io_actions(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    int                 n;
+
+    if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
+        MR_TRACE_CALL_MERCURY(
+            ML_BROWSE_set_num_io_actions(n,
+                MR_trace_browser_persistent_state,
+                &MR_trace_browser_persistent_state);
+        );
+    } else if (word_count == 1) {
+        MR_TRACE_CALL_MERCURY(
+            ML_BROWSE_get_num_io_actions(
+                MR_trace_browser_persistent_state, &n);
+        );
+        fprintf(MR_mdb_out,
+            "The maximum number of I/O actions printed is %d\n",
+            n);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_xml_browser_cmd(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 2) {
+        char    *copied_value;
+        char    *aligned_value;
+
+        copied_value = (char *) MR_GC_malloc(strlen(words[1]) + 1);
+        strcpy(copied_value, words[1]);
+        MR_TRACE_USE_HP(
+            MR_make_aligned_string(aligned_value, copied_value);
+        );
+        MR_TRACE_CALL_MERCURY(
+            ML_BROWSE_set_xml_browser_cmd_from_mdb(aligned_value,
+                MR_trace_browser_persistent_state,
+                &MR_trace_browser_persistent_state);
+        );
+    } else if (word_count == 1) {
+        MR_String   command;
+
+        MR_TRACE_CALL_MERCURY(
+            ML_BROWSE_get_xml_browser_cmd_from_mdb(
+                MR_trace_browser_persistent_state, &command);
+        );
+
+        if (command != NULL && strlen(command) > 0) {
+            fprintf(MR_mdb_out, "The XML browser command is %s\n", command);
+        } else {
+            fprintf(MR_mdb_out, "The XML browser command has not been set.\n");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_xml_tmp_filename(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 2) {
+        char    *copied_value;
+        char    *aligned_value;
+
+        copied_value = (char *) MR_GC_malloc(strlen(words[1]) + 1);
+        strcpy(copied_value, words[1]);
+        MR_TRACE_USE_HP(
+            MR_make_aligned_string(aligned_value, copied_value);
+        );
+        MR_TRACE_CALL_MERCURY(
+            ML_BROWSE_set_xml_tmp_filename_from_mdb(aligned_value,
+                MR_trace_browser_persistent_state,
+                &MR_trace_browser_persistent_state);
+        );
+    } else if (word_count == 1) {
+        MR_String   file;
+
+        MR_TRACE_CALL_MERCURY(
+            ML_BROWSE_get_xml_browser_cmd_from_mdb(
+                MR_trace_browser_persistent_state, &file);
+        );
+
+        if (file != NULL && strlen(file) > 0) {
+            fprintf(MR_mdb_out, "The XML tmp filename is %s\n", file);
+        } else {
+            fprintf(MR_mdb_out, "The XML tmp filename has not been set.\n");
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_format(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_Browse_Format    new_format;
+    MR_Word             print;
+    MR_Word             browse;
+    MR_Word             print_all;
+
+    if (! MR_trace_options_cmd_format(&print, &browse, &print_all,
+        &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count == 2 &&
+        MR_trace_is_portray_format(words[1], &new_format))
+    {
+        MR_TRACE_CALL_MERCURY(
+            ML_BROWSE_set_format_from_mdb(print, browse, print_all, new_format,
+                MR_trace_browser_persistent_state,
+                &MR_trace_browser_persistent_state);
+        );
+        MR_trace_browser_persistent_state =
+            MR_make_permanent(MR_trace_browser_persistent_state,
+                MR_trace_browser_persistent_state_type);
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_format_param(char **words, int word_count,
+    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_Word             print;
+    MR_Word             browse;
+    MR_Word             print_all;
+    MR_Word             flat;
+    MR_Word             raw_pretty;
+    MR_Word             verbose;
+    MR_Word             pretty;
+    int                 n;
+
+    if (! MR_trace_options_cmd_format_param(&print, &browse, &print_all,
+        &flat, &raw_pretty, &verbose, &pretty, &words, &word_count))
+    {
+        ; /* the usage message has already been printed */
+    } else if (word_count != 3) {
+        MR_trace_usage_cur_cmd();
+    } else {
+        if (MR_streq(words[1], "depth") &&
+            MR_trace_is_natural_number(words[2], &n))
+        {
+            MR_TRACE_CALL_MERCURY(
+                ML_BROWSE_set_depth_from_mdb(print, browse, print_all,
+                    flat, raw_pretty, verbose, pretty, n,
+                    MR_trace_browser_persistent_state,
+                    &MR_trace_browser_persistent_state);
+            );
+        } else if (MR_streq(words[1], "size") &&
+            MR_trace_is_natural_number(words[2], &n))
+        {
+            MR_TRACE_CALL_MERCURY(
+                ML_BROWSE_set_size_from_mdb(print, browse, print_all,
+                    flat, raw_pretty, verbose, pretty, n,
+                    MR_trace_browser_persistent_state,
+                    &MR_trace_browser_persistent_state);
+            );
+        } else if (MR_streq(words[1], "width") &&
+            MR_trace_is_natural_number(words[2], &n))
+        {
+            MR_TRACE_CALL_MERCURY(
+                ML_BROWSE_set_width_from_mdb(print, browse, print_all,
+                    flat, raw_pretty, verbose, pretty, n,
+                    MR_trace_browser_persistent_state,
+                    &MR_trace_browser_persistent_state);
+            );
+        } else if (MR_streq(words[1], "lines") &&
+            MR_trace_is_natural_number(words[2], &n))
+        {
+            MR_TRACE_CALL_MERCURY(
+                ML_BROWSE_set_lines_from_mdb(print, browse, print_all,
+                    flat, raw_pretty, verbose, pretty, n,
+                    MR_trace_browser_persistent_state,
+                    &MR_trace_browser_persistent_state);
+            );
+        } else {
+            MR_trace_usage_cur_cmd();
+            return KEEP_INTERACTING;
+        }
+
+        MR_trace_browser_persistent_state =
+            MR_make_permanent(MR_trace_browser_persistent_state,
+                MR_trace_browser_persistent_state_type);
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_alias(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 1) {
+        MR_trace_print_all_aliases(MR_mdb_out, MR_FALSE);
+    } else if (word_count == 2) {
+        MR_trace_print_alias(MR_mdb_out, words[1]);
+    } else {
+        if (MR_trace_valid_command(words[2])) {
+            MR_trace_add_alias(words[1], words+2, word_count-2);
+            if (MR_trace_internal_interacting) {
+                MR_trace_print_alias(MR_mdb_out, words[1]);
+            }
+        } else {
+            fprintf(MR_mdb_out, "`%s' is not a valid command.\n", words[2]);
+        }
+    }
+
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_unalias(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 2) {
+        if (MR_trace_remove_alias(words[1])) {
+            if (MR_trace_internal_interacting) {
+                fprintf(MR_mdb_out, "Alias `%s' removed.\n", words[1]);
+            }
+        } else {
+            fflush(MR_mdb_out);
+            fprintf(MR_mdb_err,
+                "Alias `%s' cannot be removed, since it does not exist.\n",
+                words[1]);
+        }
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+/****************************************************************************/
+
+void
+MR_trace_listing_path_ensure_init(void)
+{
+    static MR_bool  MR_trace_listing_path_initialized = MR_FALSE;
+
+    if (! MR_trace_listing_path_initialized) {
+        MR_TRACE_CALL_MERCURY(
+            MR_listing_path = ML_LISTING_new_list_path();
+        );
+        MR_trace_listing_path_initialized = MR_TRUE;
+    }
+}
+
+/****************************************************************************/
+
+const char *const    MR_trace_printlevel_cmd_args[] =
+    { "none", "some", "all", NULL };
+    
+const char *const    MR_trace_on_off_args[] =
+    { "on", "off", NULL };
+                        
+const char *const    MR_trace_context_cmd_args[] =
+    { "none", "before", "after", "prevline", "nextline", NULL };
+        
+const char *const    MR_trace_scope_cmd_args[] =
+    { "all", "interface", "entry", NULL };
+
+const char *const    MR_trace_format_cmd_args[] =
+    { "-A", "-B", "-P",
+    "--print-all", "--print", "--browse",
+    "flat", "pretty", "verbose", NULL };
+ 
+const char *const    MR_trace_format_param_cmd_args[] =
+    { "-A", "-B", "-P", "-f", "-p", "-v",
+    "--print-all", "--print", "--browse",
+    "--flat", "--pretty", "--verbose",
+    "depth", "size", "width", "lines",
+    "flat", "pretty", "verbose", NULL };
+
+/****************************************************************************/
+
+static struct MR_option MR_trace_param_cmd_format_opts[] =
+{
+    { "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 MR_bool
+MR_trace_options_cmd_format(MR_Word *print_set, MR_Word *browse_set,
+    MR_Word *print_all_set, char ***words, int *word_count)
+{
+    int     c;
+    MR_Word mercury_bool_yes;
+    MR_Word mercury_bool_no;
+
+    MR_TRACE_CALL_MERCURY(
+        mercury_bool_yes = ML_BROWSE_mercury_bool_yes();
+        mercury_bool_no = ML_BROWSE_mercury_bool_no();
+    );
+
+    *print_set = mercury_bool_no;
+    *browse_set = mercury_bool_no;
+    *print_all_set = mercury_bool_no;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "PBA",
+        MR_trace_param_cmd_format_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'P':
+                *print_set = mercury_bool_yes;
+                break;
+
+            case 'B':
+                *browse_set = mercury_bool_yes;
+                break;
+
+            case 'A':
+                *print_all_set = mercury_bool_yes;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
+
+static struct MR_option MR_trace_param_cmd_format_param_opts[] =
+{
+    { "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 MR_bool
+MR_trace_options_cmd_format_param(MR_Word *print_set, MR_Word *browse_set,
+    MR_Word *print_all_set, MR_Word *flat_format,
+    MR_Word *raw_pretty_format, MR_Word *verbose_format,
+    MR_Word *pretty_format, char ***words, int *word_count)
+{
+    int     c;
+    MR_Word mercury_bool_yes;
+    MR_Word mercury_bool_no;
+
+    MR_TRACE_CALL_MERCURY(
+        mercury_bool_yes = ML_BROWSE_mercury_bool_yes();
+        mercury_bool_no = ML_BROWSE_mercury_bool_no();
+    );
+
+    *print_set = mercury_bool_no;
+    *browse_set = mercury_bool_no;
+    *print_all_set = mercury_bool_no;
+    *flat_format = mercury_bool_no;
+    *raw_pretty_format = mercury_bool_no;
+    *verbose_format = mercury_bool_no;
+    *pretty_format = mercury_bool_no;
+
+    MR_optind = 0;
+    while ((c = MR_getopt_long(*word_count, *words, "PBAfrvp",
+        MR_trace_param_cmd_format_param_opts, NULL)) != EOF)
+    {
+        switch (c) {
+
+            case 'f':
+                *flat_format = mercury_bool_yes;
+                break;
+
+            case 'r':
+                *raw_pretty_format = mercury_bool_yes;
+                break;
+
+            case 'v':
+                *verbose_format = mercury_bool_yes;
+                break;
+
+            case 'p':
+                *pretty_format = mercury_bool_yes;
+                break;
+
+            case 'P':
+                *print_set = mercury_bool_yes;
+                break;
+
+            case 'B':
+                *browse_set = mercury_bool_yes;
+                break;
+
+            case 'A':
+                *print_all_set = mercury_bool_yes;
+                break;
+
+            default:
+                MR_trace_usage_cur_cmd();
+                return MR_FALSE;
+        }
+    }
+
+    *words = *words + MR_optind - 1;
+    *word_count = *word_count - MR_optind + 1;
+    return MR_TRUE;
+}
Index: trace/mercury_trace_cmd_parameter.h
===================================================================
RCS file: trace/mercury_trace_cmd_parameter.h
diff -N trace/mercury_trace_cmd_parameter.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_parameter.h	3 Apr 2006 12:41:04 -0000
@@ -0,0 +1,136 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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.
+*/
+
+#include "mercury_std.h"
+#include "mercury_types.h"
+#include "mercury_stack_trace.h"    /* for MR_Context_Position  */
+
+#include "mercury_trace_cmds.h"
+#include "mercury_trace_spy.h"      /* for MR_Spy_When          */
+
+/*
+** Options to pass to mmc when compiling queries.
+*/
+
+extern  char                *MR_mmc_options;
+
+/*
+** The default print level governs whether we out reports for events at which
+** we don't stop.
+*/
+
+extern  MR_Trace_Print_Level MR_default_print_level;
+
+/*
+** These variables say (a) whether the printing of event sequences will pause
+** after each screenful of events, (b) how may events constitute a screenful
+** (although we count only events, not how many lines they take up), and (c)
+** how many events we have printed so far in this screenful.
+*/
+
+extern  MR_bool             MR_scroll_control;
+extern  int                 MR_scroll_limit;
+extern  int                 MR_scroll_next;
+
+/*
+** This variable controls the number of stack frame lines printed by the stack
+** and nondet_stack commands if the user doesn't override it.
+*/
+
+extern  int                 MR_stack_default_line_limit;
+
+/*
+** We echo each command just as it is executed iff this variable is MR_TRUE.
+*/
+
+extern  MR_bool             MR_echo_commands;
+
+/*
+** We include values of sometimes-useful types such as typeinfos in the set of
+** variables whose values we collect at events for possible later printing
+** only if MR_print_optionals is true.
+*/
+
+extern  MR_bool             MR_print_optionals;
+
+/*
+** This variable holds either the name of a file which contains a list of
+** the file names of passing test case trace counts, or the name of a single
+** file of passing test case trace counts.
+*/
+
+extern  char                *MR_dice_pass_trace_counts_file;
+
+/*
+** This variable holds either the name of a file which contains a list of
+** the file names of failing test case trace counts, or the name of a single
+** file of failing test case trace counts.
+*/
+
+extern  char                *MR_dice_fail_trace_counts_file;
+
+/*
+** MR_context_position specifies whether we print context at events,
+** and if so, where.
+*/
+
+extern  MR_Context_Position MR_context_position;
+
+/*
+** MR_print_goal_paths specifies whether we print goal paths at events.
+*/
+
+extern  MR_bool             MR_print_goal_paths;
+
+/*
+** MR_listing_path holds the current value of the listings structure
+** as defined in browser/listing.m. You need to ensure that it is initialized
+** before accessing it.
+*/
+
+extern  MR_Word             MR_listing_path;
+extern  void                MR_trace_listing_path_ensure_init(void);
+
+/*
+** MR_num_context_lines holds the current number of context lines to be
+** printed before and after the current callee/caller's file context.
+*/
+
+extern  int                 MR_num_context_lines;
+
+extern  MR_Spy_When         MR_default_breakpoint_scope;
+
+extern  MR_TraceCmdFunc     MR_trace_cmd_mmc_options;
+extern  MR_TraceCmdFunc     MR_trace_cmd_printlevel;
+extern  MR_TraceCmdFunc     MR_trace_cmd_scroll;
+extern  MR_TraceCmdFunc     MR_trace_cmd_stack_default_limit;
+extern  MR_TraceCmdFunc     MR_trace_cmd_context;
+extern  MR_TraceCmdFunc     MR_trace_cmd_goal_paths;
+extern  MR_TraceCmdFunc     MR_trace_cmd_scope;
+extern  MR_TraceCmdFunc     MR_trace_cmd_echo;
+extern  MR_TraceCmdFunc     MR_trace_cmd_list_context_lines;
+extern  MR_TraceCmdFunc     MR_trace_cmd_list_path;
+extern  MR_TraceCmdFunc     MR_trace_cmd_push_list_dir;
+extern  MR_TraceCmdFunc     MR_trace_cmd_pop_list_dir;
+extern  MR_TraceCmdFunc     MR_trace_cmd_fail_trace_counts;
+extern  MR_TraceCmdFunc     MR_trace_cmd_pass_trace_counts;
+extern  MR_TraceCmdFunc     MR_trace_cmd_max_io_actions;
+extern  MR_TraceCmdFunc     MR_trace_cmd_xml_browser_cmd;
+extern  MR_TraceCmdFunc     MR_trace_cmd_xml_tmp_filename;
+extern  MR_TraceCmdFunc     MR_trace_cmd_format;
+extern  MR_TraceCmdFunc     MR_trace_cmd_format_param;
+extern  MR_TraceCmdFunc     MR_trace_cmd_alias;
+extern  MR_TraceCmdFunc     MR_trace_cmd_unalias;
+
+extern  const char *const   MR_trace_printlevel_cmd_args[];
+extern  const char *const   MR_trace_on_off_args[];
+extern  const char *const   MR_trace_context_cmd_args[];
+extern  const char *const   MR_trace_scope_cmd_args[];
+extern  const char *const   MR_trace_format_cmd_args[];
+extern  const char *const   MR_trace_format_param_cmd_args[];
Index: trace/mercury_trace_cmd_queries.c
===================================================================
RCS file: trace/mercury_trace_cmd_queries.c
diff -N trace/mercury_trace_cmd_queries.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_queries.c	3 Apr 2006 12:51:04 -0000
@@ -0,0 +1,58 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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 module implements the mdb commands in the "queries" category.
+**
+** The structure of these files is:
+**
+** - all the #includes
+** - local macros and declarations of local static functions
+** - one function for each command in the category
+** - any auxiliary functions
+** - any command argument strings
+** - option processing functions.
+*/
+
+#include "mercury_std.h"
+#include "mercury_getopt.h"
+
+#include "mercury_trace_internal.h"
+#include "mercury_trace_cmds.h"
+#include "mercury_trace_cmd_queries.h"
+#include "mercury_trace_cmd_parameter.h"
+#include "mercury_trace_browse.h"
+
+/****************************************************************************/
+
+MR_Next
+MR_trace_cmd_query(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_trace_query(MR_NORMAL_QUERY, MR_mmc_options, word_count - 1, words + 1);
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_cc_query(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_trace_query(MR_CC_QUERY, MR_mmc_options, word_count - 1, words + 1);
+    return KEEP_INTERACTING;
+}
+
+MR_Next
+MR_trace_cmd_io_query(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    MR_trace_query(MR_IO_QUERY, MR_mmc_options, word_count - 1, words + 1);
+    return KEEP_INTERACTING;
+}
+
+/****************************************************************************/
Index: trace/mercury_trace_cmd_queries.h
===================================================================
RCS file: trace/mercury_trace_cmd_queries.h
diff -N trace/mercury_trace_cmd_queries.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_queries.h	3 Apr 2006 11:32:58 -0000
@@ -0,0 +1,16 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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.
+*/
+
+#include "mercury_imp.h"
+
+#include "mercury_trace_cmds.h"
+
+extern  MR_TraceCmdFunc     MR_trace_cmd_query;
+extern  MR_TraceCmdFunc     MR_trace_cmd_cc_query;
+extern  MR_TraceCmdFunc     MR_trace_cmd_io_query;
Index: trace/mercury_trace_cmd_table_io.c
===================================================================
RCS file: trace/mercury_trace_cmd_table_io.c
diff -N trace/mercury_trace_cmd_table_io.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_table_io.c	3 Apr 2006 12:51:09 -0000
@@ -0,0 +1,152 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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 module implements the mdb commands in the "table_io" category.
+**
+** The structure of these files is:
+**
+** - all the #includes
+** - local macros and declarations of local static functions
+** - one function for each command in the category
+** - any auxiliary functions
+** - any command argument strings
+** - option processing functions.
+*/
+
+#include "mercury_std.h"
+#include "mercury_getopt.h"
+
+#include "mercury_trace_internal.h"
+#include "mercury_trace_cmds.h"
+#include "mercury_trace_cmd_table_io.h"
+
+/****************************************************************************/
+
+static  void        MR_print_unsigned_var(FILE *fp, const char *var,
+                        MR_Unsigned value);
+
+/****************************************************************************/
+
+MR_Next
+MR_trace_cmd_table_io(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
+    MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
+    if (word_count == 1) {
+        if (! MR_io_tabling_allowed) {
+            fprintf(MR_mdb_err,
+                "This executable wasn't prepared for I/O tabling.\n");
+            return KEEP_INTERACTING;
+        }
+
+        if (MR_io_tabling_phase == MR_IO_TABLING_BEFORE) {
+            fprintf(MR_mdb_out, "I/O tabling has not yet started.\n");
+        } else if (MR_io_tabling_phase == MR_IO_TABLING_DURING) {
+            fprintf(MR_mdb_out, "I/O tabling has started.\n");
+        } else if (MR_io_tabling_phase == MR_IO_TABLING_AFTER) {
+            fprintf(MR_mdb_out, "I/O tabling has stopped.\n");
+        } else {
+            MR_fatal_error("I/O tabling in impossible phase.\n");
+        }
+    } else if (word_count == 2 &&
+        (MR_streq(words[1], "start") || MR_streq(words[1], "begin")))
+    {
+        if (! MR_io_tabling_allowed) {
+            fprintf(MR_mdb_err,
+                "This executable wasn't prepared for I/O tabling.\n");
+            return KEEP_INTERACTING;
+        }
+
+        if (MR_io_tabling_phase == MR_IO_TABLING_BEFORE) {
+            MR_io_tabling_phase = MR_IO_TABLING_DURING;
+            MR_io_tabling_start = MR_io_tabling_counter;
+            MR_io_tabling_end = MR_IO_ACTION_MAX;
+            MR_io_tabling_start_event_num = event_info->MR_event_number;
+#ifdef  MR_DEBUG_RETRY
+            MR_io_tabling_debug = MR_TRUE;
+#endif
+            fprintf(MR_mdb_out, "I/O tabling started.\n");
+        } else if (MR_io_tabling_phase == MR_IO_TABLING_DURING) {
+            fprintf(MR_mdb_out, "I/O tabling has already started.\n");
+        } else if (MR_io_tabling_phase == MR_IO_TABLING_AFTER) {
+            fprintf(MR_mdb_out, "I/O tabling has already stopped.\n");
+        } else {
+            MR_fatal_error("I/O tabling in impossible phase.\n");
+        }
+    } else if (word_count == 2 &&
+        (MR_streq(words[1], "stop") || MR_streq(words[1], "end")))
+    {
+        if (! MR_io_tabling_allowed) {
+            fprintf(MR_mdb_err,
+                "This executable wasn't prepared for I/O tabling.\n");
+            return KEEP_INTERACTING;
+        }
+
+        if (MR_io_tabling_phase == MR_IO_TABLING_BEFORE) {
+            fprintf(MR_mdb_out, "I/O tabling has not yet started.\n");
+        } else if (MR_io_tabling_phase == MR_IO_TABLING_DURING) {
+            MR_io_tabling_phase = MR_IO_TABLING_AFTER;
+            MR_io_tabling_end = MR_io_tabling_counter_hwm;
+            MR_io_tabling_stop_event_num = event_info->MR_event_number;
+            fprintf(MR_mdb_out, "I/O tabling stopped.\n");
+        } else if (MR_io_tabling_phase == MR_IO_TABLING_AFTER) {
+            fprintf(MR_mdb_out, "I/O tabling has already stopped.\n");
+        } else {
+            MR_fatal_error("I/O tabling in impossible phase.\n");
+        }
+    } else if (word_count == 2 && MR_streq(words[1], "stats")) {
+        if (! MR_io_tabling_allowed) {
+            fprintf(MR_mdb_err,
+                "This executable wasn't prepared for I/O tabling.\n");
+            return KEEP_INTERACTING;
+        }
+
+        fprintf(MR_mdb_out, "phase = %d\n", MR_io_tabling_phase);
+        MR_print_unsigned_var(MR_mdb_out, "counter", MR_io_tabling_counter);
+        MR_print_unsigned_var(MR_mdb_out, "hwm", MR_io_tabling_counter_hwm);
+        MR_print_unsigned_var(MR_mdb_out, "start", MR_io_tabling_start);
+        MR_print_unsigned_var(MR_mdb_out, "end", MR_io_tabling_end);
+    } else if (word_count == 2 && MR_streq(words[1], "allow")) {
+        /*
+        ** The "table_io allow" command allows the programmer to give
+        ** the command "table_io start" even in grades in which there
+        ** is no guarantee that all I/O primitives are tabled. It is
+        ** for developers only, because if it is used on programs in
+        ** which some but not all I/O primitives are tabled, the
+        ** results of turning on I/O tabling can be weird.
+        */
+
+        MR_io_tabling_allowed = MR_TRUE;
+    } else {
+        MR_trace_usage_cur_cmd();
+    }
+
+    return KEEP_INTERACTING;
+}
+
+/****************************************************************************/
+
+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);
+}
+
+/****************************************************************************/
+
+/*
+** "table_io allow" is deliberately not documented as it is developer only.
+** "table_io begin" and "table_io end" are deliberately not documented in an
+** effort to encourage consistent use of start/stop.
+*/
+
+const char *const    MR_trace_table_io_cmd_args[] =
+    { "stats", "start", "stop", NULL };
+
+/****************************************************************************/
Index: trace/mercury_trace_cmd_table_io.h
===================================================================
RCS file: trace/mercury_trace_cmd_table_io.h
diff -N trace/mercury_trace_cmd_table_io.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmd_table_io.h	3 Apr 2006 11:31:28 -0000
@@ -0,0 +1,16 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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.
+*/
+
+#include "mercury_imp.h"
+
+#include "mercury_trace_cmds.h"
+
+extern  MR_TraceCmdFunc     MR_trace_cmd_table_io;
+
+extern  const char *const   MR_trace_table_io_cmd_args[];
Index: trace/mercury_trace_cmds.h
===================================================================
RCS file: trace/mercury_trace_cmds.h
diff -N trace/mercury_trace_cmds.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ trace/mercury_trace_cmds.h	3 Apr 2006 12:43:30 -0000
@@ -0,0 +1,58 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 1998-2006 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.
+*/
+
+#include "mercury_std.h"
+#include "mercury_types.h"
+
+#include "mercury_trace.h"
+#include "mercury_trace_completion.h"
+
+#ifndef MERCURY_TRACE_CMDS_H
+#define MERCURY_TRACE_CMDS_H
+
+typedef enum {
+    KEEP_INTERACTING,
+    STOP_INTERACTING
+} MR_Next;
+
+typedef MR_Next MR_TraceCmdFunc(char **words, int word_count,
+                    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
+                    MR_Code **jumpaddr);
+
+/*
+** We keep a table of the available commands. The information we have about
+** each command is stored in a value of type MR_Trace_Command_Info.
+**
+** The name of the command itself is stored in the name field; the category
+** field contains name of the category to which the command belongs,
+** e.g. "browsing".
+**
+** The code that the command loop should execute to handle a command of a given
+** type is the function pointed to by the function field.
+**
+** Some commands take fixed strings as arguments. The arg_strings field
+** is a NULL terminated array of those strings, or NULL if there are
+** no fixed strings.
+**
+** The arg_completer field contains the address of a function for more
+** arbitrary completion, e.g. on predicate names. This field should not be
+** null; if the command cannot use a completion function, the field should
+** contain MR_trace_null_completer.
+*/
+
+typedef struct
+{
+    const char                  *MR_cmd_category;
+    const char                  *MR_cmd_name;
+    MR_TraceCmdFunc             *MR_cmd_function;
+    const char *const           *MR_cmd_arg_strings;
+    const MR_Make_Completer     MR_cmd_arg_completer;
+} MR_Trace_Command_Info;
+
+#endif  /* MERCURY_TRACE_CMDS_H */
Index: trace/mercury_trace_external.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_external.c,v
retrieving revision 1.79
diff -u -b -r1.79 mercury_trace_external.c
--- trace/mercury_trace_external.c	8 Feb 2006 21:54:33 -0000	1.79
+++ trace/mercury_trace_external.c	3 Apr 2006 09:30:49 -0000
@@ -1,4 +1,7 @@
 /*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
 ** Copyright (C) 1998-2006 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.
@@ -57,49 +60,79 @@
 */
 
 typedef enum {
-	MR_REQUEST_HELLO_REPLY   = 0, /* initiate debugging session	      */
-	MR_REQUEST_FORWARD_MOVE  = 1, /* go to the next matching trace event  */
-	MR_REQUEST_CURRENT_VARS  = 2, /* report data for current_vars query   */
-	MR_REQUEST_CURRENT_SLOTS = 3, /* report data for current_slots query  */
-	MR_REQUEST_NO_TRACE      = 4, /* continue to end, not tracing	      */
-	MR_REQUEST_ABORT_PROG    = 5, /* abort the current execution	      */
-	MR_REQUEST_ERROR         = 6, /* something went wrong                 */
-	MR_REQUEST_CURRENT_LIVE_VAR_NAMES  
-				 = 7, /* report data for 
-					 current_live_var_names query	      */
-	MR_REQUEST_CURRENT_NTH_VAR 
-				 = 8, /* report data for 
-					 current_nth_var query		      */
-	MR_REQUEST_RETRY	 = 9, /* restart the execution to the call 
-					 port of the current event	      */
-	MR_REQUEST_STACK         = 10,/* print the ancestors list             */
-	MR_REQUEST_NONDET_STACK  = 11,/* print the nondet stack		      */
-	MR_REQUEST_STACK_REGS    = 12,/* prints the contents of the virtual
-							   machine registers. */
-	MR_REQUEST_INTERACTIVE_QUERY_NORMAL	 
-				 = 13,/* wait for a normal interactive query  */
-	MR_REQUEST_INTERACTIVE_QUERY_CC	 
-				 = 14,/* wait for a cc interactive query      */
-	MR_REQUEST_INTERACTIVE_QUERY_IO	 
-				 = 15,/* wait for a io interactive query      */
-	MR_REQUEST_MMC_OPTIONS	 = 16,/* pass down new options to compile
-					 queries with			      */
-	MR_REQUEST_BROWSE	 = 17,/* call the term browser	              */
-	MR_REQUEST_LINK_COLLECT	 = 18,/* dynamically link the collect module  */
-	MR_REQUEST_COLLECT	 = 19,/* collecting monitoring informations   */
-	MR_REQUEST_CURRENT_GRADE = 20,/* retrieving the grade of the current
-					 program has been compiled with       */
-	MR_REQUEST_COLLECT_ARG_ON
-				 = 21,/* switch the arguments collecting on   */
-	MR_REQUEST_COLLECT_ARG_OFF
-				 = 22 /* switch the arguments collecting off  */
+    /* initiate debugging session */
+    MR_REQUEST_HELLO_REPLY              = 0,
+
+    /* go to the next matching trace event */
+    MR_REQUEST_FORWARD_MOVE             = 1,
+
+    /* report data for current_vars query */
+    MR_REQUEST_CURRENT_VARS             = 2,
+
+    /* report data for current_slots query */
+    MR_REQUEST_CURRENT_SLOTS            = 3,
+
+    /* continue to end, not tracing */
+    MR_REQUEST_NO_TRACE                 = 4,
+
+    /* abort the current execution */
+    MR_REQUEST_ABORT_PROG               = 5,
+
+    /* something went wrong */
+    MR_REQUEST_ERROR                    = 6,
+
+    /* report data for current_live_var_names query */
+    MR_REQUEST_CURRENT_LIVE_VAR_NAMES   = 7,
+
+    /* report data for current_nth_var query */
+    MR_REQUEST_CURRENT_NTH_VAR          = 8,
+
+    /* restart the execution to the call port of the current event */
+    MR_REQUEST_RETRY                    = 9,
+
+    /* print the ancestors list */
+    MR_REQUEST_STACK                    = 10,
+
+    /* print the nondet stack */
+    MR_REQUEST_NONDET_STACK             = 11,
+
+    /* prints the contents of the virtual machine registers. */
+    MR_REQUEST_STACK_REGS               = 12,
+
+    /* wait for a normal interactive query */
+    MR_REQUEST_INTERACTIVE_QUERY_NORMAL = 13,
+
+    /* wait for a cc interactive query */
+    MR_REQUEST_INTERACTIVE_QUERY_CC     = 14,
+
+    /* wait for a io interactive query */
+    MR_REQUEST_INTERACTIVE_QUERY_IO     = 15,
+    /* pass down new options to compile queries with */
+    MR_REQUEST_MMC_OPTIONS              = 16,
+
+    /* call the term browser */
+    MR_REQUEST_BROWSE                   = 17,
+    /* dynamically link the collect module */
+    MR_REQUEST_LINK_COLLECT             = 18,
+
+    /* collecting monitoring informations */
+    MR_REQUEST_COLLECT                  = 19,
+
+    /* retrieving the grade of the current program has been compiled with */
+    MR_REQUEST_CURRENT_GRADE            = 20,
+
+    /* switch the arguments collecting on */
+    MR_REQUEST_COLLECT_ARG_ON           = 21,
+
+    /* switch the arguments collecting off */
+    MR_REQUEST_COLLECT_ARG_OFF          = 22
 
 } MR_debugger_request_type;
 
 MercuryFile MR_debugger_socket_in;
 MercuryFile MR_debugger_socket_out;
 
-static MR_String	MR_mmc_options;
+static MR_String    MR_external_mmc_options;
 
 /*
 ** Type of a static variable that indicates in which mode the external 
@@ -107,8 +140,10 @@
 ** (1) `MR_searching', it tries to find an event that matches a forward 
 **      move request,
 ** (2) `MR_reading_request', it reads a new request on the socket,
-** (3) `MR_collecting', it is collecting information (after a `collect' request).
+** (3) `MR_collecting', it is collecting information (after a `collect'
+**     request).
 */
+
 typedef enum {
 	MR_searching, MR_reading_request, MR_collecting
 } MR_external_debugger_mode_type;
@@ -162,25 +197,24 @@
 ** (See the "Function attributes" section of "C extensions"
 ** chapter of the GNU C manual for detailed documentation.)
 */
+
 #ifdef __GNUC__
   #define MR_LIKE_PRINTF(format_argnum, vars_argnum) \
     __attribute__ ((format (printf, (format_argnum), (vars_argnum))))
 #else
   #define MR_LIKE_PRINTF(n, m) /* nothing */
 #endif
+
 static void MR_send_message_to_socket_format(const char *format, ...)
 	MR_LIKE_PRINTF(1, 2);
 
 static void	MR_send_message_to_socket(const char *message);
-static void	MR_read_request_from_socket(
-			MR_Word *debugger_request_ptr, 
+static void     MR_read_request_from_socket(MR_Word *debugger_request_ptr, 
 			MR_Integer *debugger_request_type_ptr);
 	
 static MR_bool	MR_found_match(const MR_Label_Layout *layout,
-			MR_Trace_Port port, MR_Unsigned seqno,
-			MR_Unsigned depth,
-			/* XXX registers */
-			const char *path, MR_Word search_data);
+                    MR_Trace_Port port, MR_Unsigned seqno, MR_Unsigned depth,
+                    /* XXX registers */ const char *path, MR_Word search_data);
 static void	MR_output_current_slots(const MR_Label_Layout *layout,
 			MR_Trace_Port port, MR_Unsigned seqno,
 			MR_Unsigned depth, const char *path, int lineno);
@@ -194,8 +228,7 @@
 static MR_Word	MR_trace_make_nth_var(MR_Word debugger_request);
 static int	MR_get_var_number(MR_Word debugger_request);
 static void	MR_print_proc_id_to_socket(const MR_Proc_Layout *entry,
-			const char *extra,
-			MR_Word *base_sp, MR_Word *base_curfr);
+                    const char *extra, MR_Word *base_sp, MR_Word *base_curfr);
 static void	MR_dump_stack_record_print_to_socket(FILE *fp, 
 			const MR_Proc_Layout *entry_layout, int count,
 			int start_level, MR_Word *base_sp, MR_Word *base_curfr,
@@ -283,15 +316,16 @@
 	char *inet_socket;
 	struct sockaddr_un unix_address;
 	struct sockaddr_in inet_address;
-	struct sockaddr* addr;
+    struct sockaddr     *addr;
 	MR_Word debugger_request;
 	MR_Integer debugger_request_type;
 
 	/* 
-	** MR_mmc_options contains the options to pass to mmc when compiling 
-	** queries. We initialize it to the MR_String "".
+    ** MR_external_mmc_options contains the options to pass to mmc
+    ** when compiling queries. We initialize it to the MR_String "".
 	*/
-	MR_TRACE_CALL_MERCURY(ML_DI_init_mercury_string(&MR_mmc_options));
+
+    MR_TRACE_CALL_MERCURY(ML_DI_init_mercury_string(&MR_external_mmc_options));
 
 	/*
 	** We presume that the user's program has been invoked from
@@ -301,6 +335,7 @@
 	** environment variable to tell the user's program which socket
 	** it needs to connect to.
 	*/
+
 	unix_socket = getenv("MERCURY_DEBUGGER_UNIX_SOCKET");
 	inet_socket = getenv("MERCURY_DEBUGGER_INET_SOCKET");
 	if (unix_socket == NULL && inet_socket == NULL) {
@@ -520,8 +555,7 @@
 			if (MR_found_match(layout, port, seqno, depth,
 				/* XXX registers, */ path, search_data))
 			{
-				MR_send_message_to_socket(
-					"forward_move_match_found");
+                MR_send_message_to_socket("forward_move_match_found");
 				external_debugger_mode = MR_reading_request;
 			} else {
 				goto done;
@@ -544,8 +578,7 @@
 
 	/* loop to process requests read from the debugger socket */
 	for(;;) {
-		MR_read_request_from_socket(
-			&debugger_request, &debugger_request_type);
+        MR_read_request_from_socket(&debugger_request, &debugger_request_type);
 		switch((int) debugger_request_type) {
 			case MR_REQUEST_ABORT_PROG:
 				exit(EXIT_SUCCESS);
@@ -562,14 +595,11 @@
 			case MR_REQUEST_CURRENT_LIVE_VAR_NAMES:
 				if (MR_debug_socket) {
 					fprintf(stderr, "\nMercury runtime: "
-						"MR_REQUEST_CURRENT_LIVE_VAR"
-						"_NAMES\n");
+                        "MR_REQUEST_CURRENT_LIVE_VAR_NAMES\n");
 				}
-				var_names_list = 
-					MR_trace_make_var_names_list();
+                var_names_list = MR_trace_make_var_names_list();
 				type_list = MR_trace_make_type_list();
-				MR_output_current_live_var_names(var_names_list,
-					type_list);
+                MR_output_current_live_var_names(var_names_list, type_list);
 				break;
 
 			case MR_REQUEST_CURRENT_VARS:
@@ -578,10 +608,8 @@
 						"REQUEST_CURRENT_VARS\n");
 				}
 				var_list = MR_trace_make_var_list();
-				var_names_list = 
-					MR_trace_make_var_names_list();
-				MR_output_current_vars(var_list, 
-						       var_names_list);
+                var_names_list = MR_trace_make_var_names_list();
+                MR_output_current_vars(var_list, var_names_list);
 				break;
 
 			case MR_REQUEST_CURRENT_NTH_VAR:
@@ -592,13 +620,14 @@
 				var = MR_trace_make_nth_var(debugger_request);
 				MR_output_current_nth_var(var);
 				break;			
+
 			case MR_REQUEST_CURRENT_SLOTS:
 				if (MR_debug_socket) {
 					fprintf(stderr, "\nMercury runtime: "
 						"REQUEST_CURRENT_SLOTS\n");
 				}
-				MR_output_current_slots(layout, port, seqno, 
-					depth, path, lineno);
+                MR_output_current_slots(layout, port, seqno, depth, path,
+                    lineno);
 				break;
 
 			case MR_REQUEST_RETRY:
@@ -606,19 +635,18 @@
 					fprintf(stderr, "\nMercury runtime: "
 						"REQUEST_RETRY\n");
 				}
+
 				retry_result = MR_trace_retry(event_info, 0,
-					MR_RETRY_IO_ONLY_IF_SAFE, 
-					MR_FALSE, "", &unsafe_retry, 
+                    MR_RETRY_IO_ONLY_IF_SAFE, MR_FALSE, "", &unsafe_retry, 
 					&message, NULL, NULL, &jumpaddr);
 				if (retry_result == MR_RETRY_OK_DIRECT) {
 					MR_send_message_to_socket("ok");
 					cmd->MR_trace_cmd = MR_CMD_GOTO;
-					cmd->MR_trace_stop_event = 
-						MR_trace_event_number + 1;
+                    cmd->MR_trace_stop_event = MR_trace_event_number + 1;
 					goto done;
 				} else {
-					MR_send_message_to_socket_format(
-						"error(\"%s\").\n", message);
+                    MR_send_message_to_socket_format("error(\"%s\").\n",
+                        message);
 				}
 				break;
 				
@@ -628,16 +656,14 @@
 						"REQUEST_STACK\n");
 				}
 				MR_trace_init_modules();
-				message = MR_dump_stack_from_layout(
-					stdout, layout,
-					MR_saved_sp(saved_regs),
-					MR_saved_curfr(saved_regs),
+                message = MR_dump_stack_from_layout(stdout, layout,
+                    MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs),
 					include_trace_data, MR_FALSE, 0, 0,
 					&MR_dump_stack_record_print_to_socket);
 				MR_send_message_to_socket("end_stack");
 				if (message != NULL) {
-					MR_send_message_to_socket_format(
-						"error(\"%s\").\n", message);
+                    MR_send_message_to_socket_format("error(\"%s\").\n",
+                        message);
 				} else {
 					MR_send_message_to_socket("ok");
 				}
@@ -650,14 +676,12 @@
 				}
 				MR_trace_init_modules();
 				/* 
-			        ** XXX As in stack dump, we could send the
-				** output of this function on the socket. But
-				** the outputs are done via fprintf() and
-				** printlabel(), so we would need to define new
-				** fprintf() and printlabel() and pass them
-				** down as parameters of
-				** MR_dump_nondet_stack() (as we do
-				** with MR_dump_stack_record_print()).
+                ** XXX As in stack dump, we could send the output of this
+                ** function on the socket. But the outputs are done via
+                ** fprintf() and printlabel(), so we would need to define new
+                ** fprintf() and printlabel() and pass them down as parameters
+                ** of MR_dump_nondet_stack() (as we do with
+                ** MR_dump_stack_record_print()).
 				*/						
 				MR_dump_nondet_stack(stdout, NULL, 0, 0,
 					MR_saved_maxfr(saved_regs));
@@ -671,25 +695,20 @@
 				}
 				MR_send_message_to_socket_format(
 					"stack_regs(%lu, %lu, %lu).\n",
-					(unsigned long)
-					MR_saved_sp(saved_regs),
-					(unsigned long)
-					MR_saved_curfr(saved_regs),
-					(unsigned long)
-					MR_saved_maxfr(saved_regs));
+                    (unsigned long) MR_saved_sp(saved_regs),
+                    (unsigned long) MR_saved_curfr(saved_regs),
+                    (unsigned long) MR_saved_maxfr(saved_regs));
 				break;
 			
 			case MR_REQUEST_INTERACTIVE_QUERY_NORMAL:
 				if (MR_debug_socket) {
 					fprintf(stderr, "\nMercury runtime: "
-						"REQUEST_INTERACTIVE_QUERY"
-						"_NORMAL\n");
+                        "REQUEST_INTERACTIVE_QUERY_NORMAL\n");
 				}
-				MR_get_list_modules_to_import(
-					debugger_request, &modules_list_length,
-					&modules_list);
+                MR_get_list_modules_to_import(debugger_request,
+                    &modules_list_length, &modules_list);
 				MR_trace_query_external(MR_NORMAL_QUERY, 
-					MR_mmc_options, modules_list_length, 
+                    MR_external_mmc_options, modules_list_length, 
 					modules_list);
 				break;
 
@@ -698,12 +717,10 @@
 					fprintf(stderr, "\nMercury runtime: "
 						"REQUEST_INTERACTIVE_QUERY_IO\n");
 				}
-				MR_get_list_modules_to_import(
-					debugger_request, &modules_list_length,
-					&modules_list);
-				MR_trace_query_external(MR_IO_QUERY, 
-					MR_mmc_options, modules_list_length, 
-					modules_list);
+                MR_get_list_modules_to_import(debugger_request,
+                    &modules_list_length, &modules_list);
+                MR_trace_query_external(MR_IO_QUERY, MR_external_mmc_options,
+                    modules_list_length, modules_list);
 				break;
 
 			case MR_REQUEST_INTERACTIVE_QUERY_CC:
@@ -711,12 +728,10 @@
 					fprintf(stderr, "\nMercury runtime: "
 						"REQUEST_INTERACTIVE_QUERY_CC\n");
 				}
-				MR_get_list_modules_to_import(
-					debugger_request, &modules_list_length,
-					&modules_list);
-				MR_trace_query_external(MR_CC_QUERY, 
-					MR_mmc_options, modules_list_length, 
-					modules_list);
+                MR_get_list_modules_to_import(debugger_request,
+                    &modules_list_length, &modules_list);
+                MR_trace_query_external(MR_CC_QUERY, MR_external_mmc_options,
+                    modules_list_length, modules_list);
 				break;
 
 			case MR_REQUEST_MMC_OPTIONS:
@@ -724,8 +739,7 @@
 					fprintf(stderr, "\nMercury runtime: "
 						"REQUEST_MMC_OPTIONS\n");
 				}
-				MR_get_mmc_options(debugger_request, 
-					&MR_mmc_options);
+                MR_get_mmc_options(debugger_request, &MR_external_mmc_options);
 				MR_send_message_to_socket("mmc_options_ok");
 				break;
 
@@ -738,14 +752,14 @@
 					fprintf(stderr, "\nMercury runtime: "
 						"REQUEST_BROWSE\n");
 				}
-				MR_get_variable_name(debugger_request, 
-					&var_name);
+                    MR_get_variable_name(debugger_request, &var_name);
 				var_spec.MR_var_spec_kind = MR_VAR_SPEC_NAME;
 				var_spec.MR_var_spec_name = var_name;
 				MR_trace_browse_one_external(var_spec);
 				MR_send_message_to_socket("browser_end");
 				break;
 			  }
+
 			case MR_REQUEST_NO_TRACE:
 				cmd->MR_trace_cmd = MR_CMD_TO_END;
 				external_debugger_mode = MR_searching;
@@ -763,8 +777,7 @@
 				MR_get_object_file_name(debugger_request,
 					    &MR_object_file_name);
 				MR_TRACE_CALL_MERCURY(
-					ML_CL_link_collect(
-			       		    MR_object_file_name,
+                        ML_CL_link_collect(MR_object_file_name,
 					    (MR_Word *) &cmd->MR_filter_ptr,
 					    (MR_Word *) &initialize_ptr,
 					    (MR_Word *) &post_process_ptr,
@@ -772,51 +785,45 @@
 					    (MR_Word *) &get_collect_var_type_ptr,
 					    &collect_lib_maybe_handle,
 					    &result
-					    ));
+                        )
+                    );
 				collect_linked = (result == 'y');
 				if (collect_linked) {
-					MR_send_message_to_socket(
-						"link_collect_succeeded");
+                        MR_send_message_to_socket("link_collect_succeeded");
 					MR_TRACE_CALL_MERCURY(
 					    (*get_collect_var_type_ptr)(
 						&MR_accumulator_variable_type));
-					MR_accumulator_variable = 
-					    MR_make_permanent(
+                        MR_accumulator_variable = MR_make_permanent(
 						MR_accumulator_variable,
-						(MR_TypeInfo) 
-						MR_accumulator_variable_type);
+                            (MR_TypeInfo) MR_accumulator_variable_type);
 				} else {
-					MR_send_message_to_socket(
-						"link_collect_failed");
+                        MR_send_message_to_socket("link_collect_failed");
 				}
 				break;
 			  }
 			case MR_REQUEST_COLLECT:
-			  {
 				if (MR_debug_socket) {
 					fprintf(stderr, "\nMercury runtime: "
 						"REQUEST_COLLECT\n");
 				}
 				if (collect_linked) {
-					MR_send_message_to_socket(
-						"collect_linked");
+                    MR_send_message_to_socket("collect_linked");
 					external_debugger_mode = MR_collecting;
 					MR_TRACE_CALL_MERCURY(
-					  (*initialize_ptr)(&MR_accumulator_variable));
+                        (*initialize_ptr)(&MR_accumulator_variable)
+                    );
 
 					/*
-					** In order to perform the collect from
-					** the current event, we need to call 
-					** filter once here.
+                    ** In order to perform the collect from the current
+                    ** event, we need to call filter once here.
 					*/
-					MR_COLLECT_filter(cmd->MR_filter_ptr,
-						seqno, depth, port, layout, path, 
-						lineno, &stop_collecting);
+
+                    MR_COLLECT_filter(cmd->MR_filter_ptr, seqno, depth,
+                        port, layout, path, lineno, &stop_collecting);
 
 					if (stop_collecting) {
 						MR_send_collect_result();
-						MR_send_message_to_socket(
-							"execution_continuing");
+                        MR_send_message_to_socket("execution_continuing");
 						break;
 					} else {
 					/*
@@ -824,38 +831,29 @@
 					** to MR_COLLECT_filter() are done in 
 					** MR_trace_real().
 					*/
-					        cmd->MR_trace_cmd =
-							MR_CMD_COLLECT;
-						cmd->MR_trace_must_check =
-							MR_FALSE;
+
+                        cmd->MR_trace_cmd = MR_CMD_COLLECT;
+                        cmd->MR_trace_must_check = MR_FALSE;
 						cmd->MR_trace_strict = MR_TRUE;
-						MR_init_trace_check_integrity(
-							cmd);
-						cmd->MR_trace_print_level = 
-						 	MR_PRINT_LEVEL_NONE;
+                        MR_init_trace_check_integrity(cmd);
+                        cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE;
 						goto done;
 					}
 				} else {
-					MR_send_message_to_socket(
-						"collect_not_linked");
+                    MR_send_message_to_socket("collect_not_linked");
 					break;
 				}
-			  }
 
 			case MR_REQUEST_CURRENT_GRADE:
-			  {
 				if (MR_debug_socket) {
 					fprintf(stderr, "\nMercury runtime: "
 						"REQUEST_CURRENT_GRADE\n");
 				}
-				MR_send_message_to_socket_format(
-						"grade(\"%s\").\n", 
+                MR_send_message_to_socket_format("grade(\"%s\").\n", 
 						MR_GRADE_OPT);
 				break;
-			  }
 
 			case MR_REQUEST_COLLECT_ARG_ON:
-			  {
 				if (MR_debug_socket) {
 					fprintf(stderr, "\nMercury runtime: "
 						"REQUEST_COLLECT_ARG_ON\n");
@@ -863,9 +861,8 @@
 				MR_collect_arguments = MR_TRUE;
 				MR_send_message_to_socket("collect_arg_on_ok");
 				break;
-			  }
+
 			case MR_REQUEST_COLLECT_ARG_OFF:
-			  {
 				if (MR_debug_socket) {
 					fprintf(stderr, "\nMercury runtime: "
 						"REQUEST_COLLECT_ARG_OFF\n");
@@ -873,7 +870,7 @@
 				MR_collect_arguments = MR_FALSE;
 				MR_send_message_to_socket("collect_arg_off_ok");
 				break;
-			  }
+
 			default:
 				MR_fatal_error("unexpected request read from "
 					"debugger socket");
@@ -955,9 +952,7 @@
 MR_output_current_vars(MR_Word var_list, MR_Word string_list)
 {
     MR_TRACE_CALL_MERCURY(
-	ML_DI_output_current_vars(
-		var_list,
-		string_list,
+        ML_DI_output_current_vars(var_list, string_list,
 		&MR_debugger_socket_out);
     );
 }
@@ -966,9 +961,7 @@
 MR_output_current_nth_var(MR_Word var)
 {
     MR_TRACE_CALL_MERCURY(
-	ML_DI_output_current_nth_var(
-		var,
-		&MR_debugger_socket_out);
+        ML_DI_output_current_nth_var(var, &MR_debugger_socket_out);
     );
 }
 
@@ -976,25 +969,20 @@
 MR_output_current_live_var_names(MR_Word var_names_list, MR_Word type_list)
 {
     MR_TRACE_CALL_MERCURY(
-	ML_DI_output_current_live_var_names(
-		var_names_list,
-		type_list,
+        ML_DI_output_current_live_var_names(var_names_list, type_list,
 		&MR_debugger_socket_out);
     );
 }
 
 static void
-MR_read_request_from_socket(
-			MR_Word *debugger_request_ptr, 
+MR_read_request_from_socket(MR_Word *debugger_request_ptr, 
 			MR_Integer *debugger_request_type_ptr)
 {		
 	fflush(MR_file(MR_debugger_socket_in));
 
     MR_TRACE_CALL_MERCURY(
-	ML_DI_read_request_from_socket(
-		&MR_debugger_socket_in, 
-		debugger_request_ptr, 
-		debugger_request_type_ptr);
+        ML_DI_read_request_from_socket(&MR_debugger_socket_in, 
+            debugger_request_ptr, debugger_request_type_ptr);
     );
 }
  
@@ -1053,6 +1041,7 @@
 			search_data);
 		    );
 	}
+
 	return result;
 }
 
@@ -1103,8 +1092,7 @@
 	);
 
 	for (i = var_count; i > 0; i--) {
-		problem = MR_trace_return_var_info(i, NULL,
-				&type_info, &value);
+        problem = MR_trace_return_var_info(i, NULL, &type_info, &value);
 		if (problem != NULL) {
 			MR_fatal_error(problem);
 		}
@@ -1194,8 +1182,8 @@
 			type_info_string = ML_type_name((MR_Word) type_info);
 		);
 	        MR_TRACE_USE_HP(
-			type_list = MR_string_list_cons(
-				(MR_Word) type_info_string, type_list);
+            type_list = MR_string_list_cons((MR_Word) type_info_string,
+                type_list);
 	        );
 	}
 
@@ -1217,11 +1205,9 @@
 	MR_Word		univ;
 
 	var_number = MR_get_var_number(debugger_request);
-		/* debugger_request should be of the form: 
-		   current_nth_var(var_number) */
+    /* debugger_request should be of the form: current_nth_var(var_number) */
 
-	problem = MR_trace_return_var_info(var_number, NULL,
-			&type_info, &value);
+    problem = MR_trace_return_var_info(var_number, NULL, &type_info, &value);
 	if (problem == NULL) {
 		MR_TRACE_USE_HP(
 			MR_new_univ_on_hp(univ, type_info, value);
@@ -1231,6 +1217,7 @@
 		** Should never occur since we check in the external debugger
 		** process if a variable is live before retrieving it.
 		*/
+
 		MR_fatal_error(problem);
 	}
 
@@ -1301,26 +1288,24 @@
 	if (base_sp != NULL && base_curfr != NULL) {
 		MR_bool print_details = MR_FALSE;
 		if (MR_PROC_LAYOUT_HAS_EXEC_TRACE(entry)) {
-			MR_Integer maybe_from_full =
-				entry->MR_sle_maybe_from_full;
+            MR_Integer maybe_from_full = entry->MR_sle_maybe_from_full;
 			if (maybe_from_full > 0) {
 				/*
-				** for procedures compiled with shallow
-				** tracing, the details will be valid only
-				** if the value of MR_from_full saved in
+                ** For procedures compiled with shallow tracing, the details
+                ** will be valid only if the value of MR_from_full saved in
 				** the appropriate stack slot was MR_TRUE.
 				*/
 				if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
-					print_details = MR_based_stackvar(
-						base_sp, maybe_from_full);
+                    print_details = MR_based_stackvar(base_sp,
+                        maybe_from_full);
 				} else {
-					print_details = MR_based_framevar(
-						base_curfr, maybe_from_full);
+                    print_details = MR_based_framevar(base_curfr,
+                        maybe_from_full);
 				}
 			} else {
 				/*
-				** for procedures compiled with full tracing,
-				** always print out the details
+                ** For procedures compiled with full tracing,
+                ** always print out the details.
 				*/
 				print_details = MR_TRUE;
 			}
@@ -1329,21 +1314,15 @@
 			if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
 				MR_send_message_to_socket_format( 
 					"detail(%lu, %lu, %lu).\n",
-					(unsigned long)
-					MR_event_num_stackvar(base_sp) + 1,
-					(unsigned long)
-					MR_call_num_stackvar(base_sp),
-					(unsigned long)
-					MR_call_depth_stackvar(base_sp));
+                    (unsigned long) MR_event_num_stackvar(base_sp) + 1,
+                    (unsigned long) MR_call_num_stackvar(base_sp),
+                    (unsigned long) MR_call_depth_stackvar(base_sp));
 			} else {
 				MR_send_message_to_socket_format( 
 					"detail(%lu, %lu, %lu).\n",
-					(unsigned long)
-					MR_event_num_framevar(base_curfr) + 1,
-					(unsigned long)
-					MR_call_num_framevar(base_curfr),
-					(unsigned long)
-					MR_call_depth_framevar(base_curfr));
+                    (unsigned long) MR_event_num_framevar(base_curfr) + 1,
+                    (unsigned long) MR_call_num_framevar(base_curfr),
+                    (unsigned long) MR_call_depth_framevar(base_curfr));
 			}
 		} 
 	}
@@ -1368,9 +1347,7 @@
 	} else {
 		if (entry->MR_sle_user.MR_user_pred_or_func == MR_PREDICATE) {
 			MR_send_message_to_socket("pred");
-		} else if (entry->MR_sle_user.MR_user_pred_or_func ==
-				MR_FUNCTION)
-		{
+        } else if (entry->MR_sle_user.MR_user_pred_or_func == MR_FUNCTION) {
 			MR_send_message_to_socket("func");
 		} else {
 			MR_fatal_error("procedure is not pred or func");
@@ -1387,8 +1364,7 @@
 		if (strcmp(entry->MR_sle_user.MR_user_decl_module,
 				entry->MR_sle_user.MR_user_def_module) != 0)
 		{
-			MR_send_message_to_socket_format(
-				"def_module(\"%s\").\n",
+            MR_send_message_to_socket_format("def_module(\"%s\").\n",
 				entry->MR_sle_user.MR_user_def_module);
 		}
 	}
@@ -1403,10 +1379,8 @@
 	MR_Integer *modules_list_length_ptr, MR_Word *modules_list_ptr)
 {
 	MR_TRACE_CALL_MERCURY(
-		ML_DI_get_list_modules_to_import(
-			debugger_request, 
-			modules_list_length_ptr, 
-			modules_list_ptr);
+        ML_DI_get_list_modules_to_import(debugger_request, 
+            modules_list_length_ptr, modules_list_ptr);
 		);
 }
 
@@ -1414,19 +1388,16 @@
 MR_get_mmc_options(MR_Word debugger_request, MR_String *mmc_options_ptr)
 {
 	MR_TRACE_CALL_MERCURY(
-		ML_DI_get_mmc_options(
-			debugger_request, 
-			mmc_options_ptr);
+        ML_DI_get_mmc_options(debugger_request, mmc_options_ptr);
 		);
 }
 
 static void
-MR_get_object_file_name(MR_Word debugger_request, MR_String *object_file_name_ptr)
+MR_get_object_file_name(MR_Word debugger_request,
+    MR_String *object_file_name_ptr)
 {
 	MR_TRACE_CALL_MERCURY(
-		ML_DI_get_object_file_name(
-			debugger_request, 
-			object_file_name_ptr);
+        ML_DI_get_object_file_name(debugger_request, object_file_name_ptr);
 		);
 }
 
@@ -1434,9 +1405,7 @@
 MR_get_variable_name(MR_Word debugger_request, MR_String *var_name_ptr)
 {
 	MR_TRACE_CALL_MERCURY(
-		ML_DI_get_variable_name(
-			debugger_request, 
-			var_name_ptr);
+        ML_DI_get_variable_name(debugger_request, var_name_ptr);
 		);
 }
 
@@ -1506,13 +1475,15 @@
 		lineno,
 		MR_accumulator_variable,
 		&MR_accumulator_variable,
-		&result));
+        &result)
+    );
 	*stop_collecting = (result == 'y');
 }
 
 /*
 ** This function retrieves the line number of the current goal.
 */
+
 int
 MR_get_line_number(MR_Word *saved_regs, const MR_Label_Layout *layout, 
 	MR_Trace_Port port)
@@ -1521,25 +1492,26 @@
 	const MR_Label_Layout	*parent_layout;
 	const char		*problem; 
 	int			lineno = 0;
-	MR_Word			*base_sp, *base_curfr;
+    MR_Word                 *base_sp;
+    MR_Word                 *base_curfr;
 
-	if MR_port_is_interface(port)
+    if MR_port_is_interface(port) {
 	/* 
-	** At external events, we want the line number 
-	** where the call is made, not the one where the 
-	** procedure is defined.
+        ** At external events, we want the line number where the call is made,
+        ** not the one where the procedure is defined.
 	*/
-	{
+
 		base_sp = MR_saved_sp(saved_regs);
 		base_curfr = MR_saved_curfr(saved_regs);
-		parent_layout = MR_find_nth_ancestor(layout, 1,
-			&base_sp, &base_curfr, &problem);
+        parent_layout = MR_find_nth_ancestor(layout, 1, &base_sp, &base_curfr,
+            &problem);
 		if (parent_layout != NULL) {
 			(void) MR_find_context(parent_layout, &filename, &lineno);
 		}
 	} else {
 		(void) MR_find_context(layout, &filename, &lineno);
-	} ;
+    }
+
 	return lineno;
 }
 
@@ -1547,16 +1519,15 @@
 MR_send_collect_result(void)
 {
 	MR_TRACE_CALL_MERCURY(
-		(*post_process_ptr)(
-			MR_accumulator_variable, 
-			&MR_collected_variable);
+        (*post_process_ptr)(MR_accumulator_variable, &MR_collected_variable);
+
+        (*send_collect_result_ptr)(MR_collected_variable, 
+            (MR_Word) &MR_debugger_socket_out)
+    );
 
-		(*send_collect_result_ptr)(
-			MR_collected_variable, 
-			(MR_Word) &MR_debugger_socket_out));
 #if defined(MR_HAVE_DLFCN_H) && defined(MR_HAVE_DLCLOSE)
-	MR_TRACE_CALL_MERCURY(
-       		ML_CL_unlink_collect(collect_lib_maybe_handle));
+    MR_TRACE_CALL_MERCURY(ML_CL_unlink_collect(collect_lib_maybe_handle));
 #endif
 }
+
 #endif /* MR_USE_EXTERNAL_DEBUGGER */
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.222
diff -u -b -r1.222 mercury_trace_internal.c
--- trace/mercury_trace_internal.c	31 Mar 2006 05:12:18 -0000	1.222
+++ trace/mercury_trace_internal.c	3 Apr 2006 12:38:24 -0000
@@ -8,7 +8,9 @@
 */
 
 /*
-** This file contains the code of the internal, in-process debugger.
+** This file contains the top level of the code of the internal, in-process
+** debugger. The functions implementing the commands themselves are in the
+** files mercury_trac_cmd_*.c.
 **
 ** Main author: Zoltan Somogyi.
 */
@@ -23,6 +25,7 @@
 
 #include "mercury_trace.h"
 #include "mercury_trace_internal.h"
+#include "mercury_trace_cmds.h"
 #include "mercury_trace_declarative.h"
 #include "mercury_trace_alias.h"
 #include "mercury_trace_help.h"
@@ -35,6 +38,19 @@
 #include "mercury_trace_readline.h"
 #include "mercury_trace_source.h"
 
+#include "mercury_trace_cmd_forward.h"
+#include "mercury_trace_cmd_backward.h"
+#include "mercury_trace_cmd_browsing.h"
+#include "mercury_trace_cmd_breakpoint.h"
+#include "mercury_trace_cmd_queries.h"
+#include "mercury_trace_cmd_table_io.h"
+#include "mercury_trace_cmd_parameter.h"
+#include "mercury_trace_cmd_help.h"
+#include "mercury_trace_cmd_dd.h"
+#include "mercury_trace_cmd_misc.h"
+#include "mercury_trace_cmd_exp.h"
+#include "mercury_trace_cmd_developer.h"
+
 #include "mdb.browse.mh"
 #include "mdb.listing.mh"
 #include "mdb.diff.mh"
@@ -86,28 +102,10 @@
 /* The initial size of arrays of words. */
 #define MR_INIT_WORD_COUNT  20
 
-/* The initial number of lines in documentation entries. */
-#define MR_INIT_DOC_CHARS   800
-
 /* An upper bound on the maximum number of characters in a number. */
 /* If a number has more than this many chars, the user is in trouble. */
 #define MR_NUMBER_LEN       80
 
-/*
-** The default number of lines to display for a dice.
-*/
-
-#define MR_DEFAULT_DICE_LINES   50
-
-/*
-** The message to print for retries through un-io-tabled areas, when
-** the MR_RETRY_IO_INTERACTIVE option is given.
-*/
-
-#define MR_UNTABLED_IO_RETRY_MESSAGE \
-    "Retry across I/O operations is not always safe.\n" \
-    "Are you sure you want to do it? "
-
 #define MDBRC_FILENAME      ".mdbrc"
 #define DEFAULT_MDBRC_FILENAME  "mdbrc"
 
@@ -141,32 +139,6 @@
 FILE    *MR_mdb_out;
 FILE    *MR_mdb_err;
 
-static  MR_Trace_Print_Level    MR_default_print_level = MR_PRINT_LEVEL_SOME;
-
-/*
-** These variables say (a) whether the printing of event sequences will pause
-** after each screenful of events, (b) how may events constitute a screenful
-** (although we count only events, not how many lines they take up), and (c)
-** how many events we have printed so far in this screenful.
-*/
-
-static  MR_bool     MR_scroll_control = MR_TRUE;
-static  int         MR_scroll_limit = 24;
-static  int         MR_scroll_next = 0;
-
-/*
-** This variable controls the number of stack frame lines printed by the stack
-** and nondet_stack commands if the user doesn't override it.
-*/
-
-static  int         MR_stack_default_line_limit = 0;
-
-/*
-** We echo each command just as it is executed iff this variable is MR_TRUE.
-*/
-
-static  MR_bool     MR_echo_commands = MR_FALSE;
-
 /*
 ** MR_have_mdb_window and MR_mdb_window_pid are set by
 ** mercury_trace_internal.c after the xterm window for
@@ -184,258 +156,14 @@
 ** The details of the source server, if any.
 */
 
-static  MR_Trace_Source_Server  MR_trace_source_server =
+MR_Trace_Source_Server  MR_trace_source_server =
     { NULL, NULL, MR_FALSE };
 
-/*
-** We print confirmation of commands (e.g. new aliases) if this is MR_TRUE.
-*/
-
-static  MR_bool     MR_trace_internal_interacting = MR_FALSE;
-
-/*
-** We include values of sometimes-useful types such as typeinfos in the set of
-** variables whose values we collect at events for possible later printing
-** only if MR_print_optionals is true.
-*/
-
-static  MR_bool     MR_print_optionals = MR_FALSE;
-
-/*
-** This variable holds either the name of a file which contains a list of
-** the file names of passing test case trace counts, or the name of a single
-** file of passing test case trace counts.
-*/
-
-static  char        *MR_dice_pass_trace_counts_file = NULL;
-
-/*
-** This variable holds either the name of a file which contains a list of
-** the file names of failing test case trace counts, or the name of a single
-** file of failing test case trace counts.
-*/
-
-static  char        *MR_dice_fail_trace_counts_file = NULL;
-
-/*
-** MR_context_position specifies whether we print context at events,
-** and if so, where.
-*/
-
-static  MR_Context_Position MR_context_position = MR_CONTEXT_AFTER;
-
-/*
-** MR_print_goal_paths specifies whether we print goal paths at events.
-*/
-
-static  MR_bool     MR_print_goal_paths = MR_TRUE;
-
-/*
-** MR_listing_path holds the current value of the listings structure
-** as defined in browser/listing.m.
-*/
-
-static  MR_Word     MR_listing_path;
-
-/*
-** MR_num_context_lines holds the current number of context lines to be
-** printed before and after the current callee/caller's file context.
-*/
-
-static  int         MR_num_context_lines = 2;
-
-typedef struct MR_Line_Struct {
-    char            *MR_line_contents;
-    struct MR_Line_Struct   *MR_line_next;
-} MR_Line;
+MR_bool     MR_trace_internal_interacting = MR_FALSE;
 
 static  MR_Line     *MR_line_head = NULL;
 static  MR_Line     *MR_line_tail = NULL;
 
-typedef enum {
-    KEEP_INTERACTING,
-    STOP_INTERACTING
-} MR_Next;
-
-static const char   *MR_context_set_msg[] = {
-    "Contexts will not be printed.",
-    "Contexts will be printed before, on the same line.",
-    "Contexts will be printed after, on the same line.",
-    "Contexts will be printed on the previous line.",
-    "Contexts will be printed on the next line.",
-};
-
-static const char   *MR_context_report_msg[] = {
-    "Contexts are not printed.",
-    "Contexts are printed before, on the same line.",
-    "Contexts are printed after, on the same line.",
-    "Contexts are printed on the previous line.",
-    "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",
-};
-
-typedef enum {
-    MR_MULTIMATCH_ASK, MR_MULTIMATCH_ALL, MR_MULTIMATCH_ONE
-} MR_MultiMatch;
-
-/*
-** We keep a table of the available commands. The information we have about
-** each command is stored in a value of type MR_Trace_Command_Info.
-**
-** The name of the command itself is stored in the name field; the category
-** field contains name of the category to which the command belongs,
-** e.g. "browsing".
-**
-** The code that the command loop should execute to handle a command of a given
-** type is the function pointed to by the function field.
-**
-** Some commands take fixed strings as arguments. The arg_strings field
-** is a NULL terminated array of those strings, or NULL if there are
-** no fixed strings.
-**
-** The arg_completer field contains the address of a function for more
-** arbitrary completion, e.g. on predicate names. This field should not be
-** null; if the command cannot use a completion function, the field should
-** contain MR_trace_null_completer.
-*/
-
-typedef MR_Next MR_Trace_Command_Function(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr);
-
-typedef struct
-{
-    const char                  *MR_cmd_category;
-    const char                  *MR_cmd_name;
-    MR_Trace_Command_Function   *MR_cmd_function;
-    const char *const           *MR_cmd_arg_strings;
-    const MR_Make_Completer     MR_cmd_arg_completer;
-} MR_Trace_Command_Info;
-
-/*
-** The following data structures describe the information we have about the
-** input arguments of tabled procedures. We use them to decode the call tables
-** of such procedures.
-**
-** We use one MR_Call_Table_Arg structure for each input argument.
-**
-** The step field specifies what data structure the tabling system uses to
-** implement the trie nodes at the level of the call table corresponding to
-** the relevant argument. At the moment, we support only four values of this
-** field, MR_TABLE_STEP_INT, MR_TABLE_STEP_FLOAT, MR_TABLE_STEP_STRING and
-** MR_TABLE_STEP_PROMISE_IMPLIED. The first three of these implicitly select
-** the corresponding alternative in the arg_values union; the last one
-** indicates the absence of a step.
-**
-** The start_node field specifies the start node of the relevant trie. For the
-** first input argument, this will be the tabling pointer variable for the
-** given procedure. For later input arguments, it will be the trie node you
-** reach after following the current values of the previous arguments through
-** the call table.
-**
-** The MR_{Int,Float,String}_Table_Arg_Values structs have the same fields and
-** the same meanings, differing only in the types of the values they store.
-** Each struct is used for one of two things.
-**
-** 1. To describe a value supplied by the user on the mdb command line.
-**    In this case, the only field that matters is the cur_value field.
-**
-** 2. To describe the set of values you can find in a trie node, the one given
-**    by the start_node field, and to specify which is the current one.
-**    In this case, all the fields matter.
-**
-** The code that manipulates these structures distinguishes between the two
-** uses based on argument number.
-**
-** The values array is managed with the macros in mercury_array_macros.h,
-** so its size is given by the value_next field. The cur_index field gives the
-** index of the current value, while the cur_value field gives the current
-** value itself. (The contents of the cur_value field can be deduced from the
-** contents of the other fields with use 2, but not with use 1.)
-**
-** The valid field in the MR_Call_Table_Arg structure gives the validity
-** of the values subfield of its arg_values field; if it is false, then the
-** array is logically considered empty.
-*/
-
-typedef struct {
-    MR_Integer                  *MR_ctai_values;
-    int                         MR_ctai_value_next;
-    int                         MR_ctai_cur_index;
-    MR_Integer                  MR_ctai_cur_value;
-} MR_Int_Table_Arg_Values;
-
-typedef struct {
-    MR_Float                    *MR_ctaf_values;
-    int                         MR_ctaf_value_next;
-    int                         MR_ctaf_cur_index;
-    MR_Float                    MR_ctaf_cur_value;
-} MR_Float_Table_Arg_Values;
-
-typedef struct {
-    MR_ConstString              *MR_ctas_values;
-    int                         MR_ctas_value_next;
-    int                         MR_ctas_cur_index;
-    MR_ConstString              MR_ctas_cur_value;
-} MR_String_Table_Arg_Values;
-
-typedef union {
-    MR_Int_Table_Arg_Values     MR_cta_values_int;
-    MR_Float_Table_Arg_Values   MR_cta_values_float;
-    MR_String_Table_Arg_Values  MR_cta_values_string;
-} MR_Table_Arg_Values;
-
-typedef struct {
-    MR_Table_Trie_Step          MR_cta_step;
-    int                         MR_cta_unfiltered_arg_num;
-    MR_TrieNode                 MR_cta_start_node;
-    MR_bool                     MR_cta_valid;
-    MR_Table_Arg_Values         MR_cta_arg_values;
-} MR_Call_Table_Arg;
-
-#define MR_cta_int_values       MR_cta_arg_values.MR_cta_values_int.\
-                                    MR_ctai_values
-#define MR_cta_int_value_next   MR_cta_arg_values.MR_cta_values_int.\
-                                    MR_ctai_value_next
-#define MR_cta_int_cur_index    MR_cta_arg_values.MR_cta_values_int.\
-                                    MR_ctai_cur_index
-#define MR_cta_int_cur_value    MR_cta_arg_values.MR_cta_values_int.\
-                                    MR_ctai_cur_value
-
-#define MR_cta_float_values     MR_cta_arg_values.MR_cta_values_float.\
-                                    MR_ctaf_values
-#define MR_cta_float_value_next MR_cta_arg_values.MR_cta_values_float.\
-                                    MR_ctaf_value_next
-#define MR_cta_float_cur_index  MR_cta_arg_values.MR_cta_values_float.\
-                                    MR_ctaf_cur_index
-#define MR_cta_float_cur_value  MR_cta_arg_values.MR_cta_values_float.\
-                                    MR_ctaf_cur_value
-
-#define MR_cta_string_values    MR_cta_arg_values.MR_cta_values_string.\
-                                    MR_ctas_values
-#define MR_cta_string_value_next MR_cta_arg_values.MR_cta_values_string.\
-                                    MR_ctas_value_next
-#define MR_cta_string_cur_index MR_cta_arg_values.MR_cta_values_string.\
-                                    MR_ctas_cur_index
-#define MR_cta_string_cur_value MR_cta_arg_values.MR_cta_values_string.\
-                                    MR_ctas_cur_value
-
 static  void    MR_trace_internal_ensure_init(void);
 static  MR_bool MR_trace_internal_create_mdb_window(void);
 static  void    MR_trace_internal_kill_mdb_window(void);
@@ -445,332 +173,28 @@
 static  MR_Next MR_trace_debug_cmd(char *line, MR_Trace_Cmd_Info *cmd,
                     MR_Event_Info *event_info, MR_Code **jumpaddr);
 
-typedef MR_Next MR_TraceCmdFunc(char **words, int word_count,
-                    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
-                    MR_Code **jumpaddr);
-
 static  MR_TraceCmdFunc MR_trace_handle_cmd;
 
-static  MR_TraceCmdFunc MR_trace_cmd_step;
-static  MR_TraceCmdFunc MR_trace_cmd_goto;
-static  MR_TraceCmdFunc MR_trace_cmd_next;
-static  MR_TraceCmdFunc MR_trace_cmd_finish;
-static  MR_TraceCmdFunc MR_trace_cmd_fail;
-static  MR_TraceCmdFunc MR_trace_cmd_exception;
-static  MR_TraceCmdFunc MR_trace_cmd_return;
-static  MR_TraceCmdFunc MR_trace_cmd_forward;
-static  MR_TraceCmdFunc MR_trace_cmd_mindepth;
-static  MR_TraceCmdFunc MR_trace_cmd_maxdepth;
-static  MR_TraceCmdFunc MR_trace_cmd_continue;
-static  MR_TraceCmdFunc MR_trace_cmd_retry;
-static  MR_TraceCmdFunc MR_trace_cmd_level;
-static  MR_TraceCmdFunc MR_trace_cmd_up;
-static  MR_TraceCmdFunc MR_trace_cmd_down;
-static  MR_TraceCmdFunc MR_trace_cmd_vars;
-static  MR_TraceCmdFunc MR_trace_cmd_held_vars;
-static  MR_TraceCmdFunc MR_trace_cmd_print;
-static  MR_TraceCmdFunc MR_trace_cmd_browse;
-static  MR_TraceCmdFunc MR_trace_cmd_stack;
-static  MR_TraceCmdFunc MR_trace_cmd_current;
-static  MR_TraceCmdFunc MR_trace_cmd_set;
-static  MR_TraceCmdFunc MR_trace_cmd_view;
-static  MR_TraceCmdFunc MR_trace_cmd_hold;
-static  MR_TraceCmdFunc MR_trace_cmd_diff;
-static  MR_TraceCmdFunc MR_trace_cmd_dump;
-static  MR_TraceCmdFunc MR_trace_cmd_list;
-static  MR_TraceCmdFunc MR_trace_cmd_set_list_dir_path;
-static  MR_TraceCmdFunc MR_trace_cmd_push_list_dir;
-static  MR_TraceCmdFunc MR_trace_cmd_pop_list_dir;
-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;
-static  MR_TraceCmdFunc MR_trace_cmd_disable;
-static  MR_TraceCmdFunc MR_trace_cmd_delete;
-static  MR_TraceCmdFunc MR_trace_cmd_register;
-static  MR_TraceCmdFunc MR_trace_cmd_modules;
-static  MR_TraceCmdFunc MR_trace_cmd_procedures;
-static  MR_TraceCmdFunc MR_trace_cmd_query;
-static  MR_TraceCmdFunc MR_trace_cmd_cc_query;
-static  MR_TraceCmdFunc MR_trace_cmd_io_query;
-static  MR_TraceCmdFunc MR_trace_cmd_printlevel;
-static  MR_TraceCmdFunc MR_trace_cmd_mmc_options;
-static  MR_TraceCmdFunc MR_trace_cmd_scroll;
-static  MR_TraceCmdFunc MR_trace_cmd_stack_default_limit;
-static  MR_TraceCmdFunc MR_trace_cmd_context;
-static  MR_TraceCmdFunc MR_trace_cmd_goal_paths;
-static  MR_TraceCmdFunc MR_trace_cmd_scope;
-static  MR_TraceCmdFunc MR_trace_cmd_echo;
-static  MR_TraceCmdFunc MR_trace_cmd_alias;
-static  MR_TraceCmdFunc MR_trace_cmd_unalias;
-static  MR_TraceCmdFunc MR_trace_cmd_document_category;
-static  MR_TraceCmdFunc MR_trace_cmd_document;
-static  MR_TraceCmdFunc MR_trace_cmd_help;
-static  MR_TraceCmdFunc MR_trace_cmd_histogram_all;
-static  MR_TraceCmdFunc MR_trace_cmd_histogram_exp;
-static  MR_TraceCmdFunc MR_trace_cmd_clear_histogram;
-static  MR_TraceCmdFunc MR_trace_cmd_var_details;
-static  MR_TraceCmdFunc MR_trace_cmd_term_size;
-static  MR_TraceCmdFunc MR_trace_cmd_flag;
-static  MR_TraceCmdFunc MR_trace_cmd_subgoal;
-static  MR_TraceCmdFunc MR_trace_cmd_consumer;
-static  MR_TraceCmdFunc MR_trace_cmd_gen_stack;
-static  MR_TraceCmdFunc MR_trace_cmd_cut_stack;
-static  MR_TraceCmdFunc MR_trace_cmd_pneg_stack;
-static  MR_TraceCmdFunc MR_trace_cmd_mm_stacks;
-static  MR_TraceCmdFunc MR_trace_cmd_nondet_stack;
-static  MR_TraceCmdFunc MR_trace_cmd_stack_regs;
-static  MR_TraceCmdFunc MR_trace_cmd_all_regs;
-static  MR_TraceCmdFunc MR_trace_cmd_debug_vars;
-static  MR_TraceCmdFunc MR_trace_cmd_table_io;
-static  MR_TraceCmdFunc MR_trace_cmd_stats;
-static  MR_TraceCmdFunc MR_trace_cmd_proc_body;
-static  MR_TraceCmdFunc MR_trace_cmd_print_optionals;
-static  MR_TraceCmdFunc MR_trace_cmd_unhide_events;
-static  MR_TraceCmdFunc MR_trace_cmd_table;
-static  MR_TraceCmdFunc MR_trace_cmd_type_ctor;
-static  MR_TraceCmdFunc MR_trace_cmd_class_decl;
-static  MR_TraceCmdFunc MR_trace_cmd_all_type_ctors;
-static  MR_TraceCmdFunc MR_trace_cmd_all_class_decls;
-static  MR_TraceCmdFunc MR_trace_cmd_all_procedures;
-static  MR_TraceCmdFunc MR_trace_cmd_ambiguity;
-static  MR_TraceCmdFunc MR_trace_cmd_save;
-static  MR_TraceCmdFunc MR_trace_cmd_quit;
-static  MR_TraceCmdFunc MR_trace_cmd_dd;
-static  MR_TraceCmdFunc MR_trace_cmd_trust;
-static  MR_TraceCmdFunc MR_trace_cmd_untrust;
-static  MR_TraceCmdFunc MR_trace_cmd_trusted;
-static  MR_TraceCmdFunc MR_trace_cmd_dice;
-
-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  MR_bool     MR_parse_source_locn(char *word, const char **file,
-                        int *line);
-static  const char  *MR_trace_new_source_window(const char *window_cmd,
-                        const char *server_cmd, const char *server_name,
-                        int timeout, MR_bool force, MR_bool verbose,
-                        MR_bool split);
-static  void        MR_trace_maybe_sync_source_window(
-                        MR_Event_Info *event_info, MR_bool verbose);
-static  void        MR_trace_maybe_close_source_window(MR_bool verbose);
-
-static  void        MR_trace_cmd_stack_2(MR_Event_Info *event_info,
-                        MR_bool detailed, int frame_limit, int line_limit);
-static  void        MR_trace_cmd_nondet_stack_2(MR_Event_Info *event_info,
-                        MR_bool detailed, int frame_limit, int line_limit);
-static  MR_Spy_Print_List MR_add_to_print_list_end(MR_Browse_Format format,
-                        char *word, MR_bool warn,
-                        MR_Spy_Print_List print_list);
-
-static  MR_bool     MR_trace_options_movement_cmd(MR_Trace_Cmd_Info *cmd,
-                        char ***words, int *word_count);
-static  MR_bool     MR_trace_options_retry(MR_Retry_Across_Io *across_io,
-                        MR_bool *assume_all_io_is_tabled,
-                        char ***words, int *word_count);
-static  MR_bool     MR_trace_options_when_action_multi_ignore(MR_Spy_When *when,
-                        MR_Spy_Action *action, MR_MultiMatch *multi_match,
-                        MR_Spy_Ignore_When *ignore_when, int *ignore_count,
-                        MR_Spy_Print_List *print_list,
-                        char ***words, int *word_count);
-static  MR_bool     MR_trace_options_condition(int *break_num,
-                        MR_bool *require_var, MR_bool *require_path,
-                        char ***words, int *word_count);
-static  MR_bool     MR_trace_options_ignore_count(
-                        MR_Spy_Ignore_When *ignore_when,
-                        int *ignore_count, char ***words, int *word_count);
-static  MR_bool     MR_trace_options_quiet(MR_bool *verbose, char ***words,
-                        int *word_count);
-static  MR_bool     MR_trace_options_ignore(MR_bool *ignore_errors,
-                        char ***words, int *word_count);
-static  MR_bool     MR_trace_options_break_print(MR_Browse_Format *format,
-                        MR_bool *at_start, MR_bool *warn, char ***words,
-                        int *word_count);
-static  MR_bool     MR_trace_options_detailed(MR_bool *detailed, char ***words,
-                        int *word_count);
-static  MR_bool     MR_trace_options_stack_trace(MR_bool *detailed,
-                        int *frame_limit, char ***words, int *word_count);
-static  MR_bool     MR_trace_options_confirmed(MR_bool *confirmed,
-                        char ***words, int *word_count);
-static  MR_bool     MR_trace_options_format(MR_Browse_Format *format,
-                        MR_bool *xml, char ***words, int *word_count);
-static  MR_bool     MR_trace_options_param_set(MR_Word *print_set,
-                        MR_Word *browse_set, MR_Word *print_all_set,
-                        MR_Word *flat_format, MR_Word *raw_pretty_format,
-                        MR_Word *verbose_format, MR_Word *pretty_format,
-                        char ***words, int *word_count);
-static  MR_bool     MR_trace_options_view(const char **window_cmd,
-                        const char **server_cmd, const char **server_name,
-                        int *timeout, MR_bool *force, MR_bool *verbose,
-                        MR_bool *split, MR_bool *close_window, char ***words,
-                        int *word_count);
-static  MR_bool     MR_trace_options_dd(MR_bool *assume_all_io_is_tabled,
-                        MR_Unsigned *default_depth, MR_Unsigned *num_nodes,
-                        MR_Decl_Search_Mode *search_mode,
-                        MR_bool *search_mode_was_set,
-                        MR_bool *search_mode_requires_trace_counts,
-                        char **pass_trace_counts_file,
-                        char **fail_trace_counts_file,
-                        MR_bool *new_session, MR_bool *testing, MR_bool *debug,
-                        char ***words, int *word_count);
-static  MR_bool     MR_trace_options_stats(char **filename, char ***words,
-                        int *word_count);
-static  MR_bool     MR_trace_options_type_ctor(MR_bool *print_rep,
-                        MR_bool *print_functors, char ***words,
-                        int *word_count);
-static  MR_bool     MR_trace_options_class_decl(MR_bool *print_methods,
-                        MR_bool *print_instances, char ***words,
-                        int *word_count);
-static  MR_bool     MR_trace_options_all_procedures(MR_bool *separate,
-                        MR_bool *uci, char **module, char ***words,
-                        int *word_count);
-static  MR_bool     MR_trace_options_ambiguity(const char **outfile,
-                        char ***words, int *word_count);
-static  MR_bool     MR_trace_options_diff(int *start, int *max,
-                        char ***words, int *word_count);
-static  MR_bool     MR_trace_options_dump(MR_bool *xml,
-                        char ***words, int *word_count);
-static  MR_bool     MR_trace_options_dice(char **pass_trace_counts_file,
-                        char **fail_trace_count_file, char **sort_str,
-                        int *number_of_lines, char **out_file, char **module,
-                        char ***words, int *word_count);
-static  void        MR_trace_usage_cur_cmd(void);
-static  void        MR_trace_do_noop(void);
 static  void        MR_mdb_print_proc_id_and_nl(void *data,
                         const MR_Proc_Layout *entry_layout);
 static  int         MR_trace_var_print_list(MR_Spy_Print_List print_list);
-static  void        MR_trace_print_dice(char *pass_trace_counts_file,
-                        char *fail_trace_counts_file, char *sort_str,
-                        int number_of_lines, char *out_str, char *module);
-static  void        MR_trace_listing_path_ensure_init(void);
-
-static  const MR_Proc_Layout *MR_find_single_matching_proc(MR_Proc_Spec *spec,
-                        MR_bool verbose);
-
-/*
-** These functions fill in the data structure describing one input argument
-** of a tabled procedure with a constant value given on the mdb command line.
-** They return true if they succeed, and false if they fail (e.g. because the
-** string given on the mdb command line does not describe a value of the
-** required type).
-*/
-
-static  MR_bool     MR_trace_fill_in_int_table_arg_slot(
-                        MR_TrieNode *table_cur_ptr,
-                        int arg_num, MR_ConstString given_arg,
-                        MR_Call_Table_Arg *call_table_arg_ptr);
-static  MR_bool     MR_trace_fill_in_float_table_arg_slot(
-                        MR_TrieNode *table_cur_ptr,
-                        int arg_num, MR_ConstString given_arg,
-                        MR_Call_Table_Arg *call_table_arg_ptr);
-static  MR_bool     MR_trace_fill_in_string_table_arg_slot(
-                        MR_TrieNode *table_cur_ptr,
-                        int arg_num, MR_ConstString given_arg,
-                        MR_Call_Table_Arg *call_table_arg_ptr);
-
-/*
-** These functions fill in the data structure describing one input argument
-** of a tabled procedure with the next value taken from the given trie node.
-** They return true if there are no more values in the trie node, and false
-** otherwise.
-*/
 
-static  MR_bool     MR_update_int_table_arg_slot(MR_TrieNode *table_cur_ptr,
-                        MR_Call_Table_Arg *call_table_arg_ptr);
-static  MR_bool     MR_update_float_table_arg_slot(MR_TrieNode *table_cur_ptr,
-                        MR_Call_Table_Arg *call_table_arg_ptr);
-static  MR_bool     MR_update_string_table_arg_slot(MR_TrieNode *table_cur_ptr,
-                        MR_Call_Table_Arg *call_table_arg_ptr);
-
-/* Prints the given subgoal of the given procedure to MR_mdb_out. */
-static  void        MR_trace_cmd_table_print_tip(const MR_Proc_Layout *proc,
-                        int filtered_num_inputs,
-                        MR_Call_Table_Arg *call_table_args, MR_TrieNode table);
-
-/* Prints the given subgoal of the given procedure to MR_mdb_out. */
-static  void        MR_trace_print_subgoal(const MR_Proc_Layout *proc,
-                        MR_Subgoal *subgoal);
-static  void        MR_trace_print_subgoal_debug(const MR_Proc_Layout *proc,
-                        MR_SubgoalDebug *subgoal_debug);
-
-/* Prints the given generator of the given procedure to MR_mdb_out. */
-static  void        MR_trace_print_generator(const MR_Proc_Layout *proc,
-                        MR_Generator *generator);
-static  void        MR_trace_print_generator_debug(const MR_Proc_Layout *proc,
-                        MR_GenDebug *generator_debug);
-
-/* Prints the given consumer of the given procedure to MR_mdb_out. */
-static  void        MR_trace_print_consumer(const MR_Proc_Layout *proc,
-                        MR_Consumer *consumer);
-static  void        MR_trace_print_consumer_debug(const MR_Proc_Layout *proc,
-                        MR_ConsumerDebug *consumer_debug);
-
-/* Prints the requested information inside the given MR_TypeCtorInfo. */
-static  void        MR_print_type_ctor_info(FILE *fp,
-                        MR_TypeCtorInfo type_ctor_info,
-                        MR_bool print_rep, MR_bool print_functors);
-/* Prints the requested information inside the given MR_TypeClassDeclInfo. */
-static  void        MR_print_class_decl_info(FILE *fp,
-                        MR_TypeClassDeclInfo *type_class_decl_info,
-                        MR_bool print_methods, MR_bool print_instances);
-/* Print the given pseudo-typeinfo. */
-static  void        MR_print_pseudo_type_info(FILE *fp,
-                        MR_PseudoTypeInfo pseudo);
-
-static  void        MR_trace_set_level_and_report(int ancestor_level,
-                        MR_bool detailed, MR_bool print_optionals);
-static  void        MR_trace_browse_internal(MR_Word type_info, MR_Word value,
-                        MR_Browse_Caller_Type caller, MR_Browse_Format format);
-static  void        MR_trace_browse_goal_internal(MR_ConstString name,
-                        MR_Word arg_list, MR_Word is_func,
-                        MR_Browse_Caller_Type caller, MR_Browse_Format format);
-static  const char  *MR_trace_browse_exception(MR_Event_Info *event_info,
-                        MR_Browser browser, MR_Browse_Caller_Type caller,
-                        MR_Browse_Format format);
-static  const char  *MR_trace_browse_proc_body(MR_Event_Info *event_info,
-                        MR_Browser browser, MR_Browse_Caller_Type caller,
-                        MR_Browse_Format format);
-
-/* Functions to invoke the user's XML browser on terms or goals */
-static  void        MR_trace_browse_xml(MR_Word type_info, MR_Word value,
-                        MR_Browse_Caller_Type caller, MR_Browse_Format format);
-static  void        MR_trace_browse_goal_xml(MR_ConstString name,
-                        MR_Word arg_list, MR_Word is_func,
-                        MR_Browse_Caller_Type caller, MR_Browse_Format format);
-
-static  const char  *MR_trace_read_help_text(void);
 static  const char  *MR_trace_parse_line(char *line, char ***words,
                         int *word_max, int *word_count);
 static  const char  *MR_trace_break_into_words(char *line, char ***words_ptr,
                         int *word_max_ptr, int *word_count_ptr);
 static  const char  *MR_trace_break_off_one_word(char *line, int char_pos,
                         int *new_char_pos_ptr);
-static  void        MR_trace_expand_aliases(char ***words,
-                        int *word_max, int *word_count);
-static  MR_bool     MR_trace_source(const char *filename,
-                        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 *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);
 
-static  void        MR_insert_line_at_head(const char *line);
-static  void        MR_insert_line_at_tail(const char *line);
-
-static  void        MR_trace_event_print_internal_report(
-                        MR_Event_Info *event_info);
-
-static  const MR_Trace_Command_Info *MR_trace_valid_command(
-                        const char *command);
-
 static  char        *MR_trace_command_completer_next(const char *word,
                         size_t word_len, MR_Completer_Data *data);
 
-static  MR_SavedDebugState  MR_saved_debug_state;
+MR_SavedDebugState  MR_saved_debug_state;
 
 MR_Code *
 MR_trace_event_internal(MR_Trace_Cmd_Info *cmd, MR_bool interactive,
@@ -798,6 +222,8 @@
 #endif
 
     MR_trace_internal_ensure_init();
+    MR_trace_browse_ensure_init();
+    MR_trace_listing_path_ensure_init();
 
     if (MR_spy_point_cond_problem != NULL) {
         fprintf(MR_mdb_err, "mdb: couldn't evaluate break point condition\n");
@@ -1252,160 +678,65 @@
     MR_free(buf);
 }
 
-static void
-MR_trace_set_level_and_report(int ancestor_level, MR_bool detailed,
-    MR_bool print_optionals)
+MR_bool
+MR_trace_source(const char *filename, MR_bool ignore_errors)
 {
-    const char              *problem;
-    const MR_Proc_Layout    *entry;
-    MR_Word                 *base_sp;
-    MR_Word                 *base_curfr;
-    const char              *filename;
-    int                     lineno;
-    int                     indent;
-
-    problem = MR_trace_set_level(ancestor_level, print_optionals);
-    if (problem == NULL) {
-        fprintf(MR_mdb_out, "Ancestor level set to %d:\n",
-            ancestor_level);
-        MR_trace_current_level_details(&entry, &filename, &lineno,
-            &base_sp, &base_curfr);
-        fprintf(MR_mdb_out, "%4d ", ancestor_level);
-        if (detailed) {
-            /*
-            ** We want to print the trace info first regardless
-            ** of the value of MR_context_position.
-            */
-
-            MR_print_call_trace_info(MR_mdb_out, entry, base_sp, base_curfr);
-            indent = 26;
-        } else {
-            indent = 5;
-        }
+    FILE    *fp;
 
-        MR_print_proc_id_trace_and_context(MR_mdb_out, MR_FALSE,
-            MR_context_position, entry, base_sp, base_curfr, "",
-            filename, lineno, MR_FALSE, "", 0, indent);
-    } else {
-        fflush(MR_mdb_out);
-        fprintf(MR_mdb_err, "%s.\n", problem);
+    if ((fp = fopen(filename, "r")) != NULL) {
+        MR_trace_source_from_open_file(fp);
+        fclose(fp);
+        return MR_TRUE;
     }
-}
-
-static void
-MR_trace_browse_internal(MR_Word type_info, MR_Word value,
-        MR_Browse_Caller_Type caller, MR_Browse_Format format)
-{
-    switch (caller) {
-
-        case MR_BROWSE_CALLER_BROWSE:
-            MR_trace_browse(type_info, value, format);
-            break;
 
-        case MR_BROWSE_CALLER_PRINT:
-        case MR_BROWSE_CALLER_PRINT_ALL:
-            fprintf(MR_mdb_out, "\t");
+    if (! ignore_errors) {
             fflush(MR_mdb_out);
-            MR_trace_print(type_info, value, caller, format);
-            break;
-
-        default:
-            MR_fatal_error("MR_trace_browse_internal: unknown caller type");
+        fprintf(MR_mdb_err, "%s: %s.\n", filename, strerror(errno));
     }
-}
 
-static void
-MR_trace_browse_xml(MR_Word type_info, MR_Word value,
-    MR_Browse_Caller_Type caller, MR_Browse_Format format)
-{
-    MR_Word     browser_term;
-
-    browser_term = MR_type_value_to_browser_term((MR_TypeInfo) type_info,
-        value);
-
-    MR_trace_save_and_invoke_xml_browser(browser_term);
+    return MR_FALSE;
 }
 
-static void
-MR_trace_browse_goal_internal(MR_ConstString name, MR_Word arg_list,
-    MR_Word is_func, MR_Browse_Caller_Type caller, MR_Browse_Format format)
+void
+MR_trace_source_from_open_file(FILE *fp)
 {
-    switch (caller) {
+    char    *contents;
+    MR_Line *line;
+    MR_Line *prev_line;
+    MR_Line *old_head;
 
-        case MR_BROWSE_CALLER_BROWSE:
-            MR_trace_browse_goal(name, arg_list, is_func, format);
-            break;
+    prev_line = NULL;
+    old_head = MR_line_head;
 
-        case MR_BROWSE_CALLER_PRINT:
-            MR_trace_print_goal(name, arg_list, is_func, caller, format);
-            break;
+    /*
+    ** Insert the sourced commands at the front of the command queue,
+    ** preserving their order in the sourced file.
+    */
 
-        case MR_BROWSE_CALLER_PRINT_ALL:
-            MR_fatal_error("MR_trace_browse_goal_internal: bad caller type");
+    while ((contents = MR_trace_readline_raw(fp)) != NULL) {
+        line = MR_NEW(MR_Line);
+        line->MR_line_contents = MR_copy_string(contents);
 
-        default:
-            MR_fatal_error("MR_trace_browse_goal_internal:"
-                " unknown caller type");
+        if (prev_line == NULL) {
+            MR_line_head = line;
+        } else {
+            prev_line->MR_line_next = line;
     }
-}
-
-static void
-MR_trace_browse_goal_xml(MR_ConstString name, MR_Word arg_list,
-    MR_Word is_func, MR_Browse_Caller_Type caller, MR_Browse_Format format)
-{
-    MR_Word     browser_term;
-
-    browser_term = MR_synthetic_to_browser_term(name, arg_list, is_func);
-    MR_trace_save_and_invoke_xml_browser(browser_term);
-}
-
-static const char *
-MR_trace_browse_exception(MR_Event_Info *event_info, MR_Browser browser,
-    MR_Browse_Caller_Type caller, MR_Browse_Format format)
-{
-    MR_TypeInfo type_info;
-    MR_Word     value;
-    MR_Word     exception;
 
-    if (event_info->MR_trace_port != MR_PORT_EXCEPTION) {
-        return "command only available from EXCP ports";
+        prev_line = line;
     }
 
-    exception = MR_trace_get_exception_value();
-    if (exception == (MR_Word) NULL) {
-        return "missing exception value";
+    if (prev_line != NULL) {
+        prev_line->MR_line_next = old_head;
+        if (MR_line_tail == NULL) {
+            MR_line_tail = prev_line;
     }
-
-    MR_unravel_univ(exception, type_info, value);
-
-    (*browser)((MR_Word) type_info, value, caller, format);
-
-    return (const char *) NULL;
-}
-
-static const char *
-MR_trace_browse_proc_body(MR_Event_Info *event_info, MR_Browser browser,
-    MR_Browse_Caller_Type caller, MR_Browse_Format format)
-{
-    const MR_Proc_Layout    *entry;
-    MR_Word                 rep;
-
-    entry = event_info->MR_event_sll->MR_sll_entry;
-
-    if (entry->MR_sle_body_bytes == NULL) {
-        return "current procedure has no body info";
     }
 
-    MR_TRACE_CALL_MERCURY(
-        MR_DD_trace_read_rep(entry->MR_sle_body_bytes,
-            event_info->MR_event_sll, &rep);
-    );
-
-    (*browser)(ML_proc_rep_type(), rep, caller, format);
-    return (const char *) NULL;
+    MR_trace_internal_interacting = MR_FALSE;
 }
 
-static void
+void
 MR_trace_do_noop(void)
 {
     fflush(MR_mdb_out);
@@ -1490,9 +821,6 @@
     return count;
 }
 
-/* Options to pass to mmc when compiling queries. */
-static char *MR_mmc_options = NULL;
-
 static MR_Next
 MR_trace_debug_cmd(char *line, MR_Trace_Cmd_Info *cmd,
     MR_Event_Info *event_info, MR_Code **jumpaddr)
@@ -1585,6185 +913,60 @@
     return KEEP_INTERACTING;
 }
 
-static MR_Next
-MR_trace_cmd_step(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
+void
+MR_trace_usage_cur_cmd(void)
 {
-    int n;
-
-    cmd->MR_trace_strict = MR_FALSE;
-    cmd->MR_trace_print_level = MR_default_print_level;
-    MR_init_trace_check_integrity(cmd);
-    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 1) {
-        cmd->MR_trace_cmd = MR_CMD_GOTO;
-        cmd->MR_trace_stop_event = MR_trace_event_number + 1;
-        return STOP_INTERACTING;
-    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
-        cmd->MR_trace_cmd = MR_CMD_GOTO;
-        cmd->MR_trace_stop_event = MR_trace_event_number + n;
-        return STOP_INTERACTING;
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
+    /* MR_current_cmd_category is unused now, for but could be used later. */
+    fflush(MR_mdb_out);
+    fprintf(MR_mdb_err,
+        "mdb: %s: usage error -- type `help %s' for help.\n",
+        MR_current_cmd_name, MR_current_cmd_name);
 }
 
-static MR_Next
-MR_trace_cmd_goto(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
+/*
+** Given a text line, break it up into words composed of non-space characters
+** separated by space characters. Make each word a NULL-terminated string,
+** overwriting some spaces in the line array in the process.
+**
+** If the first word is a number but the second is not, swap the two.
+** If the first word has a number prefix, separate it out.
+**
+** On return *words will point to an array of strings, with space for
+** *words_max strings. The number of strings (words) filled in will be
+** given by *word_count.
+**
+** The space for the *words array is allocated with MR_malloc().
+** It is the caller's responsibility to free it when appropriate.
+** The elements of the *words array point to memory from the line array.
+** The lifetime of the elements of the *words array expires when
+** the line array is MR_free()'d or further modified or when
+** MR_trace_parse_line is called again, whichever comes first.
+**
+** The return value is NULL if everything went OK, and an error message
+** otherwise.
+*/
+
+static const char *
+MR_trace_parse_line(char *line, char ***words, int *word_max, int *word_count)
 {
-    MR_Unsigned n;
+    char        **raw_words;
+    int         raw_word_max;
+    int         raw_word_count;
+    static char count_buf[MR_NUMBER_LEN + 1];
+    char        *s;
+    int         i;
+    const char  *problem;
 
-    cmd->MR_trace_strict = MR_TRUE;
-    cmd->MR_trace_print_level = MR_default_print_level;
-    MR_init_trace_check_integrity(cmd);
-    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 2 && MR_trace_is_unsigned(words[1], &n)) {
-        if (MR_trace_event_number < n) {
-            cmd->MR_trace_cmd = MR_CMD_GOTO;
-            cmd->MR_trace_stop_event = n;
-            return STOP_INTERACTING;
-        } else {
-            /* XXX this message is misleading */
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "The debugger cannot go to a past event.\n");
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
+    /*
+    ** Handle a possible number prefix on the first word on the line,
+    ** separating it out into a word on its own.
+    */
 
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_next(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_Unsigned depth;
-    int         stop_depth;
-    int         n;
-
-    depth = event_info->MR_call_depth;
-    cmd->MR_trace_strict = MR_TRUE;
-    cmd->MR_trace_print_level = MR_default_print_level;
-    MR_init_trace_check_integrity(cmd);
-    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-        return KEEP_INTERACTING;
-    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
-        stop_depth = depth - n;
-    } else if (word_count == 1) {
-        stop_depth = depth;
-    } else {
-        MR_trace_usage_cur_cmd();
-        return KEEP_INTERACTING;
-    }
-
-    if (depth == stop_depth && MR_port_is_final(event_info->MR_trace_port)) {
-        MR_trace_do_noop();
-    } else {
-        cmd->MR_trace_cmd = MR_CMD_NEXT;
-        cmd->MR_trace_stop_depth = stop_depth;
-        return STOP_INTERACTING;
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_finish(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_Unsigned depth;
-    int         stop_depth;
-    int         n;
-
-    depth = event_info->MR_call_depth;
-    cmd->MR_trace_strict = MR_TRUE;
-    cmd->MR_trace_print_level = MR_default_print_level;
-    MR_init_trace_check_integrity(cmd);
-    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-        return KEEP_INTERACTING;
-    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
-        stop_depth = depth - n;
-    } else if (word_count == 1) {
-        stop_depth = depth;
-    } else {
-        MR_trace_usage_cur_cmd();
-        return KEEP_INTERACTING;
-    }
-
-    if (depth == stop_depth && MR_port_is_final(event_info->MR_trace_port)) {
-        MR_trace_do_noop();
-    } else {
-        cmd->MR_trace_cmd = MR_CMD_FINISH;
-        cmd->MR_trace_stop_depth = stop_depth;
-        return STOP_INTERACTING;
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_fail(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_Determinism  detism;
-    MR_Unsigned     depth;
-    int             stop_depth;
-    int             n;
-
-    detism = event_info->MR_event_sll->MR_sll_entry->MR_sle_detism;
-    depth = event_info->MR_call_depth;
-
-    cmd->MR_trace_strict = MR_TRUE;
-    cmd->MR_trace_print_level = MR_default_print_level;
-    MR_init_trace_check_integrity(cmd);
-    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-        return KEEP_INTERACTING;
-    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
-        stop_depth = depth - n;
-    } else if (word_count == 1) {
-        stop_depth = depth;
-    } else {
-        MR_trace_usage_cur_cmd();
-        return KEEP_INTERACTING;
-    }
-
-    if (MR_DETISM_DET_STACK(detism)) {
-        fflush(MR_mdb_out);
-        fprintf(MR_mdb_err, "mdb: cannot continue until failure: "
-            "selected procedure has determinism %s.\n",
-            MR_detism_names[detism]);
-        return KEEP_INTERACTING;
-    }
-
-    if (depth == stop_depth && event_info->MR_trace_port == MR_PORT_FAIL) {
-        MR_trace_do_noop();
-    } else if (depth == stop_depth &&
-        event_info->MR_trace_port == MR_PORT_EXCEPTION)
-    {
-        fflush(MR_mdb_out);
-        fprintf(MR_mdb_err, "mdb: cannot continue until failure: "
-            "the call has raised an exception.\n");
-    } else {
-        cmd->MR_trace_cmd = MR_CMD_FAIL;
-        cmd->MR_trace_stop_depth = stop_depth;
-        return STOP_INTERACTING;
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_exception(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    cmd->MR_trace_strict = MR_TRUE;
-    cmd->MR_trace_print_level = MR_default_print_level;
-    MR_init_trace_check_integrity(cmd);
-    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 1) {
-        if (event_info->MR_trace_port != MR_PORT_EXCEPTION) {
-            cmd->MR_trace_cmd = MR_CMD_EXCP;
-            return STOP_INTERACTING;
-        } else {
-            MR_trace_do_noop();
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_return(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    cmd->MR_trace_strict = MR_TRUE;
-    cmd->MR_trace_print_level = MR_default_print_level;
-    MR_init_trace_check_integrity(cmd);
-    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 1) {
-        if (event_info->MR_trace_port == MR_PORT_EXIT) {
-            cmd->MR_trace_cmd = MR_CMD_RETURN;
-            return STOP_INTERACTING;
-        } else {
-            MR_trace_do_noop();
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_forward(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    cmd->MR_trace_strict = MR_TRUE;
-    cmd->MR_trace_print_level = MR_default_print_level;
-    MR_init_trace_check_integrity(cmd);
-    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 1) {
-        MR_Trace_Port   port;
-
-        port = event_info->MR_trace_port;
-        if (port == MR_PORT_FAIL ||
-            port == MR_PORT_REDO ||
-            port == MR_PORT_EXCEPTION)
-        {
-            cmd->MR_trace_cmd = MR_CMD_RESUME_FORWARD;
-            return STOP_INTERACTING;
-        } else {
-            MR_trace_do_noop();
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_mindepth(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int newdepth;
-
-    cmd->MR_trace_strict = MR_TRUE;
-    cmd->MR_trace_print_level = MR_default_print_level;
-    MR_init_trace_check_integrity(cmd);
-    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 2 &&
-        MR_trace_is_natural_number(words[1], &newdepth))
-    {
-        cmd->MR_trace_cmd = MR_CMD_MIN_DEPTH;
-        cmd->MR_trace_stop_depth = newdepth;
-        return STOP_INTERACTING;
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_maxdepth(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int newdepth;
-
-    cmd->MR_trace_strict = MR_TRUE;
-    cmd->MR_trace_print_level = MR_default_print_level;
-    MR_init_trace_check_integrity(cmd);
-    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 2 &&
-        MR_trace_is_natural_number(words[1], &newdepth))
-    {
-        cmd->MR_trace_cmd = MR_CMD_MAX_DEPTH;
-        cmd->MR_trace_stop_depth = newdepth;
-        return STOP_INTERACTING;
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_continue(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    cmd->MR_trace_strict = MR_FALSE;
-    cmd->MR_trace_print_level = (MR_Trace_Cmd_Type) -1;
-    MR_init_trace_check_integrity(cmd);
-    if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 1) {
-        cmd->MR_trace_cmd = MR_CMD_TO_END;
-        if (cmd->MR_trace_print_level == (MR_Trace_Cmd_Type) -1) {
-            /*
-            ** The user did not specify the print level;
-            ** select the intelligent default.
-            */
-            if (cmd->MR_trace_strict) {
-                cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE;
-            } else {
-                cmd->MR_trace_print_level = MR_PRINT_LEVEL_SOME;
-            }
-        }
-        return STOP_INTERACTING;
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_retry(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int                 n;
-    int                 ancestor_level;
-    MR_Retry_Across_Io  across_io;
-    const char          *problem;
-    MR_Retry_Result     result;
-    MR_bool             assume_all_io_is_tabled;
-    MR_bool             unsafe_retry;
-
-    ancestor_level = 0;
-    across_io = MR_RETRY_IO_INTERACTIVE;
-    assume_all_io_is_tabled = MR_FALSE;
-    if (! MR_trace_options_retry(&across_io, &assume_all_io_is_tabled,
-        &words, &word_count))
-    {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
-        ancestor_level = n;
-    } else if (word_count == 1) {
-        ancestor_level = 0;
-    } else {
-        MR_trace_usage_cur_cmd();
-        return KEEP_INTERACTING;
-    }
-
-    if (ancestor_level == 0 && MR_port_is_entry(event_info->MR_trace_port)) {
-        MR_trace_do_noop();
-        return KEEP_INTERACTING;
-    }
-
-    result = MR_trace_retry(event_info, ancestor_level,
-        across_io, assume_all_io_is_tabled, MR_UNTABLED_IO_RETRY_MESSAGE,
-        &unsafe_retry, &problem, MR_mdb_in, MR_mdb_out,
-        jumpaddr);
-    switch (result) {
-
-    case MR_RETRY_OK_DIRECT:
-        cmd->MR_trace_cmd = MR_CMD_GOTO;
-        cmd->MR_trace_stop_event = MR_trace_event_number + 1;
-        cmd->MR_trace_strict = MR_FALSE;
-        cmd->MR_trace_print_level = MR_default_print_level;
-        return STOP_INTERACTING;
-
-    case MR_RETRY_OK_FINISH_FIRST:
-        cmd->MR_trace_cmd = MR_CMD_FINISH;
-        cmd->MR_trace_stop_depth = event_info->MR_call_depth - ancestor_level;
-        cmd->MR_trace_strict = MR_TRUE;
-        cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE;
-
-        /* Arrange to retry the call once it is finished. */
-        /* XXX we should use the same options as the original retry */
-        MR_insert_line_at_head("retry -o");
-        return STOP_INTERACTING;
-
-    case MR_RETRY_OK_FAIL_FIRST:
-        cmd->MR_trace_cmd = MR_CMD_FAIL;
-        cmd->MR_trace_stop_depth = event_info->MR_call_depth - ancestor_level;
-        cmd->MR_trace_strict = MR_TRUE;
-        cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE;
-
-        /* Arrange to retry the call once it is finished. */
-        /* XXX we should use the same options as the original retry */
-        MR_insert_line_at_head("retry -o");
-        return STOP_INTERACTING;
-
-    case MR_RETRY_ERROR:
-        fflush(MR_mdb_out);
-        fprintf(MR_mdb_err, "%s\n", problem);
-        return KEEP_INTERACTING;
-    }
-
-    MR_fatal_error("unrecognized retry result");
-}
-
-static MR_Next
-MR_trace_cmd_level(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int n;
-    MR_bool detailed;
-
-    detailed = MR_FALSE;
-    if (! MR_trace_options_detailed(&detailed, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
-        MR_trace_set_level_and_report(n, detailed, MR_print_optionals);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_up(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int     n;
-    MR_bool detailed;
-
-    detailed = MR_FALSE;
-    if (! MR_trace_options_detailed(&detailed, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
-        MR_trace_set_level_and_report(MR_trace_current_level() + n, detailed,
-            MR_print_optionals);
-    } else if (word_count == 1) {
-        MR_trace_set_level_and_report(MR_trace_current_level() + 1, detailed,
-            MR_print_optionals);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_down(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int     n;
-    MR_bool detailed;
-
-    detailed = MR_FALSE;
-    if (! MR_trace_options_detailed(&detailed, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
-        MR_trace_set_level_and_report(MR_trace_current_level() - n, detailed,
-            MR_print_optionals);
-    } else if (word_count == 1) {
-        MR_trace_set_level_and_report(MR_trace_current_level() - 1, detailed,
-            MR_print_optionals);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_vars(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 1) {
-        const char  *problem;
-
-        problem = MR_trace_list_vars(MR_mdb_out);
-        if (problem != NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: %s.\n", problem);
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_held_vars(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 1) {
-        MR_trace_list_held_vars(MR_mdb_out);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_print(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_Browse_Format    format;
-    MR_bool             xml;
-    int             n;
-
-    if (! MR_trace_options_format(&format, &xml, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (xml) {
-        /* the --xml option is not valid for print */
-        MR_trace_usage_cur_cmd();
-    } else if (word_count == 1) {
-        const char  *problem;
-
-        problem = MR_trace_browse_one_goal(MR_mdb_out,
-            MR_trace_browse_goal_internal,
-            MR_BROWSE_CALLER_PRINT, format);
-
-        if (problem != NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: %s.\n", problem);
-        }
-    } else if (word_count == 2) {
-        const char  *problem;
-
-        if (MR_streq(words[1], "*")) {
-            problem = MR_trace_browse_all(MR_mdb_out,
-                MR_trace_browse_internal, format);
-        } else if (MR_streq(words[1], "goal")) {
-            problem = MR_trace_browse_one_goal(MR_mdb_out,
-                MR_trace_browse_goal_internal, MR_BROWSE_CALLER_PRINT, format);
-        } else if (MR_streq(words[1], "exception")) {
-            problem = MR_trace_browse_exception(event_info,
-                MR_trace_browse_internal, MR_BROWSE_CALLER_PRINT, format);
-        } else if (MR_streq(words[1], "proc_body")) {
-            problem = MR_trace_browse_proc_body(event_info,
-                MR_trace_browse_internal, MR_BROWSE_CALLER_PRINT, format);
-        } else {
-            problem = MR_trace_parse_browse_one(MR_mdb_out, MR_TRUE, words[1],
-                MR_trace_browse_internal, MR_BROWSE_CALLER_PRINT, format,
-                MR_FALSE);
-        }
-
-        if (problem != NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: %s.\n", problem);
-        }
-    } else if (word_count == 3 && MR_streq(words[1], "action")
-        && MR_trace_is_natural_number(words[2], &n))
-    {
-        const char  *problem;
-
-        problem = MR_trace_browse_action(MR_mdb_out, n,
-            MR_trace_browse_goal_internal,
-            MR_BROWSE_CALLER_PRINT, format);
-
-        if (problem != NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: %s.\n", problem);
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_browse(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_Browse_Format    format;
-    MR_bool             xml;
-    int                 n;
-    MR_GoalBrowser      goal_browser;
-    MR_Browser          browser;
-
-    if (! MR_trace_options_format(&format, &xml, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else {
-        if (xml) {
-            goal_browser = MR_trace_browse_goal_xml;
-            browser = MR_trace_browse_xml;
-        } else {
-            goal_browser = MR_trace_browse_goal_internal;
-            browser = MR_trace_browse_internal;
-        }
-
-        if (word_count == 1) {
-            const char  *problem;
-
-            problem = MR_trace_browse_one_goal(MR_mdb_out, goal_browser,
-                MR_BROWSE_CALLER_BROWSE, format);
-
-            if (problem != NULL) {
-                fflush(MR_mdb_out);
-                fprintf(MR_mdb_err, "mdb: %s.\n", problem);
-            }
-        } else if (word_count == 2) {
-            const char  *problem;
-
-            if (MR_streq(words[1], "goal")) {
-                problem = MR_trace_browse_one_goal(MR_mdb_out, goal_browser,
-                    MR_BROWSE_CALLER_BROWSE, format);
-            } else if (MR_streq(words[1], "exception")) {
-                problem = MR_trace_browse_exception(event_info, browser,
-                    MR_BROWSE_CALLER_BROWSE, format);
-            } else if (MR_streq(words[1], "proc_body")) {
-                problem = MR_trace_browse_proc_body(event_info, browser,
-                    MR_BROWSE_CALLER_BROWSE, format);
-            } else {
-                problem = MR_trace_parse_browse_one(MR_mdb_out, MR_FALSE,
-                    words[1], browser, MR_BROWSE_CALLER_BROWSE, format,
-                    MR_TRUE);
-            }
-
-            if (problem != NULL) {
-                fflush(MR_mdb_out);
-                fprintf(MR_mdb_err, "mdb: %s.\n", problem);
-            }
-        } else if (word_count == 3 && MR_streq(words[1], "action")
-            && MR_trace_is_natural_number(words[2], &n))
-        {
-            const char  *problem;
-
-            problem = MR_trace_browse_action(MR_mdb_out, n, goal_browser,
-                MR_BROWSE_CALLER_BROWSE, format);
-
-            if (problem != NULL) {
-                fflush(MR_mdb_out);
-                fprintf(MR_mdb_err, "mdb: %s.\n", problem);
-            }
-        } else {
-            MR_trace_usage_cur_cmd();
-        }
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_bool     detailed;
-    int         frame_limit = 0;
-    int         line_limit = MR_stack_default_line_limit;
-    int         spec_line_limit;
-
-    detailed = MR_FALSE;
-    if (! MR_trace_options_stack_trace(&detailed, &frame_limit,
-        &words, &word_count))
-    {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 1) {
-        MR_trace_cmd_stack_2(event_info, detailed, frame_limit, line_limit);
-    } else if (word_count == 2 &&
-        MR_trace_is_natural_number(words[1], &spec_line_limit))
-    {
-        MR_trace_cmd_stack_2(event_info, detailed, frame_limit,
-            spec_line_limit);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static void
-MR_trace_cmd_stack_2(MR_Event_Info *event_info, MR_bool detailed,
-    int frame_limit, int line_limit)
-{
-    const MR_Label_Layout   *layout;
-    MR_Word                 *saved_regs;
-    const char              *msg;
-
-    layout = event_info->MR_event_sll;
-    saved_regs = event_info->MR_saved_regs;
-
-    MR_trace_init_modules();
-    msg = MR_dump_stack_from_layout(MR_mdb_out, layout,
-        MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs),
-        detailed, MR_context_position != MR_CONTEXT_NOWHERE,
-        frame_limit, line_limit, &MR_dump_stack_record_print);
-
-    if (msg != NULL) {
-        fflush(MR_mdb_out);
-        fprintf(MR_mdb_err, "%s.\n", msg);
-    }
-}
-
-static MR_Next
-MR_trace_cmd_current(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 1) {
-        MR_trace_event_print_internal_report(event_info);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_set(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_Browse_Format    format;
-    MR_Word             print_set;
-    MR_Word             browse_set;
-    MR_Word             print_all_set;
-    MR_Word             flat_format;
-    MR_Word             raw_pretty_format;
-    MR_Word             verbose_format;
-    MR_Word             pretty_format;
-    int                 max_io_actions;
-
-    if (word_count >= 3 && MR_streq(words[1], "list_context_lines")) {
-        if (word_count > 3
-            || !MR_trace_is_natural_number(words[2], &MR_num_context_lines)) {
-            MR_trace_usage_cur_cmd();
-        }
-    } else if (word_count >= 3 && MR_streq(words[1], "list_path")) {
-        MR_trace_cmd_set_list_dir_path(words, word_count, cmd, event_info,
-            jumpaddr);
-    } else if (word_count == 3 &&
-        (  MR_streq(words[1], "fail_trace_count")
-        || MR_streq(words[1], "fail_trace_counts")))
-    {
-        if (MR_dice_fail_trace_counts_file != NULL) {
-            free(MR_dice_fail_trace_counts_file);
-        }
-        MR_dice_fail_trace_counts_file = MR_copy_string(words[2]);
-    } else if (word_count == 3 &&
-        (  MR_streq(words[1], "pass_trace_count")
-        || MR_streq(words[1], "pass_trace_counts")))
-    {
-        if (MR_dice_pass_trace_counts_file != NULL) {
-            free(MR_dice_pass_trace_counts_file);
-        }
-        MR_dice_pass_trace_counts_file = MR_copy_string(words[2]);
-    } else if (word_count == 3 &&
-        MR_streq(words[1], "max_io_actions") &&
-        MR_trace_is_natural_number(words[2], &max_io_actions))
-    {
-        MR_TRACE_CALL_MERCURY(
-            ML_BROWSE_set_num_io_actions_from_mdb(max_io_actions,
-                MR_trace_browser_persistent_state,
-                &MR_trace_browser_persistent_state);
-        );
-    } else if (! MR_trace_options_param_set(&print_set, &browse_set,
-        &print_all_set, &flat_format, &raw_pretty_format, &verbose_format,
-        &pretty_format, &words, &word_count))
-    {
-        ; /* the usage message has already been printed */
-    }
-    else if (word_count != 3 ||
-        ! MR_trace_set_browser_param(print_set, browse_set, print_all_set,
-            flat_format, raw_pretty_format, verbose_format, pretty_format,
-            words[1], words[2]))
-    {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_view(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    const char      *window_cmd = NULL;
-    const char      *server_cmd = NULL;
-    const char      *server_name = NULL;
-    int             timeout = 8;    /* seconds */
-    MR_bool         force = MR_FALSE;
-    MR_bool         verbose = MR_FALSE;
-    MR_bool         split = MR_FALSE;
-    MR_bool         close_window = MR_FALSE;
-    const char      *msg;
-
-    if (! MR_trace_options_view(&window_cmd, &server_cmd, &server_name,
-        &timeout, &force, &verbose, &split, &close_window,
-        &words, &word_count))
-    {
-        ; /* the usage message has already been printed */
-    } else if (word_count != 1) {
-        MR_trace_usage_cur_cmd();
-    } else if (close_window) {
-        MR_trace_maybe_close_source_window(verbose);
-    } else {
-        msg = MR_trace_new_source_window(window_cmd, server_cmd, server_name,
-            timeout, force, verbose, split);
-        if (msg != NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: %s.\n", msg);
-        }
-
-        MR_trace_maybe_sync_source_window(event_info, verbose);
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_hold(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    char        *event_var_name;
-    char        *held_var_name;
-    MR_TypeInfo type_info;
-    MR_Word     value;
-    const char  *ignored_name;
-    const char  *problem;
-    MR_bool     bad_subterm;
-
-    if (word_count == 2) {
-        event_var_name = words[1];
-        held_var_name = words[1];
-    } else if (word_count == 3) {
-        event_var_name = words[1];
-        held_var_name = words[2];
-    } else {
-        MR_trace_usage_cur_cmd();
-        return KEEP_INTERACTING;
-    }
-
-    if (strpbrk(held_var_name, "^/") != NULL) {
-        /* Don't allow path separators in variable names. */
-        MR_trace_usage_cur_cmd();
-        return KEEP_INTERACTING;
-    }
-
-    if (held_var_name[0] == '$') {
-        /* Ignore any unneeded initial $ signs. */
-        held_var_name = &held_var_name[1];
-    }
-
-    problem = MR_trace_parse_lookup_var_path(event_var_name, &type_info,
-        &value, &bad_subterm);
-    if (problem != NULL) {
-        fflush(MR_mdb_out);
-        fprintf(MR_mdb_err, "mdb: %s%s.\n",
-            (bad_subterm? "there is no path " : ""), problem);
-        return KEEP_INTERACTING;
-    }
-
-    if (! MR_add_hold_var(held_var_name, type_info, value)) {
-        fflush(MR_mdb_out);
-        fprintf(MR_mdb_err, "mdb: there is already a held variable $%s\n",
-            held_var_name);
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_diff(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int         start;
-    int         max;
-    char        *name1;
-    char        *name2;
-    MR_TypeInfo type_info1;
-    MR_TypeInfo type_info2;
-    MR_Word     value1;
-    MR_Word     value2;
-    MR_Word     univ1;
-    MR_Word     univ2;
-    const char  *problem1;
-    const char  *problem2;
-    MR_bool     bad_subterm1;
-    MR_bool     bad_subterm2;
-
-    start = 0;
-    max = 20;
-    if (! MR_trace_options_diff(&start, &max, &words, &word_count)) {
-        /* the usage message has already been printed */
-        return KEEP_INTERACTING;
-    } else if (word_count != 3) {
-        MR_trace_usage_cur_cmd();
-        return KEEP_INTERACTING;
-    }
-
-    name1 = words[1];
-    name2 = words[2];
-    problem1 = MR_trace_parse_lookup_var_path(name1, &type_info1, &value1,
-        &bad_subterm1);
-    problem2 = MR_trace_parse_lookup_var_path(name2, &type_info2, &value2,
-        &bad_subterm2);
-    if (problem1 != NULL) {
-        fflush(MR_mdb_out);
-        fprintf(MR_mdb_err, "mdb: %s%s.\n",
-            (bad_subterm1? "arg1: there is no path " : ""), problem1);
-        return KEEP_INTERACTING;
-    }
-    if (problem2 != NULL) {
-        fflush(MR_mdb_out);
-        fprintf(MR_mdb_err, "mdb: %s%s.\n",
-            (bad_subterm2? "arg2: there is no path " : ""), problem2);
-        return KEEP_INTERACTING;
-    }
-
-    MR_TRACE_CALL_MERCURY(
-        MR_new_univ_on_hp(univ1, type_info1, value1);
-        MR_new_univ_on_hp(univ2, type_info2, value2);
-        ML_report_diffs(start, max, univ1, univ2);
-    );
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_dump(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_bool         verbose = MR_FALSE;
-    MR_Word         browser_term;
-    const char      *problem = NULL;
-    MR_bool         xml = MR_FALSE;
-
-    /*
-    ** Set this to NULL to avoid uninitialization warnings.
-    */
-    browser_term = (MR_Word) NULL;
-
-    if (! MR_trace_options_dump(&xml, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count != 3) {
-        MR_trace_usage_cur_cmd();
-    } else {
-        if (MR_streq(words[1], "goal")) {
-            const char  *name;
-            MR_Word     arg_list;
-            MR_bool     is_func;
-
-            problem = NULL;
-            MR_convert_goal_to_synthetic_term(&name, &arg_list, &is_func);
-            browser_term = MR_synthetic_to_browser_term(name, arg_list,
-                is_func);
-        } else if (MR_streq(words[1], "exception")) {
-            MR_Word exception;
-
-            exception = MR_trace_get_exception_value();
-            if (exception == (MR_Word) NULL) {
-                problem = "missing exception value";
-            } else {
-                browser_term = MR_univ_to_browser_term(exception);
-            }
-        } else if (MR_streq(words[1], "proc_body")) {
-            const MR_Proc_Layout    *entry;
-            MR_Word                 rep;
-
-            entry = event_info->MR_event_sll->MR_sll_entry;
-
-            if (entry->MR_sle_body_bytes == NULL) {
-                problem = "current procedure has no body bytecodes";
-            } else {
-                MR_TRACE_CALL_MERCURY(
-                    MR_DD_trace_read_rep(entry->MR_sle_body_bytes,
-                        event_info->MR_event_sll, &rep);
-                );
-
-                browser_term = MR_type_value_to_browser_term(
-                    (MR_TypeInfo) ML_proc_rep_type(), rep);
-            }
-        } else {
-            MR_Var_Spec var_spec;
-            MR_TypeInfo type_info;
-            MR_Word     value;
-            const char  *name;
-
-            MR_convert_arg_to_var_spec(words[1], &var_spec);
-            problem = MR_lookup_unambiguous_var_spec(var_spec,
-                &type_info, &value, &name);
-            if (problem == NULL) {
-                browser_term = MR_type_value_to_browser_term(type_info, value);
-            }
-        }
-
-        if (problem != NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: %s.\n", problem);
-        } else {
-            if (xml) {
-                MR_trace_save_term_xml(words[2], browser_term);
-            } else {
-                MR_trace_save_term(words[2], browser_term);
-            }
-        }
-    }
-
-    return KEEP_INTERACTING;
-}
-
-/*
-** list [num]
-**  List num lines of context around the line number of the context of the
-**  current point (i.e., level in the call stack).  If num is not given,
-**  the number of context lines defaults to the value of the context_lines
-**  setting.
-**
-** TODO: add the following (use MR_parse_source_locn()):
-** list filename:num[-num]
-**  List a range of lines from a given file.  If only one number is
-**  given, the default number of lines of context is used.
-*/
-
-static MR_Next
-MR_trace_cmd_list(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    const MR_Proc_Layout    *entry_ptr;
-    const char              *filename;
-    int                     lineno;
-    MR_Word                 *base_sp_ptr;
-    MR_Word                 *base_curfr_ptr;
-    MR_bool                 num = MR_num_context_lines;
-    MR_String               aligned_filename;
-
-    MR_trace_listing_path_ensure_init();
-
-    if (word_count > 2) {
-        MR_trace_usage_cur_cmd();
-        return KEEP_INTERACTING;
-    }
-
-    if (word_count == 2 && !MR_trace_is_natural_number(words[1], &num)) {
-        MR_trace_usage_cur_cmd();
-        return KEEP_INTERACTING;
-    }
-
-    MR_trace_current_level_details(&entry_ptr, &filename, &lineno,
-        &base_sp_ptr, &base_curfr_ptr);
-
-    MR_TRACE_USE_HP(
-        MR_make_aligned_string(aligned_filename, (MR_String) filename);
-    );
-
-    MR_TRACE_CALL_MERCURY(
-        ML_LISTING_list_file(MR_mdb_out, MR_mdb_err, (char *) aligned_filename,
-            lineno - num, lineno + num, lineno, MR_listing_path);
-    );
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_set_list_dir_path(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int       i;
-    MR_String aligned_word;
-
-    MR_trace_listing_path_ensure_init();
-
-    MR_TRACE_CALL_MERCURY(
-        ML_LISTING_clear_list_path(MR_listing_path, &MR_listing_path);
-        for(i = word_count - 1; i >= 1; i--) {
-            MR_TRACE_USE_HP(
-                MR_make_aligned_string(aligned_word, (MR_String) words[i]);
-            );
-            ML_LISTING_push_list_path(aligned_word,
-                MR_listing_path, &MR_listing_path);
-        }
-    );
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_push_list_dir(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int       i;
-    MR_String aligned_word;
-
-    MR_trace_listing_path_ensure_init();
-
-    if (word_count < 2) {
-        MR_trace_usage_cur_cmd();
-        return KEEP_INTERACTING;
-    }
-
-    MR_TRACE_CALL_MERCURY(
-        for(i = word_count - 1; i >= 1; i--) {
-            MR_TRACE_USE_HP(
-                MR_make_aligned_string(aligned_word, (MR_String) words[i]);
-            );
-            ML_LISTING_push_list_path(aligned_word,
-                MR_listing_path, &MR_listing_path);
-        }
-    );
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_pop_list_dir(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_trace_listing_path_ensure_init();
-
-    if (word_count > 1) {
-        MR_trace_usage_cur_cmd();
-        return KEEP_INTERACTING;
-    }
-
-    MR_TRACE_CALL_MERCURY(
-        ML_LISTING_pop_list_path(MR_listing_path, &MR_listing_path);
-    );
-
-    return KEEP_INTERACTING;
-}
-
-static  void
-MR_trace_listing_path_ensure_init()
-{
-    static MR_bool  MR_trace_listing_path_initialized = MR_FALSE;
-
-    if (! MR_trace_listing_path_initialized) {
-        MR_TRACE_CALL_MERCURY(
-            MR_listing_path = ML_LISTING_new_list_path();
-        );
-        MR_trace_listing_path_initialized = MR_TRUE;
-    }
-}
-
-static MR_Next
-MR_trace_cmd_break(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    const MR_Label_Layout   *layout;
-    MR_Proc_Spec            spec;
-    MR_Spy_When             when;
-    MR_Spy_Action           action;
-    MR_MultiMatch           multi_match;
-    MR_Spy_Ignore_When      ignore_when;
-    int                     ignore_count;
-    MR_Spy_Print_List       print_list;
-    const char              *file;
-    int                     line;
-    int                     breakline;
-    const char              *problem;
-
-    layout = event_info->MR_event_sll;
-
-    if (word_count == 2 && MR_streq(words[1], "info")) {
-        int i;
-        int count;
-
-        count = 0;
-        for (i = 0; i < MR_spy_point_next; i++) {
-            if (MR_spy_points[i]->spy_exists) {
-                MR_print_spy_point(MR_mdb_out, i, MR_TRUE);
-                count++;
-            }
-        }
-
-        if (count == 0) {
-            fprintf(MR_mdb_out, "There are no break points.\n");
-        }
-
-        return KEEP_INTERACTING;
-    }
-
-    when = MR_default_breakpoint_scope;
-    action = MR_SPY_STOP;
-    multi_match = MR_MULTIMATCH_ASK;
-    /*
-    ** The value of ignore_when doesn't matter
-    ** while ignore_count contains zero.
-    */
-    ignore_when = MR_SPY_DONT_IGNORE;
-    ignore_count = 0;
-    print_list = NULL;
-    if (! MR_trace_options_when_action_multi_ignore(&when, &action,
-        &multi_match, &ignore_when, &ignore_count, &print_list,
-        &words, &word_count))
-    {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 2 && MR_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, MR_TRUE);
-        slot = MR_add_proc_spy_point(MR_SPY_SPECIFIC, action, ignore_when,
-            ignore_count, layout->MR_sll_entry, layout, print_list, &problem);
-        MR_maybe_print_spy_point(slot, problem);
-    } else if (word_count == 2 && MR_parse_proc_spec(words[1], &spec)) {
-        MR_Matches_Info matches;
-        int             slot;
-
-        MR_register_all_modules_and_procs(MR_mdb_out, MR_TRUE);
-        matches = MR_search_for_matching_procedures(&spec);
-        if (matches.match_proc_next == 0) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: there is no such procedure.\n");
-        } else if (matches.match_proc_next == 1) {
-            slot = MR_add_proc_spy_point(when, action, ignore_when,
-                ignore_count, matches.match_procs[0], NULL, print_list,
-                &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, ignore_when,
-                    ignore_count, matches.match_procs[i], NULL, print_list,
-                    &problem);
-                MR_maybe_print_spy_point(slot, problem);
-            }
-        } else {
-            char    buf[80];
-            int     i;
-            char    *line2;
-
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err,
-                "Ambiguous procedure specification. The matches are:\n");
-
-            for (i = 0; i < matches.match_proc_next; i++) {
-                fprintf(MR_mdb_out, "%d: ", i);
-                MR_print_proc_id_and_nl(MR_mdb_out, matches.match_procs[i]);
-            }
-
-            if (multi_match == MR_MULTIMATCH_ONE) {
-                return KEEP_INTERACTING;
-            }
-
-            sprintf(buf, "\nWhich do you want to put "
-                "a breakpoint on (0-%d or *)? ",
-                matches.match_proc_next - 1);
-            line2 = MR_trace_getline(buf, MR_mdb_in, MR_mdb_out);
-            if (line2 == NULL) {
-                /* This means the user input EOF. */
-                fprintf(MR_mdb_out, "none of them\n");
-            } else if (MR_streq(line2, "*")) {
-                for (i = 0; i < matches.match_proc_next; i++) {
-                    slot = MR_add_proc_spy_point(when, action, ignore_when,
-                        ignore_count, matches.match_procs[i], NULL, print_list,
-                        &problem);
-                    MR_maybe_print_spy_point(slot, problem);
-                }
-
-                MR_free(line2);
-            } else if (MR_trace_is_natural_number(line2, &i)) {
-                if (0 <= i && i < matches.match_proc_next) {
-                    slot = MR_add_proc_spy_point(when, action, ignore_when,
-                        ignore_count, matches.match_procs[i], NULL, print_list,
-                        &problem);
-                    MR_maybe_print_spy_point(slot, problem);
-                } else {
-                    fprintf(MR_mdb_out, "no such match\n");
-                }
-                MR_free(line2);
-            } else {
-                fprintf(MR_mdb_out, "none of them\n");
-                MR_free(line2);
-            }
-        }
-    } else if (word_count == 2 &&
-        MR_parse_source_locn(words[1], &file, &line))
-    {
-        int slot;
-
-        slot = MR_add_line_spy_point(action, ignore_when, ignore_count, file,
-            line, print_list, &problem);
-        MR_maybe_print_spy_point(slot, problem);
-    } else if (word_count == 2 &&
-        MR_trace_is_natural_number(words[1], &breakline))
-    {
-        int slot;
-
-        if (MR_find_context(layout, &file, &line)) {
-            slot = MR_add_line_spy_point(action, ignore_when, ignore_count,
-                file, breakline, print_list, &problem);
-            MR_maybe_print_spy_point(slot, problem);
-        } else {
-            MR_fatal_error("cannot find current filename");
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_condition(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, 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))
-    {
-        /* the usage message has already been printed */
-        return KEEP_INTERACTING;
-    } else if (word_count < 4) {
-        MR_trace_usage_cur_cmd();
-        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], "!=") || 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_Code **jumpaddr)
-{
-    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))
-    {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 2 && MR_trace_is_natural_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 && MR_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, "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 {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: there is no most recent break point.\n");
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_break_print(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int                 n;
-    int                 i;
-    MR_Browse_Format    format;
-    MR_bool             at_start;
-    MR_bool             warn;
-    MR_Spy_Print_List   print_list;
-
-    if (! MR_trace_options_break_print(&format, &at_start, &warn,
-        &words, &word_count))
-    {
-        ; /* the usage message has already been printed */
-    } else if (word_count > 2 && MR_trace_is_natural_number(words[1], &n)) {
-        if (word_count == 3 && MR_streq(words[2], "none")) {
-            MR_clear_spy_point_print_list(n);
-            MR_print_spy_point(MR_mdb_out, n, MR_TRUE);
-        } else if (0 <= n && n < MR_spy_point_next
-            && MR_spy_points[n]->spy_exists)
-        {
-            print_list = NULL;
-            for (i = 2; i < word_count; i++) {
-                print_list = MR_add_to_print_list_end(format, words[i], warn,
-                    print_list);
-            }
-
-            if (at_start) {
-                MR_add_spy_point_print_list_start(n, print_list);
-            } else {
-                MR_add_spy_point_print_list_end(n, print_list);
-            }
-
-            MR_print_spy_point(MR_mdb_out, n, MR_TRUE);
-        } else {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: break point #%d does not exist.\n", n);
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Spy_Print_List
-MR_add_to_print_list_end(MR_Browse_Format format, char *word, MR_bool warn,
-    MR_Spy_Print_List print_list)
-{
-    MR_Spy_Print_List   list;
-    MR_Spy_Print_List   new_list;
-    MR_Spy_Print        new_node;
-
-    new_node = MR_malloc(sizeof(struct MR_Spy_Print_Struct));
-    new_node->p_format = format;
-    new_node->p_warn = warn;
-    if (MR_streq(word, "*")) {
-        new_node->p_what = MR_SPY_PRINT_ALL;
-        new_node->p_name = NULL;
-    } else if (MR_streq(word, "goal")) {
-        new_node->p_what = MR_SPY_PRINT_GOAL;
-        new_node->p_name = NULL;
-    } else {
-        new_node->p_what = MR_SPY_PRINT_ONE;
-        new_node->p_name = MR_copy_string(word);
-    }
-
-    new_list = MR_malloc(sizeof(struct MR_Spy_Print_List_Struct));
-    new_list->pl_cur = new_node;
-    new_list->pl_next = NULL;
-
-    list = print_list;
-    if (list == NULL) {
-        return new_list;
-    }
-
-    while (list->pl_next != NULL) {
-        list = list->pl_next;
-    }
-
-    list->pl_next = new_list;
-    return print_list;
-}
-
-static MR_Next
-MR_trace_cmd_enable(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int n;
-
-    if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
-        if (0 <= n && n < MR_spy_point_next && MR_spy_points[n]->spy_exists) {
-            MR_spy_points[n]->spy_enabled = MR_TRUE;
-            MR_print_spy_point(MR_mdb_out, n, MR_FALSE);
-        } else {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: break point #%d does not exist.\n", n);
-        }
-    } else if (word_count == 2 && MR_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) {
-                MR_spy_points[i]->spy_enabled = MR_TRUE;
-                MR_print_spy_point(MR_mdb_out, i, MR_FALSE);
-                count++;
-            }
-        }
-
-        if (count == 0) {
-            fprintf(MR_mdb_err, "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)
-        {
-            MR_spy_points[MR_most_recent_spy_point]->spy_enabled = MR_TRUE;
-            MR_print_spy_point(MR_mdb_out, MR_most_recent_spy_point, MR_FALSE);
-        } else {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: there is no most recent break point.\n");
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_disable(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int n;
-
-    if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
-        if (0 <= n && n < MR_spy_point_next && MR_spy_points[n]->spy_exists) {
-            MR_spy_points[n]->spy_enabled = MR_FALSE;
-            MR_print_spy_point(MR_mdb_out, n, MR_FALSE);
-        } else {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: break point #%d does not exist.\n", n);
-        }
-    } else if (word_count == 2 && MR_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) {
-                MR_spy_points[i]->spy_enabled = MR_FALSE;
-                MR_print_spy_point(MR_mdb_out, i, MR_FALSE);
-                count++;
-            }
-        }
-
-        if (count == 0) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "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)
-        {
-            MR_spy_points[MR_most_recent_spy_point]->spy_enabled = MR_FALSE;
-            MR_print_spy_point(MR_mdb_out, MR_most_recent_spy_point, MR_FALSE);
-        } else {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "There is no most recent break point.\n");
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_delete(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int n;
-
-    if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
-        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);
-            fprintf(MR_mdb_err, "mdb: break point #%d does not exist.\n", n);
-        }
-    } else if (word_count == 2 && MR_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) {
-                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++;
-            }
-        }
-
-        if (count == 0) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "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)
-        {
-            int slot;
-
-            slot = MR_most_recent_spy_point;
-            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);
-            fprintf(MR_mdb_err, "mdb: there is no most recent break point.\n");
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_register(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_bool verbose;
-
-    if (! MR_trace_options_quiet(&verbose, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 1) {
-        MR_register_all_modules_and_procs(MR_mdb_out, verbose);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_modules(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 1) {
-        MR_register_all_modules_and_procs(MR_mdb_out, MR_TRUE);
-        MR_dump_module_list(MR_mdb_out);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_procedures(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 2) {
-        MR_register_all_modules_and_procs(MR_mdb_out, MR_TRUE);
-        MR_dump_module_procs(MR_mdb_out, words[1]);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_query(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_trace_query(MR_NORMAL_QUERY, MR_mmc_options, word_count - 1, words + 1);
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_cc_query(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_trace_query(MR_CC_QUERY, MR_mmc_options, word_count - 1, words + 1);
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_io_query(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_trace_query(MR_IO_QUERY, MR_mmc_options, word_count - 1, words + 1);
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_printlevel(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 2) {
-        if (MR_streq(words[1], "none")) {
-            MR_default_print_level = MR_PRINT_LEVEL_NONE;
-            if (MR_trace_internal_interacting) {
-                fprintf(MR_mdb_out, "Default print level set to `none'.\n");
-            }
-        } else if (MR_streq(words[1], "some")) {
-            MR_default_print_level = MR_PRINT_LEVEL_SOME;
-            if (MR_trace_internal_interacting) {
-                fprintf(MR_mdb_out, "Default print level set to `some'.\n");
-            }
-        } else if (MR_streq(words[1], "all")) {
-            MR_default_print_level = MR_PRINT_LEVEL_ALL;
-            if (MR_trace_internal_interacting) {
-                fprintf(MR_mdb_out, "Default print level set to `all'.\n");
-            }
-        } else {
-            MR_trace_usage_cur_cmd();
-        }
-    } else if (word_count == 1) {
-        fprintf(MR_mdb_out, "The default print level is ");
-        switch (MR_default_print_level) {
-            case MR_PRINT_LEVEL_NONE:
-                fprintf(MR_mdb_out, "`none'.\n");
-                break;
-            case MR_PRINT_LEVEL_SOME:
-                fprintf(MR_mdb_out, "`some'.\n");
-                break;
-            case MR_PRINT_LEVEL_ALL:
-                fprintf(MR_mdb_out, "`all'.\n");
-                break;
-            default:
-                MR_default_print_level = MR_PRINT_LEVEL_SOME;
-                fprintf(MR_mdb_out, "invalid (now set to `some').\n");
-                break;
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_mmc_options(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    size_t len;
-    size_t i;
-
-    /* allocate the right amount of space */
-    len = 0;
-    for (i = 1; i < word_count; i++) {
-        len += strlen(words[i]) + 1;
-    }
-    len++;
-    MR_mmc_options = MR_realloc(MR_mmc_options, len);
-
-    /* copy the arguments to MR_mmc_options */
-    MR_mmc_options[0] = '\0';
-    for (i = 1; i < word_count; i++) {
-        strcat(MR_mmc_options, words[i]);
-        strcat(MR_mmc_options, " ");
-    }
-    MR_mmc_options[len - 1] = '\0';
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_scroll(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int n;
-
-    if (word_count == 2) {
-        if (MR_streq(words[1], "off")) {
-            MR_scroll_control = MR_FALSE;
-            if (MR_trace_internal_interacting) {
-                fprintf(MR_mdb_out, "Scroll control disabled.\n");
-            }
-        } else if (MR_streq(words[1], "on")) {
-            MR_scroll_control = MR_TRUE;
-            if (MR_trace_internal_interacting) {
-                fprintf(MR_mdb_out, "Scroll control enabled.\n");
-            }
-        } else if (MR_trace_is_natural_number(words[1], &n)) {
-            MR_scroll_limit = n;
-            if (MR_trace_internal_interacting) {
-                fprintf(MR_mdb_out,
-                    "Scroll window size set to %d.\n", MR_scroll_limit);
-            }
-        } else {
-            MR_trace_usage_cur_cmd();
-        }
-    } else if (word_count == 1) {
-        fprintf(MR_mdb_out, "Scroll control is ");
-        if (MR_scroll_control) {
-            fprintf(MR_mdb_out, "on");
-        } else {
-            fprintf(MR_mdb_out, "off");
-        }
-        fprintf(MR_mdb_out, ", scroll window size is %d.\n", MR_scroll_limit);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_stack_default_limit(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int n;
-
-    if (word_count == 2) {
-        if (MR_trace_is_natural_number(words[1], &n)) {
-            MR_stack_default_line_limit = n;
-            if (! MR_trace_internal_interacting) {
-                return KEEP_INTERACTING;
-            }
-
-            if (MR_stack_default_line_limit > 0) {
-                fprintf(MR_mdb_out,
-                    "Default stack dump size limit set to %d.\n",
-                    MR_stack_default_line_limit);
-            } else {
-                fprintf(MR_mdb_out,
-                    "Default stack dump size limit set to none.\n");
-            }
-        } else {
-            MR_trace_usage_cur_cmd();
-        }
-    } else if (word_count == 1) {
-        if (MR_stack_default_line_limit > 0) {
-            fprintf(MR_mdb_out, "Default stack dump size limit is %d.\n",
-                MR_stack_default_line_limit);
-        } else {
-            fprintf(MR_mdb_out,
-                "There is no default stack dump size limit.\n");
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_context(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 2) {
-        if (MR_streq(words[1], "none")) {
-            MR_context_position = MR_CONTEXT_NOWHERE;
-        } else if (MR_streq(words[1], "before")) {
-            MR_context_position = MR_CONTEXT_BEFORE;
-        } else if (MR_streq(words[1], "after")) {
-            MR_context_position = MR_CONTEXT_AFTER;
-        } else if (MR_streq(words[1], "prevline")) {
-            MR_context_position = MR_CONTEXT_PREVLINE;
-        } else if (MR_streq(words[1], "nextline")) {
-            MR_context_position = MR_CONTEXT_NEXTLINE;
-        } else {
-            MR_trace_usage_cur_cmd();
-            return KEEP_INTERACTING;
-        }
-
-        if (MR_trace_internal_interacting) {
-            fprintf(MR_mdb_out, "%s\n",
-                MR_context_set_msg[MR_context_position]);
-        }
-    } else if (word_count == 1) {
-        switch (MR_context_position) {
-        case MR_CONTEXT_NOWHERE:
-        case MR_CONTEXT_BEFORE:
-        case MR_CONTEXT_AFTER:
-        case MR_CONTEXT_PREVLINE:
-        case MR_CONTEXT_NEXTLINE:
-            fprintf(MR_mdb_out, "%s\n",
-                MR_context_report_msg[MR_context_position]);
-            break;
-
-        default:
-            MR_fatal_error("invalid MR_context_position");
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_goal_paths(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 2) {
-        if (MR_streq(words[1], "off")) {
-            MR_print_goal_paths = MR_FALSE;
-            fprintf(MR_mdb_out, "Goal path printing is now off.\n");
-        } else if (MR_streq(words[1], "on")) {
-            MR_print_goal_paths = MR_TRUE;
-            fprintf(MR_mdb_out, "Goal path printing is now on.\n");
-        } else {
-            MR_trace_usage_cur_cmd();
-            return KEEP_INTERACTING;
-        }
-    } else if (word_count == 1) {
-        if (MR_print_goal_paths) {
-            fprintf(MR_mdb_out, "Goal path printing is on.\n");
-        } else {
-            fprintf(MR_mdb_out, "Goal path printing is off.\n");
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_scope(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 2) {
-        if (MR_streq(words[1], "all")) {
-            MR_default_breakpoint_scope = MR_SPY_ALL;
-        } else if (MR_streq(words[1], "interface")) {
-            MR_default_breakpoint_scope = MR_SPY_INTERFACE;
-        } else if (MR_streq(words[1], "entry")) {
-            MR_default_breakpoint_scope = MR_SPY_ENTRY;
-        } else {
-            MR_trace_usage_cur_cmd();
-            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_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_echo(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 2) {
-        if (MR_streq(words[1], "off")) {
-            MR_echo_commands = MR_FALSE;
-            if (MR_trace_internal_interacting) {
-                fprintf(MR_mdb_out, "Command echo disabled.\n");
-            }
-        } else if (MR_streq(words[1], "on")) {
-            if (!MR_echo_commands) {
-                /*
-                ** Echo the `echo on' command. This is needed for historical
-                ** reasons (compatibility with our existing test suite).
-                */
-                fprintf(MR_mdb_out, "echo on\n");
-                MR_echo_commands = MR_TRUE;
-            }
-            if (MR_trace_internal_interacting) {
-                fprintf(MR_mdb_out, "Command echo enabled.\n");
-            }
-        } else {
-            MR_trace_usage_cur_cmd();
-        }
-    } else if (word_count == 1) {
-        fprintf(MR_mdb_out, "Command echo is ");
-        if (MR_echo_commands) {
-            fprintf(MR_mdb_out, "on.\n");
-        } else {
-            fprintf(MR_mdb_out, "off.\n");
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_alias(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 1) {
-        MR_trace_print_all_aliases(MR_mdb_out, MR_FALSE);
-    } else if (word_count == 2) {
-        MR_trace_print_alias(MR_mdb_out, words[1]);
-    } else {
-        if (MR_trace_valid_command(words[2])) {
-            MR_trace_add_alias(words[1], words+2, word_count-2);
-            if (MR_trace_internal_interacting) {
-                MR_trace_print_alias(MR_mdb_out, words[1]);
-            }
-        } else {
-            fprintf(MR_mdb_out, "`%s' is not a valid command.\n", words[2]);
-        }
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_unalias(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 2) {
-        if (MR_trace_remove_alias(words[1])) {
-            if (MR_trace_internal_interacting) {
-                fprintf(MR_mdb_out, "Alias `%s' removed.\n", words[1]);
-            }
-        } else {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err,
-                "Alias `%s' cannot be removed, since it does not exist.\n",
-                words[1]);
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_document_category(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int         slot;
-    const char  *msg;
-    const char  *help_text;
-
-    help_text = MR_trace_read_help_text();
-    if (word_count != 3) {
-        MR_trace_usage_cur_cmd();
-    } else if (! MR_trace_is_natural_number(words[1], &slot)) {
-        MR_trace_usage_cur_cmd();
-    } else {
-        msg = MR_trace_add_cat(words[2], slot, help_text);
-        if (msg != NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err,
-                "Document category `%s' not added: %s.\n", words[2], msg);
-        }
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_document(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int         slot;
-    const char  *msg;
-    const char  *help_text;
-
-    help_text = MR_trace_read_help_text();
-    if (word_count != 4) {
-        MR_trace_usage_cur_cmd();
-    } else if (! MR_trace_is_natural_number(words[2], &slot)) {
-        MR_trace_usage_cur_cmd();
-    } else {
-        msg = MR_trace_add_item(words[1], words[3], slot, help_text);
-        if (msg != NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err,
-                "Document item `%s' in category `%s' not added: %s.\n",
-                words[3], words[1], msg);
-        }
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_help(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 1) {
-        MR_trace_help();
-    } else if (word_count == 2) {
-        MR_trace_help_word(words[1]);
-    } else if (word_count == 3) {
-        MR_trace_help_cat_item(words[1], words[2]);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_histogram_all(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-#ifdef  MR_TRACE_HISTOGRAM
-
-    if (word_count == 2) {
-        FILE    *fp;
-
-        fp = fopen(words[1], "w");
-        if (fp == NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: cannot open file `%s' for output: %s.\n",
-                words[1], strerror(errno));
-        } else {
-            MR_trace_print_histogram(fp, "All-inclusive",
-                MR_trace_histogram_all,
-                MR_trace_histogram_hwm);
-            if (fclose(fp) != 0) {
-                fflush(MR_mdb_out);
-                fprintf(MR_mdb_err, "mdb: error closing file `%s': %s.\n",
-                    words[1], strerror(errno));
-            }
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-#else   /* MR_TRACE_HISTOGRAM */
-
-    fprintf(MR_mdb_out, "mdb: the `histogram_all' command is available "
-        "only when histogram gathering is enabled.\n");
-
-#endif  /* MR_TRACE_HISTOGRAM */
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_histogram_exp(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-#ifdef  MR_TRACE_HISTOGRAM
-
-    if (word_count == 2) {
-        FILE    *fp;
-
-        fp = fopen(words[1], "w");
-        if (fp == NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: cannot open file `%s' for output: %s.\n",
-                words[1], strerror(errno));
-        } else {
-            MR_trace_print_histogram(fp, "Experimental",
-                MR_trace_histogram_exp,
-                MR_trace_histogram_hwm);
-            if (fclose(fp) != 0) {
-                fflush(MR_mdb_out);
-                fprintf(MR_mdb_err, "mdb: error closing file `%s': %s.\n",
-                    words[1], strerror(errno));
-            }
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-#else   /* MR_TRACE_HISTOGRAM */
-
-    fprintf(MR_mdb_out, "mdb: the `histogram_exp' command is available "
-        "only when histogram gathering is enabled.\n");
-
-#endif  /* MR_TRACE_HISTOGRAM */
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_clear_histogram(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-#ifdef  MR_TRACE_HISTOGRAM
-
-    if (word_count == 1) {
-        int i;
-
-        for (i = 0; i <= MR_trace_histogram_hwm; i++) {
-            MR_trace_histogram_exp[i] = 0;
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-#else   /* MR_TRACE_HISTOGRAM */
-
-    fprintf(MR_mdb_out, "mdb: the `clear_histogram' command is available "
-        "only when histogram gathering is enabled.\n");
-
-#endif  /* MR_TRACE_HISTOGRAM */
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_var_details(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int n;
-
-    if (word_count == 1) {
-        const char  *problem;
-
-        problem = MR_trace_list_var_details(MR_mdb_out);
-        if (problem != NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: %s.\n", problem);
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_term_size(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int n;
-
-    if (word_count == 2) {
-        const char  *problem;
-
-        if (MR_streq(words[1], "*")) {
-            problem = MR_trace_print_size_all(MR_mdb_out);
-        } else {
-            problem = MR_trace_print_size_one(MR_mdb_out, words[1]);
-        }
-
-        if (problem != NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: %s.\n", problem);
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_flag(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    const char  *name;
-    MR_bool     *flagptr;
-    int         i;
-    MR_bool     found;
-    const char  *set_word;
-
-    /*
-    ** Set this to NULL to avoid uninitialization warnings.
-    */
-    flagptr = NULL;
-
-    if (word_count == 1) {
-        for (i = 0; i < MR_MAXFLAG; i++) {
-            /*
-            ** The true values of the debugging flags are stored
-            ** in MR_saved_debug_state inside the call tree
-            ** of MR_trace_event.
-            */
-            flagptr = &MR_saved_debug_state.MR_sds_debugflags[
-                MR_debug_flag_info[i].MR_debug_flag_index];
-            name = MR_debug_flag_info[i].MR_debug_flag_name;
-            if (*flagptr) {
-                fprintf(MR_mdb_out, "Flag %s is set.\n", name);
-            } else {
-                fprintf(MR_mdb_out, "Flag %s is clear.\n", name);
-            }
-        }
-        return KEEP_INTERACTING;
-    } else if (word_count == 2) {
-        name = words[1];
-        set_word = NULL;
-    } else if (word_count == 3) {
-        name = words[1];
-        set_word = words[2];
-    } else {
-        MR_trace_usage_cur_cmd();
-        return KEEP_INTERACTING;
-    }
-
-    found = MR_FALSE;
-    for (i = 0; i < MR_MAXFLAG; i++) {
-        if (MR_streq(MR_debug_flag_info[i].MR_debug_flag_name, name)) {
-            /*
-            ** The true values of the debugging flags are stored
-            ** in MR_saved_debug_state inside the call tree
-            ** of MR_trace_event.
-            */
-            flagptr = &MR_saved_debug_state.MR_sds_debugflags[
-                MR_debug_flag_info[i].MR_debug_flag_index];
-            found = MR_TRUE;
-            break;
-        }
-    }
-
-    if (!found) {
-        fprintf(MR_mdb_out, "There is no flag named %s.\n", name);
-        return KEEP_INTERACTING;
-    }
-
-    if (set_word != NULL) {
-        if (MR_streq(set_word, "on")) {
-            *flagptr = MR_TRUE;
-            fprintf(MR_mdb_out, "Flag %s is now set.\n", name);
-        } else if (MR_streq(set_word, "off")) {
-            *flagptr = MR_FALSE;
-            fprintf(MR_mdb_out, "Flag %s is now clear.\n", name);
-        } else {
-            MR_trace_usage_cur_cmd();
-        }
-    } else {
-        if (*flagptr) {
-            fprintf(MR_mdb_out, "Flag %s is set.\n", name);
-        } else {
-            fprintf(MR_mdb_out, "Flag %s is clear.\n", name);
-        }
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_subgoal(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
-
-    MR_SubgoalDebug *subgoal_debug;
-    MR_Subgoal  *subgoal;
-    int     n;
-
-    if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
-        MR_trace_init_modules();
-
-        subgoal_debug = MR_lookup_subgoal_debug_num(n);
-        if (subgoal_debug == NULL) {
-            fprintf(MR_mdb_out, "no such subgoal\n");
-        } else {
-            MR_trace_print_subgoal_debug(NULL, subgoal_debug);
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-#else   /* MR_USE_MINIMAL_MODEL_STACK_COPY */
-
-    fprintf(MR_mdb_out, "mdb: the `subgoal' command is available "
-        "only in stack copy minimal model tabling grades.\n");
-
-#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_consumer(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
-
-    MR_ConsumerDebug    *consumer_debug;
-    MR_Consumer         *consumer;
-    int                 n;
-
-    if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) {
-        MR_trace_init_modules();
-
-        consumer_debug = MR_lookup_consumer_debug_num(n);
-        if (consumer_debug == NULL) {
-            fprintf(MR_mdb_out, "no such consumer\n");
-        } else {
-            MR_trace_print_consumer_debug(NULL, consumer_debug);
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-#else   /* MR_USE_MINIMAL_MODEL_STACK_COPY */
-
-    fprintf(MR_mdb_out, "mdb: the `consumer' command is available "
-        "only in stack copy minimal model tabling grades.\n");
-
-#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_gen_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
-
-    if (word_count == 1) {
-        MR_bool saved_tabledebug;
-
-        MR_trace_init_modules();
-        saved_tabledebug = MR_tabledebug;
-        MR_tabledebug = MR_TRUE;
-        MR_print_gen_stack(MR_mdb_out);
-        MR_tabledebug = saved_tabledebug;
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-#else   /* MR_USE_MINIMAL_MODEL_STACK_COPY */
-
-    fprintf(MR_mdb_out, "mdb: the `gen_stack' command is available "
-        "only in stack copy minimal model tabling grades.\n");
-
-#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_cut_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
-
-    if (word_count == 1) {
-        MR_bool saved_tabledebug;
-
-        MR_trace_init_modules();
-        saved_tabledebug = MR_tabledebug;
-        MR_tabledebug = MR_TRUE;
-        MR_print_cut_stack(MR_mdb_out);
-        MR_tabledebug = saved_tabledebug;
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-#else   /* MR_USE_MINIMAL_MODEL_STACK_COPY */
-
-    fprintf(MR_mdb_out, "mdb: the `cut_stack' command is available "
-        "only in stack copy minimal model tabling grades.\n");
-
-#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_pneg_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
-
-    if (word_count == 1) {
-        MR_bool saved_tabledebug;
-
-        MR_trace_init_modules();
-        saved_tabledebug = MR_tabledebug;
-        MR_tabledebug = MR_TRUE;
-        MR_print_pneg_stack(MR_mdb_out);
-        MR_tabledebug = saved_tabledebug;
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-#else   /* MR_USE_MINIMAL_MODEL_STACK_COPY */
-
-    fprintf(MR_mdb_out, "mdb: the `pneg_stack' command is available "
-        "only in stack copy minimal model tabling grades.\n");
-
-#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_mm_stacks(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
-
-    if (word_count == 1) {
-        MR_bool saved_tabledebug;
-
-        MR_trace_init_modules();
-        saved_tabledebug = MR_tabledebug;
-        MR_tabledebug = MR_TRUE;
-        MR_print_gen_stack(MR_mdb_out);
-        fprintf(MR_mdb_out, "\n");
-        MR_print_cut_stack(MR_mdb_out);
-        fprintf(MR_mdb_out, "\n");
-        MR_print_pneg_stack(MR_mdb_out);
-        MR_tabledebug = saved_tabledebug;
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-#else   /* MR_USE_MINIMAL_MODEL_STACK_COPY */
-
-    fprintf(MR_mdb_out, "mdb: the `pneg_stack' command is available "
-        "only in stack copy minimal model tabling grades.\n");
-
-#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_nondet_stack(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_bool     detailed;
-    int         frame_limit = 0;
-    int         line_limit = MR_stack_default_line_limit;
-    int         spec_line_limit;
-
-    detailed = MR_FALSE;
-    if (! MR_trace_options_stack_trace(&detailed, &frame_limit,
-        &words, &word_count))
-    {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 1) {
-        MR_trace_cmd_nondet_stack_2(event_info, detailed, frame_limit,
-            line_limit);
-    } else if (word_count == 2 &&
-        MR_trace_is_natural_number(words[1], &spec_line_limit))
-    {
-        MR_trace_cmd_nondet_stack_2(event_info, detailed, frame_limit,
-            spec_line_limit);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static void
-MR_trace_cmd_nondet_stack_2(MR_Event_Info *event_info, MR_bool detailed,
-    int frame_limit, int line_limit)
-{
-    const MR_Label_Layout   *layout;
-    MR_Word                 *saved_regs;
-
-    layout = event_info->MR_event_sll;
-    saved_regs = event_info->MR_saved_regs;
-
-    MR_trace_init_modules();
-    if (detailed) {
-        int saved_level;
-
-        saved_level = MR_trace_current_level();
-        MR_dump_nondet_stack_from_layout(MR_mdb_out, NULL, frame_limit,
-            line_limit, MR_saved_maxfr(saved_regs), layout,
-            MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs));
-        MR_trace_set_level(saved_level, MR_print_optionals);
-    } else {
-        MR_dump_nondet_stack(MR_mdb_out, NULL, frame_limit, line_limit,
-            MR_saved_maxfr(saved_regs));
-    }
-}
-
-static MR_Next
-MR_trace_cmd_stack_regs(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_Word     *saved_regs;
-
-    saved_regs = event_info->MR_saved_regs;
-
-    if (word_count == 1) {
-        MR_print_stack_regs(MR_mdb_out, saved_regs);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_all_regs(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_Word     *saved_regs;
-
-    saved_regs = event_info->MR_saved_regs;
-
-    if (word_count == 1) {
-        MR_print_stack_regs(MR_mdb_out, saved_regs);
-        MR_print_heap_regs(MR_mdb_out, saved_regs);
-        MR_print_tabling_regs(MR_mdb_out, saved_regs);
-        MR_print_succip_reg(MR_mdb_out, saved_regs);
-        MR_print_r_regs(MR_mdb_out, saved_regs);
-#ifdef  MR_DEEP_PROFILING
-        MR_print_deep_prof_vars(MR_mdb_out, "mdb all_regs");
-#endif
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_debug_vars(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 1) {
-        MR_print_debug_vars(MR_mdb_out, event_info);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_table_io(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 1) {
-        if (! MR_io_tabling_allowed) {
-            fprintf(MR_mdb_err,
-                "This executable wasn't prepared for I/O tabling.\n");
-            return KEEP_INTERACTING;
-        }
-
-        if (MR_io_tabling_phase == MR_IO_TABLING_BEFORE) {
-            fprintf(MR_mdb_out, "I/O tabling has not yet started.\n");
-        } else if (MR_io_tabling_phase == MR_IO_TABLING_DURING) {
-            fprintf(MR_mdb_out, "I/O tabling has started.\n");
-        } else if (MR_io_tabling_phase == MR_IO_TABLING_AFTER) {
-            fprintf(MR_mdb_out, "I/O tabling has stopped.\n");
-        } else {
-            MR_fatal_error("I/O tabling in impossible phase.\n");
-        }
-    } else if (word_count == 2 && (MR_streq(words[1], "start")
-        || MR_streq(words[1], "begin")))
-    {
-        if (! MR_io_tabling_allowed) {
-            fprintf(MR_mdb_err,
-                "This executable wasn't prepared for I/O tabling.\n");
-            return KEEP_INTERACTING;
-        }
-
-        if (MR_io_tabling_phase == MR_IO_TABLING_BEFORE) {
-            MR_io_tabling_phase = MR_IO_TABLING_DURING;
-            MR_io_tabling_start = MR_io_tabling_counter;
-            MR_io_tabling_end = MR_IO_ACTION_MAX;
-            MR_io_tabling_start_event_num = event_info->MR_event_number;
-#ifdef  MR_DEBUG_RETRY
-            MR_io_tabling_debug = MR_TRUE;
-#endif
-            fprintf(MR_mdb_out, "I/O tabling started.\n");
-        } else if (MR_io_tabling_phase == MR_IO_TABLING_DURING) {
-            fprintf(MR_mdb_out, "I/O tabling has already started.\n");
-        } else if (MR_io_tabling_phase == MR_IO_TABLING_AFTER) {
-            fprintf(MR_mdb_out, "I/O tabling has already stopped.\n");
-        } else {
-            MR_fatal_error("I/O tabling in impossible phase.\n");
-        }
-    } else if (word_count == 2 && (MR_streq(words[1], "stop")
-        || MR_streq(words[1], "end")))
-    {
-        if (! MR_io_tabling_allowed) {
-            fprintf(MR_mdb_err,
-                "This executable wasn't prepared for I/O tabling.\n");
-            return KEEP_INTERACTING;
-        }
-
-        if (MR_io_tabling_phase == MR_IO_TABLING_BEFORE) {
-            fprintf(MR_mdb_out, "I/O tabling has not yet started.\n");
-        } else if (MR_io_tabling_phase == MR_IO_TABLING_DURING) {
-            MR_io_tabling_phase = MR_IO_TABLING_AFTER;
-            MR_io_tabling_end = MR_io_tabling_counter_hwm;
-            MR_io_tabling_stop_event_num = event_info->MR_event_number;
-            fprintf(MR_mdb_out, "I/O tabling stopped.\n");
-        } else if (MR_io_tabling_phase == MR_IO_TABLING_AFTER) {
-            fprintf(MR_mdb_out, "I/O tabling has already stopped.\n");
-        } else {
-            MR_fatal_error("I/O tabling in impossible phase.\n");
-        }
-    } else if (word_count == 2 && MR_streq(words[1], "stats")) {
-        if (! MR_io_tabling_allowed) {
-            fprintf(MR_mdb_err,
-                "This executable wasn't prepared for I/O tabling.\n");
-            return KEEP_INTERACTING;
-        }
-
-        fprintf(MR_mdb_out, "phase = %d\n", MR_io_tabling_phase);
-        MR_print_unsigned_var(MR_mdb_out, "counter", MR_io_tabling_counter);
-        MR_print_unsigned_var(MR_mdb_out, "hwm", MR_io_tabling_counter_hwm);
-        MR_print_unsigned_var(MR_mdb_out, "start", MR_io_tabling_start);
-        MR_print_unsigned_var(MR_mdb_out, "end", MR_io_tabling_end);
-    } else if (word_count == 2 && MR_streq(words[1], "allow")) {
-        /*
-        ** The "table_io allow" command allows the programmer to give
-        ** the command "table_io start" even in grades in which there
-        ** is no guarantee that all I/O primitives are tabled. It is
-        ** for developers only, because if it is used on programs in
-        ** which some but not all I/O primitives are tabled, the
-        ** results of turning on I/O tabling can be weird.
-        */
-
-        MR_io_tabling_allowed = MR_TRUE;
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_stats(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    char    *filename;
-    FILE    *fp;
-    MR_bool should_close;
-
-    filename = NULL;
-    if (! MR_trace_options_stats(&filename, &words, &word_count)) {
-        /* the usage message has already been printed */
-        return KEEP_INTERACTING;
-    }
-
-    if (word_count != 2) {
-        MR_trace_usage_cur_cmd();
-    }
-
-    if (filename != NULL) {
-        fp = fopen(filename, "w");
-        if (fp == NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: error opening `%s': %s.\n",
-                filename, strerror(errno));
-            return KEEP_INTERACTING;
-        }
-
-        should_close = MR_TRUE;
-    } else {
-        fp = MR_mdb_out;
-        should_close = MR_FALSE;
-    }
-
-    if (MR_streq(words[1], "procs")) {
-        MR_proc_layout_stats(fp);
-    } else if (MR_streq(words[1], "labels")) {
-        MR_label_layout_stats(fp);
-    } else if (MR_streq(words[1], "var_names")) {
-        MR_var_name_stats(fp);
-    } else if (MR_streq(words[1], "io_tabling")) {
-        MR_io_tabling_stats(fp);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    if (should_close) {
-        (void) fclose(fp);
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_print_optionals(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 2 && MR_streq(words[1], "off")) {
-        MR_print_optionals = MR_FALSE;
-        MR_trace_set_level(MR_trace_current_level(), MR_print_optionals);
-    } else if (word_count == 2 && MR_streq(words[1], "on")) {
-        MR_print_optionals = MR_TRUE;
-        MR_trace_set_level(MR_trace_current_level(), MR_print_optionals);
-    } else if (word_count == 1) {
-        fprintf(MR_mdb_out, "optional values are %sbeing printed\n",
-            MR_print_optionals? "" : "not ");
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_unhide_events(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 2 && MR_streq(words[1], "off")) {
-        MR_trace_unhide_events = MR_FALSE;
-        fprintf(MR_mdb_out, "Hidden events are hidden.\n");
-    } else if (word_count == 2 && MR_streq(words[1], "on")) {
-        MR_trace_unhide_events = MR_TRUE;
-        MR_trace_have_unhid_events = MR_TRUE;
-        fprintf(MR_mdb_out, "Hidden events are exposed.\n");
-    } else if (word_count == 1) {
-        fprintf(MR_mdb_out, "Hidden events are %s.\n",
-            MR_trace_unhide_events? "exposed" : "hidden");
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static const MR_Proc_Layout *
-MR_find_single_matching_proc(MR_Proc_Spec *spec, MR_bool verbose)
-{
-    MR_Matches_Info     matches;
-    int                 n;
-    int                 i;
-
-    MR_register_all_modules_and_procs(MR_mdb_out, verbose);
-    matches = MR_search_for_matching_procedures(spec);
-    if (matches.match_proc_next == 0) {
-        fflush(MR_mdb_out);
-        fprintf(MR_mdb_err, "mdb: there is no such procedure.\n");
-        return NULL;
-    } else if (matches.match_proc_next == 1) {
-        return matches.match_procs[0];
-    } else {
-        char    buf[100];
-        char    *line2;
-
-        fflush(MR_mdb_out);
-        fprintf(MR_mdb_err, "Ambiguous procedure specification. "
-            "The matches are:\n");
-        for (i = 0; i < matches.match_proc_next; i++) {
-            fprintf(MR_mdb_out, "%d: ", i);
-            MR_print_proc_id_and_nl(MR_mdb_out, matches.match_procs[i]);
-        }
-
-        sprintf(buf, "\nWhich procedure's table do you want to print (0-%d)? ",
-            matches.match_proc_next - 1);
-        line2 = MR_trace_getline(buf, MR_mdb_in, MR_mdb_out);
-        n = -1;
-        if (line2 == NULL || !MR_trace_is_natural_number(line2, &n)) {
-            n = -1;
-            fprintf(MR_mdb_out, "none of them\n");
-        } else if (n < 0 || n >= matches.match_proc_next) {
-            n = -1;
-            fprintf(MR_mdb_out, "invalid choice\n");
-        }
-
-        if (line2 != NULL) {
-            MR_free(line2);
-        }
-
-        if (n >= 0) {
-            return matches.match_procs[n];
-        } else {
-            return NULL;
-        }
-    }
-}
-
-static MR_Next
-MR_trace_cmd_table(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_Call_Table_Arg       *call_table_args;
-    const MR_Proc_Layout    *proc;
-    MR_Proc_Spec            spec;
-    const MR_Table_Gen      *table_gen;
-    MR_TrieNode             table_cur;
-    int                     num_inputs;
-    int                     filtered_num_inputs;
-    int                     cur_arg;
-    int                     filtered_cur_arg;
-    int                     num_tips;
-
-    if (word_count < 2) {
-        MR_trace_usage_cur_cmd();
-        return KEEP_INTERACTING;
-    }
-
-    if (! MR_parse_proc_spec(words[1], &spec)) {
-        fflush(MR_mdb_out);
-        fprintf(MR_mdb_err, "mdb: invalid procedure specification.\n");
-        return KEEP_INTERACTING;
-    }
-
-    proc = MR_find_single_matching_proc(&spec, MR_TRUE);
-    if (proc == NULL) {
-        return KEEP_INTERACTING;
-    }
-
-    switch (MR_sle_eval_method(proc)) {
-        case MR_EVAL_METHOD_NORMAL:
-            MR_print_proc_id(MR_mdb_out, proc);
-            fprintf(MR_mdb_out, " isn't tabled.\n");
-            return KEEP_INTERACTING;
-
-        case MR_EVAL_METHOD_LOOP_CHECK:
-        case MR_EVAL_METHOD_MEMO_STRICT:
-        case MR_EVAL_METHOD_MEMO_FAST_LOOSE:
-        case MR_EVAL_METHOD_MEMO_SPECIFIED:
-        case MR_EVAL_METHOD_MINIMAL_STACK_COPY:
-        case MR_EVAL_METHOD_MINIMAL_OWN_STACKS:
-            break;
-
-        case MR_EVAL_METHOD_TABLE_IO:
-        case MR_EVAL_METHOD_TABLE_IO_DECL:
-        case MR_EVAL_METHOD_TABLE_IO_UNITIZE:
-        case MR_EVAL_METHOD_TABLE_IO_UNITIZE_DECL:
-            fprintf(MR_mdb_out,
-                "IO tabled predicates do not have their own tables.\n");
-            return KEEP_INTERACTING;
-    }
-
-    /*
-    ** words[0] is the command, words[1] is the procedure spec;
-    ** words[2] is the first argument. We step over the command and the
-    ** procedure spec, to leave words[] containing only the argument
-    ** values.
-    */
-
-    words += 2;
-    word_count -= 2;
-
-    table_gen = proc->MR_sle_table_info.MR_table_gen;
-    num_inputs = table_gen->MR_table_gen_num_inputs;
-
-    if (word_count > num_inputs) {
-        fprintf(MR_mdb_out, "There are only %d input arguments.\n",
-            num_inputs);
-        return KEEP_INTERACTING;
-    }
-
-    call_table_args = MR_GC_NEW_ARRAY(MR_Call_Table_Arg, num_inputs);
-    if (call_table_args == NULL) {
-        MR_fatal_error("MR_trace_cmd_table: "
-            "couldn't allocate call_table_args");
-    }
-
-    table_cur = proc->MR_sle_tabling_pointer;
-    for (cur_arg = 0, filtered_cur_arg = 0; cur_arg < num_inputs; cur_arg++) {
-        switch (table_gen->MR_table_gen_input_steps[cur_arg]) {
-            case MR_TABLE_STEP_INT:
-            case MR_TABLE_STEP_FLOAT:
-            case MR_TABLE_STEP_STRING:
-                /* these are OK */
-                call_table_args[filtered_cur_arg].MR_cta_step =
-                    table_gen->MR_table_gen_input_steps[filtered_cur_arg];
-                call_table_args[filtered_cur_arg].MR_cta_valid = MR_FALSE;
-                call_table_args[filtered_cur_arg].MR_cta_unfiltered_arg_num =
-                    cur_arg;
-                filtered_cur_arg++;
-
-            case MR_TABLE_STEP_PROMISE_IMPLIED:
-                /* this argument doesn't exist in the table */
-                break;
-
-            default:
-                fprintf(MR_mdb_out, "Sorry, can handle only "
-                    "integer, float and string arguments for now.\n");
-                MR_GC_free(call_table_args);
-                return KEEP_INTERACTING;
-        }
-    }
-
-    filtered_num_inputs = filtered_cur_arg;
-    if (word_count > filtered_num_inputs) {
-        fprintf(MR_mdb_out,
-            "Sorry, this procedure has only %d tabled arguments\n",
-            filtered_num_inputs);
-        MR_GC_free(call_table_args);
-        return KEEP_INTERACTING;
-    }
-
-    /*
-    ** Set up the values of the input arguments supplied on the command
-    ** line, to enable us to print them out in each call table entry.
-    */
-
-    for (filtered_cur_arg = 0;
-        filtered_cur_arg < word_count;
-        filtered_cur_arg++)
-    {
-        MR_bool success;
-
-        switch (call_table_args[filtered_cur_arg].MR_cta_step) {
-            case MR_TABLE_STEP_INT:
-                success = MR_trace_fill_in_int_table_arg_slot(&table_cur,
-                    filtered_cur_arg + 1, words[filtered_cur_arg],
-                    &call_table_args[filtered_cur_arg]);
-                break;
-
-            case MR_TABLE_STEP_FLOAT:
-                success = MR_trace_fill_in_float_table_arg_slot(&table_cur,
-                    filtered_cur_arg + 1, words[filtered_cur_arg],
-                    &call_table_args[filtered_cur_arg]);
-                break;
-
-            case MR_TABLE_STEP_STRING:
-                success = MR_trace_fill_in_string_table_arg_slot(&table_cur,
-                    filtered_cur_arg + 1, words[filtered_cur_arg],
-                    &call_table_args[filtered_cur_arg]);
-                break;
-
-            default:
-                MR_fatal_error("arg not int, float or string after check");
-        }
-
-        if (! success) {
-            /* the error message has already been printed */
-            MR_GC_free(call_table_args);
-            return KEEP_INTERACTING;
-        }
-    }
-
-    if (word_count == filtered_num_inputs) {
-        /*
-        ** The user specified values for all the input arguments,
-        ** so what we print is a single entry, not a table of entries,
-        ** and we don't need to loop over all the entries.
-        */
-
-        MR_trace_cmd_table_print_tip(proc, filtered_num_inputs,
-            call_table_args, table_cur);
-        MR_GC_free(call_table_args);
-        return KEEP_INTERACTING;
-    }
-
-    /*
-    ** The user left the values of some input arguments unspecified,
-    ** so we print a table of entries. Here we print the header.
-    */
-
-    switch (MR_sle_eval_method(proc)) {
-        case MR_EVAL_METHOD_LOOP_CHECK:
-            fprintf(MR_mdb_out, "loopcheck table for ");
-            MR_print_proc_id(MR_mdb_out, proc);
-            fprintf(MR_mdb_out, ":\n");
-            break;
-
-        case MR_EVAL_METHOD_MEMO_STRICT:
-        case MR_EVAL_METHOD_MEMO_FAST_LOOSE:
-        case MR_EVAL_METHOD_MEMO_SPECIFIED:
-            fprintf(MR_mdb_out, "memo table for ");
-            MR_print_proc_id(MR_mdb_out, proc);
-            fprintf(MR_mdb_out, ":\n");
-            break;
-
-        case MR_EVAL_METHOD_MINIMAL_STACK_COPY:
-        case MR_EVAL_METHOD_MINIMAL_OWN_STACKS:
-            fprintf(MR_mdb_out, "minimal model table for ");
-            MR_print_proc_id(MR_mdb_out, proc);
-            fprintf(MR_mdb_out, ":\n");
-            break;
-
-        case MR_EVAL_METHOD_NORMAL:
-        case MR_EVAL_METHOD_TABLE_IO:
-        case MR_EVAL_METHOD_TABLE_IO_DECL:
-        case MR_EVAL_METHOD_TABLE_IO_UNITIZE:
-        case MR_EVAL_METHOD_TABLE_IO_UNITIZE_DECL:
-            MR_fatal_error("MR_trace_cmd_table: bad eval method");
-    }
-
-    /*
-    ** This loop prints the entries in the table.
-    **
-    ** If we knew in advance that the user left (say) two input argument
-    ** positions unspecified, we could use a loop structure such as:
-    **
-    **  for value1 in <values in the trie at node start_node[0]>
-    **      cur_value[1] = value1
-    **      start_node[1] = follow value1 in start_node[0]
-    **      for value2 in <values in the trie at node start_node[1]>
-    **          cur_value[2] = value2
-    **          start_node[2] = follow value2 in start_node[1]
-    **          print <fixed args>, cur_value[1], cur_value[2]
-    **      end for
-    **  end for
-    **
-    ** However, we don't know in advance how many input arguments the user
-    ** left unspecified. We therefore simulate the above with a single
-    ** loop, which can function as any one of the above nested loops.
-    **
-    ** The value of cur_arg controls which one it is simulating at any
-    ** given time. Initially, cur_arg grows as we enter each of the above
-    ** loops one after another, at each stage recording the set of values
-    ** in the current trie node in the values array of the relevant
-    ** argument.
-    **
-    ** We number the input arguments from 0 to filtered_num_inputs-1.
-    ** When cur_arg becomes equal to filtered_num_inputs, this means that
-    ** we have values for all the tabled input arguments, so we print the
-    ** corresponding call table entry. We then initiate backtracking:
-    ** we decrement cur_arg to get the next value of the last argument.
-    ** We also do this whenever we run out of values in any trie.
-    **
-    ** We stop when we are about to backtrack out of the outermost loop.
-    */
-
-    cur_arg = word_count;
-    num_tips = 0;
-    for (;;) {
-        MR_bool no_more;
-        MR_bool start_backtrack;
-
-        switch (call_table_args[cur_arg].MR_cta_step) {
-            case MR_TABLE_STEP_INT:
-                no_more = MR_update_int_table_arg_slot(&table_cur,
-                    &call_table_args[cur_arg]);
-                break;
-
-            case MR_TABLE_STEP_FLOAT:
-                no_more = MR_update_float_table_arg_slot(&table_cur,
-                    &call_table_args[cur_arg]);
-                break;
-
-            case MR_TABLE_STEP_STRING:
-                no_more = MR_update_string_table_arg_slot(&table_cur,
-                    &call_table_args[cur_arg]);
-                break;
-
-            default:
-                MR_fatal_error("arg not int, float or string after check");
-        }
-
-        if (no_more) {
-            /*
-            ** There aren't any more values in the current trie
-            ** of input argument cur_arg.
-            */
-
-            start_backtrack = MR_TRUE;
-        } else {
-            /*
-            ** There is at least one more value in the current trie
-            ** of input argument cur_arg, so go on to the next trie
-            ** (if there is one).
-            */
-
-            cur_arg++;
-
-            if (cur_arg >= filtered_num_inputs) {
-                MR_trace_cmd_table_print_tip(proc, filtered_num_inputs,
-                    call_table_args, table_cur);
-                num_tips++;
-                start_backtrack = MR_TRUE;
-            } else {
-                start_backtrack = MR_FALSE;
-            }
-        }
-
-        if (start_backtrack) {
-            cur_arg--;
-            table_cur = call_table_args[cur_arg].MR_cta_start_node;
-
-            if (cur_arg < word_count) {
-                break;
-            }
-        }
-    }
-
-    fprintf(MR_mdb_out, "end of table (%d %s)\n",
-        num_tips, (num_tips == 1 ? "entry" : "entries"));
-    MR_GC_free(call_table_args);
-    return KEEP_INTERACTING;
-}
-
-static MR_bool
-MR_trace_fill_in_int_table_arg_slot(MR_TrieNode *table_cur_ptr,
-    int arg_num, MR_ConstString given_arg,
-    MR_Call_Table_Arg *call_table_arg_ptr)
-{
-    MR_Integer  n;
-    MR_TrieNode table_next;
-
-    if (! MR_trace_is_integer(given_arg, &n)) {
-        fprintf(MR_mdb_out, "argument %d is not an integer.\n", arg_num);
-        return MR_FALSE;
-    }
-
-    table_next = MR_int_hash_lookup(*table_cur_ptr, n);
-    if (table_next == NULL) {
-        fprintf(MR_mdb_out,
-            "call table does not contain %" MR_INTEGER_LENGTH_MODIFIER "d"
-            " in argument position %d.\n", n, arg_num);
-        return MR_FALSE;
-    }
-
-    call_table_arg_ptr->MR_cta_start_node = *table_cur_ptr;
-    call_table_arg_ptr->MR_cta_valid = MR_TRUE;
-    call_table_arg_ptr->MR_cta_int_values = NULL;
-    call_table_arg_ptr->MR_cta_int_value_next = -1;
-    call_table_arg_ptr->MR_cta_int_cur_index = -1;
-    call_table_arg_ptr->MR_cta_int_cur_value = n;
-    *table_cur_ptr = table_next;
-
-    return MR_TRUE;
-}
-
-static MR_bool
-MR_trace_fill_in_float_table_arg_slot(MR_TrieNode *table_cur_ptr,
-    int arg_num, MR_ConstString given_arg,
-    MR_Call_Table_Arg *call_table_arg_ptr)
-{
-    MR_Float    f;
-    MR_TrieNode table_next;
-
-    if (! MR_trace_is_float(given_arg, &f)) {
-        fprintf(MR_mdb_out, "argument %d is not a float.\n", arg_num);
-        return MR_FALSE;
-    }
-
-    table_next = MR_float_hash_lookup(*table_cur_ptr, f);
-    if (table_next == NULL) {
-        fprintf(MR_mdb_out,
-            "call table does not contain %f in argument position %d.\n",
-            f, arg_num);
-        return MR_FALSE;
-    }
-
-    call_table_arg_ptr->MR_cta_start_node = *table_cur_ptr;
-    call_table_arg_ptr->MR_cta_valid = MR_TRUE;
-    call_table_arg_ptr->MR_cta_float_values = NULL;
-    call_table_arg_ptr->MR_cta_float_value_next = -1;
-    call_table_arg_ptr->MR_cta_float_cur_index = -1;
-    call_table_arg_ptr->MR_cta_float_cur_value = f;
-    *table_cur_ptr = table_next;
-
-    return MR_TRUE;
-}
-
-static MR_bool
-MR_trace_fill_in_string_table_arg_slot(MR_TrieNode *table_cur_ptr,
-    int arg_num, MR_ConstString given_arg,
-    MR_Call_Table_Arg *call_table_arg_ptr)
-{
-    MR_ConstString  s;
-    MR_TrieNode table_next;
-
-    s = given_arg;
-
-    table_next = MR_string_hash_lookup(*table_cur_ptr, s);
-    if (table_next == NULL) {
-        fprintf(MR_mdb_out,
-            "call table does not contain %s in argument position %d.\n",
-            s, arg_num);
-        return MR_FALSE;
-    }
-
-    call_table_arg_ptr->MR_cta_start_node = *table_cur_ptr;
-    call_table_arg_ptr->MR_cta_valid = MR_TRUE;
-    call_table_arg_ptr->MR_cta_string_values = NULL;
-    call_table_arg_ptr->MR_cta_string_value_next = -1;
-    call_table_arg_ptr->MR_cta_string_cur_index = -1;
-    call_table_arg_ptr->MR_cta_string_cur_value = s;
-    *table_cur_ptr = table_next;
-
-    return MR_TRUE;
-}
-
-static MR_bool
-MR_update_int_table_arg_slot(MR_TrieNode *table_cur_ptr,
-    MR_Call_Table_Arg *call_table_arg_ptr)
-{
-    MR_TrieNode table_next;
-    MR_Integer  *values;
-    int         value_next;
-
-    if (call_table_arg_ptr->MR_cta_valid
-        && call_table_arg_ptr->MR_cta_int_values != NULL)
-    {
-        call_table_arg_ptr->MR_cta_int_cur_index++;
-    } else {
-        if (! MR_get_int_hash_table_contents(*table_cur_ptr,
-            &values, &value_next))
-        {
-            /* there are no values in this trie node */
-            call_table_arg_ptr->MR_cta_valid = MR_FALSE;
-            return MR_TRUE;
-        }
-
-        call_table_arg_ptr->MR_cta_start_node = *table_cur_ptr;
-        call_table_arg_ptr->MR_cta_valid = MR_TRUE;
-        call_table_arg_ptr->MR_cta_int_values = values;
-        call_table_arg_ptr->MR_cta_int_value_next = value_next;
-        call_table_arg_ptr->MR_cta_int_cur_index = 0;
-    }
-
-    if (call_table_arg_ptr->MR_cta_int_cur_index
-        >= call_table_arg_ptr->MR_cta_int_value_next)
-    {
-        /* we have already returned all the values in this trie node */
-        call_table_arg_ptr->MR_cta_valid = MR_FALSE;
-        return MR_TRUE;
-    }
-
-    call_table_arg_ptr->MR_cta_int_cur_value =
-        call_table_arg_ptr->MR_cta_int_values[
-            call_table_arg_ptr->MR_cta_int_cur_index];
-
-    table_next = MR_int_hash_lookup(call_table_arg_ptr->MR_cta_start_node,
-        call_table_arg_ptr->MR_cta_int_cur_value);
-
-    if (table_next == NULL) {
-        MR_fatal_error("MR_update_int_table_arg_slot: bad lookup");
-    }
-
-    *table_cur_ptr = table_next;
-    return MR_FALSE;
-}
-
-static MR_bool
-MR_update_float_table_arg_slot(MR_TrieNode *table_cur_ptr,
-    MR_Call_Table_Arg *call_table_arg_ptr)
-{
-    MR_TrieNode table_next;
-    MR_Float    *values;
-    int     value_next;
-
-    if (call_table_arg_ptr->MR_cta_valid
-        && call_table_arg_ptr->MR_cta_float_values != NULL)
-    {
-        call_table_arg_ptr->MR_cta_float_cur_index++;
-    } else {
-        if (! MR_get_float_hash_table_contents(*table_cur_ptr,
-            &values, &value_next))
-        {
-            /* there are no values in this trie node */
-            call_table_arg_ptr->MR_cta_valid = MR_FALSE;
-            return MR_TRUE;
-        }
-
-        call_table_arg_ptr->MR_cta_start_node = *table_cur_ptr;
-        call_table_arg_ptr->MR_cta_valid = MR_TRUE;
-        call_table_arg_ptr->MR_cta_float_values = values;
-        call_table_arg_ptr->MR_cta_float_value_next = value_next;
-        call_table_arg_ptr->MR_cta_float_cur_index = 0;
-    }
-
-    if (call_table_arg_ptr->MR_cta_float_cur_index
-        >= call_table_arg_ptr->MR_cta_float_value_next)
-    {
-        /* we have already returned all the values in this trie node */
-        call_table_arg_ptr->MR_cta_valid = MR_FALSE;
-        return MR_TRUE;
-    }
-
-    call_table_arg_ptr->MR_cta_float_cur_value =
-        call_table_arg_ptr->MR_cta_float_values[
-            call_table_arg_ptr->MR_cta_float_cur_index];
-
-    table_next = MR_float_hash_lookup(call_table_arg_ptr->MR_cta_start_node,
-        call_table_arg_ptr->MR_cta_float_cur_value);
-
-    if (table_next == NULL) {
-        MR_fatal_error("MR_update_float_table_arg_slot: bad lookup");
-    }
-
-    *table_cur_ptr = table_next;
-    return MR_FALSE;
-}
-
-static MR_bool
-MR_update_string_table_arg_slot(MR_TrieNode *table_cur_ptr,
-    MR_Call_Table_Arg *call_table_arg_ptr)
-{
-    MR_TrieNode     table_next;
-    MR_ConstString  *values;
-    int             value_next;
-
-    if (call_table_arg_ptr->MR_cta_valid
-        && call_table_arg_ptr->MR_cta_string_values != NULL)
-    {
-        call_table_arg_ptr->MR_cta_string_cur_index++;
-    } else {
-        if (! MR_get_string_hash_table_contents(*table_cur_ptr,
-            &values, &value_next))
-        {
-            /* there are no values in this trie node */
-            call_table_arg_ptr->MR_cta_valid = MR_FALSE;
-            return MR_TRUE;
-        }
-
-        call_table_arg_ptr->MR_cta_start_node = *table_cur_ptr;
-        call_table_arg_ptr->MR_cta_valid = MR_TRUE;
-        call_table_arg_ptr->MR_cta_string_values = values;
-        call_table_arg_ptr->MR_cta_string_value_next = value_next;
-        call_table_arg_ptr->MR_cta_string_cur_index = 0;
-    }
-
-    if (call_table_arg_ptr->MR_cta_string_cur_index
-        >= call_table_arg_ptr->MR_cta_string_value_next)
-    {
-        /* we have already returned all the values in this trie node */
-        call_table_arg_ptr->MR_cta_valid = MR_FALSE;
-        return MR_TRUE;
-    }
-
-    call_table_arg_ptr->MR_cta_string_cur_value =
-        call_table_arg_ptr->MR_cta_string_values[
-            call_table_arg_ptr->MR_cta_string_cur_index];
-
-    table_next = MR_string_hash_lookup(
-        call_table_arg_ptr->MR_cta_start_node,
-        call_table_arg_ptr->MR_cta_string_cur_value);
-
-    if (table_next == NULL) {
-        MR_fatal_error("MR_update_string_table_arg_slot: bad lookup");
-    }
-
-    *table_cur_ptr = table_next;
-    return MR_FALSE;
-}
-
-static void
-MR_trace_cmd_table_print_tip(const MR_Proc_Layout *proc,
-    int num_filtered_inputs, MR_Call_Table_Arg *call_table_args,
-    MR_TrieNode table)
-{
-    int             i;
-    MR_EvalMethod   eval_method;
-
-    fprintf(MR_mdb_out, "<");
-    for (i = 0; i < num_filtered_inputs; i++) {
-        if (i > 0) {
-            fprintf(MR_mdb_out, ", ");
-        }
-
-        switch (call_table_args[i].MR_cta_step) {
-            case MR_TABLE_STEP_INT:
-                fprintf(MR_mdb_out, "%" MR_INTEGER_LENGTH_MODIFIER "d",
-                    call_table_args[i].MR_cta_int_cur_value);
-                break;
-
-            case MR_TABLE_STEP_FLOAT:
-                fprintf(MR_mdb_out, "%f",
-                    call_table_args[i].MR_cta_float_cur_value);
-                break;
-
-            case MR_TABLE_STEP_STRING:
-                fprintf(MR_mdb_out, "\"%s\"",
-                    call_table_args[i].MR_cta_string_cur_value);
-                break;
-
-            default:
-                MR_fatal_error("arg not int, float or string after check");
-        }
-    }
-
-    fprintf(MR_mdb_out, ">: ");
-
-    eval_method = MR_sle_eval_method(proc);
-    switch (eval_method) {
-        case MR_EVAL_METHOD_MINIMAL_STACK_COPY:
-            {
-                MR_Subgoal  *subgoal;
-                int         subgoal_num;
-
-                fprintf(MR_mdb_out, "trie node %p\n", table);
-                subgoal = table->MR_subgoal;
-                if (subgoal == NULL) {
-                    fprintf(MR_mdb_out, "uninitialized\n");
-                } else {
-                    MR_trace_print_subgoal(proc, subgoal);
-                }
-            }
-            break;
-
-        case MR_EVAL_METHOD_MINIMAL_OWN_STACKS:
-            {
-                MR_GeneratorPtr generator;
-
-                fprintf(MR_mdb_out, "trie node %p\n", table);
-                generator = table->MR_generator;
-                if (generator == NULL) {
-                    fprintf(MR_mdb_out, "uninitialized\n");
-                } else {
-                    MR_trace_print_generator(proc, generator);
-                }
-            }
-            break;
-
-        case MR_EVAL_METHOD_MEMO_STRICT:
-        case MR_EVAL_METHOD_MEMO_FAST_LOOSE:
-        case MR_EVAL_METHOD_MEMO_SPECIFIED:
-            {
-                MR_Determinism  detism;
-
-                detism = proc->MR_sle_detism;
-                if (MR_DETISM_DET_STACK(detism)) {
-                    MR_print_memo_tip(MR_mdb_out, proc, table);
-                } else {
-                    MR_MemoNonRecordPtr record;
-
-                    record = table->MR_memo_non_record;
-                    MR_print_memo_non_record(MR_mdb_out, proc, record);
-                }
-            }
-            break;
-
-        case MR_EVAL_METHOD_LOOP_CHECK:
-            MR_print_loopcheck_tip(MR_mdb_out, proc, table);
-            break;
-
-        case MR_EVAL_METHOD_NORMAL:
-        case MR_EVAL_METHOD_TABLE_IO:
-        case MR_EVAL_METHOD_TABLE_IO_DECL:
-        case MR_EVAL_METHOD_TABLE_IO_UNITIZE:
-        case MR_EVAL_METHOD_TABLE_IO_UNITIZE_DECL:
-            MR_fatal_error("MR_trace_cmd_table_print_tip: bad eval method");
-            break;
-    }
-}
-
-static void
-MR_trace_print_subgoal(const MR_Proc_Layout *proc, MR_Subgoal *subgoal)
-{
-#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
-    MR_print_subgoal(MR_mdb_out, proc, subgoal);
-#else
-    fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
-#endif
-}
-
-static void
-MR_trace_print_subgoal_debug(const MR_Proc_Layout *proc,
-    MR_SubgoalDebug *subgoal_debug)
-{
-#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
-    MR_print_subgoal_debug(MR_mdb_out, proc, subgoal_debug);
-#else
-    fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
-#endif
-}
-
-static void
-MR_trace_print_generator(const MR_Proc_Layout *proc, MR_Generator *generator)
-{
-#ifdef  MR_USE_MINIMAL_MODEL_OWN_STACKS
-    MR_print_generator(MR_mdb_out, proc, generator);
-#else
-    fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
-#endif
-}
-
-static void
-MR_trace_print_generator_debug(const MR_Proc_Layout *proc,
-    MR_GenDebug *generator_debug)
-{
-#ifdef  MR_USE_MINIMAL_MODEL_OWN_STACKS
-    MR_print_gen_debug(MR_mdb_out, proc, generator_debug);
-#else
-    fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
-#endif
-}
-
-static void
-MR_trace_print_consumer(const MR_Proc_Layout *proc, MR_Consumer *consumer)
-{
-#if defined(MR_USE_MINIMAL_MODEL_STACK_COPY) \
-        || defined(MR_USE_MINIMAL_MODEL_OWN_STACKS)
-    MR_print_consumer(MR_mdb_out, proc, consumer);
-#else
-    fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
-#endif
-}
-
-static void
-MR_trace_print_consumer_debug(const MR_Proc_Layout *proc,
-    MR_ConsumerDebug *consumer_debug)
-{
-#if defined(MR_USE_MINIMAL_MODEL_STACK_COPY)
-    MR_print_consumer_debug(MR_mdb_out, proc, consumer_debug);
-#elif defined(MR_USE_MINIMAL_MODEL_STACK_COPY)
-    MR_print_cons_debug(MR_mdb_out, proc, consumer_debug);
-#else
-    fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
-#endif
-}
-
-static MR_Next
-MR_trace_cmd_type_ctor(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    const char      *module_name;
-    const char      *name;
-    int             arity;
-    MR_bool         print_rep;
-    MR_bool         print_functors;
-    MR_TypeCtorInfo type_ctor_info;
-
-    MR_do_init_modules_type_tables();
-
-    print_rep = MR_FALSE;
-    print_functors = MR_FALSE;
-    if (! MR_trace_options_type_ctor(&print_rep, &print_functors,
-        &words, &word_count))
-    {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 4 &&
-        MR_trace_is_natural_number(words[3], &arity))
-    {
-        module_name = words[1];
-        name = words[2];
-        type_ctor_info = MR_lookup_type_ctor_info(module_name, name, arity);
-        if (type_ctor_info != NULL) {
-            MR_print_type_ctor_info(MR_mdb_out, type_ctor_info, print_rep,
-                print_functors);
-        } else {
-            fprintf(MR_mdb_out, "there is no such type constructor\n");
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_class_decl(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    const char              *module_name;
-    const char              *name;
-    int                     arity;
-    MR_bool                 print_methods;
-    MR_bool                 print_instances;
-    MR_TypeClassDeclInfo    *type_class_decl_info;
-
-    MR_do_init_modules_type_tables();
-
-    print_methods = MR_FALSE;
-    print_instances = MR_FALSE;
-    if (! MR_trace_options_class_decl(&print_methods, &print_instances,
-        &words, &word_count))
-    {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 4 &&
-        MR_trace_is_natural_number(words[3], &arity))
-    {
-        module_name = words[1];
-        name = words[2];
-        type_class_decl_info = MR_lookup_type_class_decl_info(module_name,
-            name, arity);
-        if (type_class_decl_info != NULL) {
-            MR_print_class_decl_info(MR_mdb_out, type_class_decl_info,
-                print_methods, print_instances);
-        } else {
-            fprintf(MR_mdb_out, "there is no such type class\n");
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_all_type_ctors(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_bool         print_rep;
-    MR_bool         print_functors;
-    MR_Dlist        *list;
-    MR_Dlist        *element_ptr;
-    MR_TypeCtorInfo type_ctor_info;
-    const char      *module_name;
-    int             count;
-
-    MR_do_init_modules_type_tables();
-
-    print_rep = MR_FALSE;
-    print_functors = MR_FALSE;
-    if (! MR_trace_options_type_ctor(&print_rep, &print_functors,
-        &words, &word_count))
-    {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 1 || word_count == 2) {
-        if (word_count == 2) {
-            module_name = words[1];
-        } else {
-            module_name = NULL;
-        }
-
-        list = MR_all_type_ctor_infos(NULL);
-        count = 0;
-        MR_for_dlist(element_ptr, list) {
-            type_ctor_info = (MR_TypeCtorInfo) MR_dlist_data(element_ptr);
-            if (module_name != NULL && strcmp(module_name,
-                type_ctor_info->MR_type_ctor_module_name) != 0)
-            {
-                continue;
-            }
-
-            if (count > 0) {
-                fprintf(MR_mdb_out, "\n");
-            }
-            MR_print_type_ctor_info(MR_mdb_out, type_ctor_info, print_rep,
-                print_functors);
-            count++;
-        }
-
-        fprintf(MR_mdb_out, "\nnumber of type constructors ");
-        if (module_name == NULL) {
-            fprintf(MR_mdb_out, "in the program: %d\n", count);
-        } else {
-            fprintf(MR_mdb_out, "in module %s: %d\n", module_name, count);
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_all_class_decls(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_bool                 print_methods;
-    MR_bool                 print_instances;
-    MR_Dlist                *list;
-    MR_Dlist                *element_ptr;
-    MR_TypeClassDeclInfo    *type_class_decl_info;
-    const char              *module_name;
-    int                     count;
-
-    MR_do_init_modules_type_tables();
-
-    print_methods = MR_FALSE;
-    print_instances = MR_FALSE;
-    if (! MR_trace_options_class_decl(&print_methods, &print_instances,
-        &words, &word_count))
-    {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 1 || word_count == 2) {
-        if (word_count == 2) {
-            module_name = words[1];
-        } else {
-            module_name = NULL;
-        }
-        list = MR_all_type_class_decl_infos(NULL);
-        count = 0;
-        MR_for_dlist(element_ptr, list) {
-            type_class_decl_info = (MR_TypeClassDeclInfo *)
-                MR_dlist_data(element_ptr);
-            if (module_name != NULL && strcmp(module_name,
-                type_class_decl_info->MR_tcd_info_decl->
-                MR_tc_decl_id->MR_tc_id_module_name) != 0)
-            {
-                continue;
-            }
-
-            if (count > 0) {
-                fprintf(MR_mdb_out, "\n");
-            }
-            MR_print_class_decl_info(MR_mdb_out, type_class_decl_info,
-                print_methods, print_instances);
-            count++;
-        }
-
-        fprintf(MR_mdb_out, "\nnumber of type classes ");
-        if (module_name == NULL) {
-            fprintf(MR_mdb_out, "in the program: %d\n", count);
-        } else {
-            fprintf(MR_mdb_out, "in module %s: %d\n", module_name, count);
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_all_procedures(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    const char      *filename;
-    MR_bool         separate;
-    MR_bool         uci;
-    FILE            *fp;
-    char            *module;
-
-    MR_register_all_modules_and_procs(MR_mdb_out, MR_TRUE);
-
-    separate = MR_FALSE;
-    uci = MR_FALSE;
-    module = NULL;
-    if (! MR_trace_options_all_procedures(&separate, &uci, &module,
-        &words, &word_count))
-    {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 2) {
-        filename = words[1];
-        fp = fopen(filename, "w");
-        if (fp == NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: error opening `%s': %s.\n",
-                filename, strerror(errno));
-            return KEEP_INTERACTING;
-        }
-
-        MR_dump_module_tables(fp, separate, uci, module);
-        if (fclose(fp) != 0) {
-            fprintf(MR_mdb_err, "mdb: error writing to `%s': %s.\n",
-                filename, strerror(errno));
-            return KEEP_INTERACTING;
-        } else {
-            fprintf(MR_mdb_out, "mdb: wrote table to `%s'.\n", filename);
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_ambiguity(char **words, int word_count,
-    MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    const char      *filename;
-    FILE            *fp;
-    int             i;
-
-    filename = NULL;
-    if (! MR_trace_options_ambiguity(&filename, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else {
-        MR_register_all_modules_and_procs(MR_mdb_out, MR_TRUE);
-
-        if (filename == NULL) {
-            fp = MR_mdb_out;
-        } else {
-            fp = fopen(filename, "w");
-            if (fp == NULL) {
-                fflush(MR_mdb_out);
-                fprintf(MR_mdb_err, "mdb: error opening `%s': %s.\n",
-                    filename, strerror(errno));
-                return KEEP_INTERACTING;
-            }
-        }
-
-        /*
-        ** The words on the command line after the command name and the already
-        ** processed options are a list of modules names. If this list is not
-        ** empty, then we consider only the modules named here when looking for
-        ** ambiguities.
-        */
-
-        MR_print_ambiguities(fp, &words[1], word_count - 1);
-
-        if (filename != NULL) {
-            fprintf(MR_mdb_out, "mdb: wrote report to `%s'.\n", filename);
-            fclose(fp);
-        }
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static void
-MR_print_type_ctor_info(FILE *fp, MR_TypeCtorInfo type_ctor_info,
-    MR_bool print_rep, MR_bool print_functors)
-{
-    MR_TypeCtorRep              rep;
-    MR_EnumFunctorDesc          *enum_functor;
-    MR_DuFunctorDesc            *du_functor;
-    MR_MaybeResAddrFunctorDesc  *maybe_res_functor;
-    MR_NotagFunctorDesc         *notag_functor;
-    int                         num_functors;
-    int                         i;
-
-    fprintf(fp, "type constructor %s.%s/%d",
-        type_ctor_info->MR_type_ctor_module_name,
-        type_ctor_info->MR_type_ctor_name,
-        (int) type_ctor_info->MR_type_ctor_arity);
-
-    rep = MR_type_ctor_rep(type_ctor_info);
-    if (print_rep) {
-        fprintf(fp, ": %s\n", MR_ctor_rep_name[MR_GET_ENUM_VALUE(rep)]);
-    } else {
-        fprintf(fp, "\n");
-    }
-
-    if (print_functors) {
-        num_functors = type_ctor_info->MR_type_ctor_num_functors;
-        switch (rep) {
-            case MR_TYPECTOR_REP_ENUM:
-            case MR_TYPECTOR_REP_ENUM_USEREQ:
-                for (i = 0; i < num_functors; i++) {
-                    enum_functor = type_ctor_info->MR_type_ctor_functors.
-                        MR_functors_enum[i];
-                    if (i > 0) {
-                        fprintf(fp, ", ");
-                    }
-                    fprintf(fp, "%s/0", enum_functor->MR_enum_functor_name);
-                }
-                fprintf(fp, "\n");
-                break;
-
-            case MR_TYPECTOR_REP_DU:
-            case MR_TYPECTOR_REP_DU_USEREQ:
-                for (i = 0; i < num_functors; i++) {
-                    du_functor = type_ctor_info->MR_type_ctor_functors.
-                        MR_functors_du[i];
-                    if (i > 0) {
-                        fprintf(fp, ", ");
-                    }
-                    fprintf(fp, "%s/%d", du_functor->MR_du_functor_name,
-                        du_functor-> MR_du_functor_orig_arity);
-                }
-                fprintf(fp, "\n");
-                break;
-
-            case MR_TYPECTOR_REP_RESERVED_ADDR:
-            case MR_TYPECTOR_REP_RESERVED_ADDR_USEREQ:
-                for (i = 0; i < num_functors; i++) {
-                    maybe_res_functor = &type_ctor_info->MR_type_ctor_functors.
-                        MR_functors_res[i];
-                    if (i > 0) {
-                        fprintf(fp, ", ");
-                    }
-                    fprintf(fp, "%s/%d", maybe_res_functor->MR_maybe_res_name,
-                        (int) maybe_res_functor-> MR_maybe_res_arity);
-                }
-                fprintf(fp, "\n");
-                break;
-
-            case MR_TYPECTOR_REP_NOTAG:
-            case MR_TYPECTOR_REP_NOTAG_USEREQ:
-            case MR_TYPECTOR_REP_NOTAG_GROUND:
-            case MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ:
-                notag_functor = type_ctor_info->MR_type_ctor_functors.
-                    MR_functors_notag;
-                fprintf(fp, "%s/1\n", notag_functor->MR_notag_functor_name);
-                break;
-
-            default:
-                break;
-        }
-    }
-}
-
-static void
-MR_print_class_decl_info(FILE *fp, MR_TypeClassDeclInfo *type_class_decl_info,
-    MR_bool print_methods, MR_bool print_instances)
-{
-    MR_TypeClassDecl            type_class_decl;
-    const MR_TypeClassId        *type_class_id;
-    const MR_TypeClassMethod    *method;
-    MR_Instance                 instance;
-    MR_Dlist                    *list;
-    MR_Dlist                    *element_ptr;
-    int                         num_methods;
-    int                         i;
-
-    type_class_decl = type_class_decl_info->MR_tcd_info_decl;
-    type_class_id = type_class_decl->MR_tc_decl_id;
-    fprintf(fp, "type class %s.%s/%d\n",
-        type_class_id->MR_tc_id_module_name,
-        type_class_id->MR_tc_id_name,
-        type_class_id->MR_tc_id_arity);
-
-    if (print_methods) {
-        num_methods = type_class_id->MR_tc_id_num_methods;
-        fprintf(fp, "methods: ");
-
-        for (i = 0; i < num_methods; i++) {
-            if (i > 0) {
-                fprintf(fp, ", ");
-            }
-
-            method = &type_class_id->MR_tc_id_methods[i];
-            if (method->MR_tc_method_pred_func == MR_FUNCTION) {
-                fprintf(fp, "func ");
-            } else {
-                fprintf(fp, "pred ");
-            }
-
-            fprintf(fp, "%s/%d", method->MR_tc_method_name,
-                method->MR_tc_method_arity);
-        }
-
-        fprintf(fp, "\n");
-    }
-
-    if (print_instances) {
-        list = type_class_decl_info->MR_tcd_info_instances;
-        MR_for_dlist (element_ptr, list) {
-            instance = (MR_Instance) MR_dlist_data(element_ptr);
-
-            if (instance->MR_tc_inst_type_class != type_class_decl) {
-                MR_fatal_error("instance/type class mismatch");
-            }
-
-            fprintf(fp, "instance ");
-
-            for (i = 0; i < type_class_id->MR_tc_id_arity; i++) {
-                if (i > 0) {
-                    fprintf(fp, ", ");
-                }
-
-                MR_print_pseudo_type_info(fp,
-                    instance->MR_tc_inst_type_args[i]);
-            }
-
-            fprintf(fp, "\n");
-        }
-    }
-}
-
-static void
-MR_print_pseudo_type_info(FILE *fp, MR_PseudoTypeInfo pseudo)
-{
-    MR_TypeCtorInfo     type_ctor_info;
-    MR_PseudoTypeInfo   *pseudo_args;
-    MR_Integer          tvar_num;
-    int                 arity;
-    int                 i;
-
-    if (MR_PSEUDO_TYPEINFO_IS_VARIABLE(pseudo)) {
-        tvar_num = (MR_Integer) pseudo;
-        fprintf(fp, "T%d", (int) tvar_num);
-    } else {
-        type_ctor_info = MR_PSEUDO_TYPEINFO_GET_TYPE_CTOR_INFO(pseudo);
-        fprintf(fp, "%s.%s",
-            type_ctor_info->MR_type_ctor_module_name,
-            type_ctor_info->MR_type_ctor_name);
-        if (MR_type_ctor_has_variable_arity(type_ctor_info)) {
-            arity = MR_PSEUDO_TYPEINFO_GET_VAR_ARITY_ARITY(pseudo);
-            pseudo_args = (MR_PseudoTypeInfo *)
-                &pseudo->MR_pti_var_arity_arity;
-        } else {
-            arity = type_ctor_info->MR_type_ctor_arity;
-            pseudo_args = (MR_PseudoTypeInfo *) &pseudo->MR_pti_type_ctor_info;
-        }
-
-        if (type_ctor_info->MR_type_ctor_arity > 0) {
-            fprintf(fp, "(");
-            for (i = 1; i <= arity; i++) {
-                if (i > 1) {
-                    fprintf(fp, ", ");
-                }
-
-                MR_print_pseudo_type_info(fp, pseudo_args[i]);
-            }
-            fprintf(fp, ")");
-        }
-    }
-}
-
-static MR_Next
-MR_trace_cmd_source(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_bool ignore_errors;
-
-    ignore_errors = MR_FALSE;
-    if (! MR_trace_options_ignore(&ignore_errors, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 2) {
-        /*
-        ** If the source fails, the error message
-        ** will have already been printed by MR_trace_source
-        ** (unless ignore_errors suppresses the message).
-        */
-        (void) MR_trace_source(words[1], ignore_errors);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_save(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 2) {
-        FILE    *fp;
-        MR_bool found_error;
-        MR_Word path_list;
-
-        fp = fopen(words[1], "w");
-        if (fp == NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: error opening `%s': %s.\n",
-                words[1], strerror(errno));
-            return KEEP_INTERACTING;
-        }
-
-        MR_trace_print_all_aliases(fp, MR_TRUE);
-        switch (MR_default_print_level) {
-            case MR_PRINT_LEVEL_NONE:
-                fprintf(fp, "printlevel none\n");
-                break;
-
-            case MR_PRINT_LEVEL_SOME:
-                fprintf(fp, "printlevel some\n");
-                break;
-
-            case MR_PRINT_LEVEL_ALL:
-                fprintf(fp, "printlevel all\n");
-                break;
-        }
-
-        if (MR_echo_commands) {
-            fprintf(fp, "echo on\n");
-        } else {
-            fprintf(fp, "echo off\n");
-        }
-
-        if (MR_scroll_control) {
-            fprintf(fp, "scroll on\n");
-        } else {
-            fprintf(fp, "scroll off\n");
-        }
-
-        fprintf(fp, "scroll %d\n", MR_scroll_limit);
-        fprintf(fp, "stack_default_limit %d\n", MR_stack_default_line_limit);
-
-        switch (MR_context_position) {
-            case MR_CONTEXT_NOWHERE:
-                fprintf(fp, "context nowhere\n");
-                break;
-
-            case MR_CONTEXT_AFTER:
-                fprintf(fp, "context after\n");
-                break;
-
-            case MR_CONTEXT_BEFORE:
-                fprintf(fp, "context before\n");
-                break;
-
-            case MR_CONTEXT_PREVLINE:
-                fprintf(fp, "context prevline\n");
-                break;
-
-            case MR_CONTEXT_NEXTLINE:
-                fprintf(fp, "context nextline\n");
-                break;
-        }
-
-        if (MR_print_goal_paths) {
-            fprintf(fp, "goal_paths on\n");
-        } else {
-            fprintf(fp, "goal_paths off\n");
-        }
-
-        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;
-
-            case MR_SPY_LINENO:
-            case MR_SPY_SPECIFIC:
-                MR_fatal_error("save cmd: invalid default scope");
-        }
-
-        MR_trace_print_all_browser_params(fp, MR_TRUE);
-        MR_decl_print_all_trusted(fp, MR_TRUE);
-
-        if (MR_dice_fail_trace_counts_file != NULL) {
-            fprintf(fp, "set fail_trace_counts %s\n",
-                MR_dice_fail_trace_counts_file);
-        }
-        if (MR_dice_pass_trace_counts_file != NULL) {
-            fprintf(fp, "set pass_trace_counts %s\n",
-                MR_dice_pass_trace_counts_file);
-        }
-
-        fprintf(fp, "set list_context_lines %d\n", MR_num_context_lines);
-        MR_TRACE_CALL_MERCURY(
-            path_list = ML_LISTING_get_list_path(MR_listing_path);
-            if (! MR_list_is_empty(path_list)) {
-                fprintf(fp, "set list_path");
-                while (! MR_list_is_empty(path_list)) {
-                    fprintf(fp, " %s", (const char *) MR_list_head(path_list));
-                    path_list = MR_list_tail(path_list);
-                }
-                fprintf(fp, "\n");
-            }
-        );
-
-        if (found_error) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: could not save debugger state to %s.\n",
-                words[1]);
-            (void) fclose(fp);
-        } else if (fclose(fp) != 0) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: error closing `%s': %s.\n",
-                words[1], strerror(errno));
-        } else {
-            fprintf(MR_mdb_out, "Debugger state saved to %s.\n", words[1]);
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_quit(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_bool confirmed;
-
-    confirmed = MR_FALSE;
-    if (! MR_trace_options_confirmed(&confirmed, &words, &word_count)) {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 1) {
-        if (! confirmed) {
-            char    *line2;
-
-            line2 = MR_trace_getline("mdb: are you sure you want to quit? ",
-                MR_mdb_in, MR_mdb_out);
-            if (line2 == NULL) {
-                /* This means the user input EOF. */
-                confirmed = MR_TRUE;
-            } else {
-                int i = 0;
-                while (line2[i] != '\0' && MR_isspace(line2[i])) {
-                    i++;
-                }
-
-                if (line2[i] == 'y' || line2[i] == 'Y') {
-                    confirmed = MR_TRUE;
-                }
-
-                MR_free(line2);
-            }
-        }
-
-        if (confirmed) {
-            MR_trace_maybe_close_source_window(MR_FALSE);
-            exit(EXIT_SUCCESS);
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_dd(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_Decl_Search_Mode search_mode;
-    MR_bool             search_mode_was_set = MR_FALSE;
-    MR_bool             new_session = MR_TRUE;
-    MR_bool             search_mode_requires_trace_counts = MR_FALSE;
-    char                *pass_trace_counts_file;
-    char                *fail_trace_counts_file;
-    MR_String           problem;
-    MR_bool             testing = MR_FALSE;
-    MR_bool             debug = MR_FALSE;
-    const char          *filename;
-    MR_Decl_Mode        decl_mode;
-
-    MR_trace_decl_assume_all_io_is_tabled = MR_FALSE;
-    MR_edt_default_depth_limit = MR_TRACE_DECL_INITIAL_DEPTH;
-    search_mode = MR_trace_get_default_search_mode();
-    pass_trace_counts_file = MR_dice_pass_trace_counts_file;
-    fail_trace_counts_file = MR_dice_fail_trace_counts_file;
-    MR_trace_decl_debug_debugger_mode = MR_FALSE;
-
-    if (! MR_trace_options_dd(&MR_trace_decl_assume_all_io_is_tabled,
-        &MR_edt_default_depth_limit, &MR_edt_desired_nodes_in_subtree,
-        &search_mode, &search_mode_was_set,
-        &search_mode_requires_trace_counts,
-        &pass_trace_counts_file, &fail_trace_counts_file, &new_session,
-        &testing, &MR_trace_decl_debug_debugger_mode, &words, &word_count))
-    {
-        ; /* the usage message has already been printed */
-    } else if (word_count <= 2) {
-        if (word_count == 2 && MR_trace_decl_debug_debugger_mode) {
-            decl_mode = MR_DECL_DUMP;
-            filename = (const char *) words[1];
-        } else {
-            decl_mode = MR_DECL_NODUMP;
-            filename = (const char *) NULL;
-        }
-        if (MR_trace_have_unhid_events) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err,
-                "mdb: dd doesn't work after `unhide_events on'.\n");
-            return KEEP_INTERACTING;
-        }
-        if (search_mode_requires_trace_counts && (
-            pass_trace_counts_file == NULL || fail_trace_counts_file == NULL))
-        {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err,
-                "mdb: you need to supply passing and failing trace count "
-                "files\nbefore using the specified search mode.\n");
-            return KEEP_INTERACTING;
-        }
-        if (pass_trace_counts_file != NULL && fail_trace_counts_file != NULL) {
-            if (! MR_trace_decl_init_suspicion_table(pass_trace_counts_file,
-                fail_trace_counts_file, &problem))
-            {
-                fflush(MR_mdb_out);
-                fprintf(MR_mdb_err, "mdb: %s\n", problem);
-                return KEEP_INTERACTING;
-            }
-        }
-
-        MR_trace_decl_set_testing_flag(testing);
-
-        if (search_mode_was_set || new_session) {
-            MR_trace_decl_set_fallback_search_mode(search_mode);
-        }
-
-        if (MR_trace_start_decl_debug(decl_mode, filename, new_session, cmd,
-            event_info, jumpaddr))
-        {
-            return STOP_INTERACTING;
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_trust(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    MR_Proc_Spec        spec;
-    MR_Matches_Info     matches;
-
-    if (word_count == 2) {
-        spec.MR_proc_module = NULL;
-        spec.MR_proc_name   = NULL;
-        spec.MR_proc_arity  = -1;
-        spec.MR_proc_mode   = -1;
-        spec.MR_proc_prefix = (MR_Proc_Prefix) -1;
-
-        MR_register_all_modules_and_procs(MR_mdb_out, MR_TRUE);
-
-        /* First see if the argument is a module name */
-        spec.MR_proc_module = words[1];
-        matches = MR_search_for_matching_procedures(&spec);
-        if (matches.match_proc_next > 0) {
-            MR_decl_add_trusted_module(words[1]);
-            fprintf(MR_mdb_out, "Trusting module %s\n", words[1]);
-        } else if (MR_parse_proc_spec(words[1], &spec)) {
-            /* Check to see if the argument is a pred/func */
-            matches = MR_search_for_matching_procedures(&spec);
-            MR_filter_user_preds(&matches);
-            if (matches.match_proc_next == 0) {
-                fprintf(MR_mdb_err,
-                    "mdb: there is no such module, predicate or function.\n");
-            } else if (matches.match_proc_next == 1) {
-                MR_decl_add_trusted_pred_or_func(matches.match_procs[0]);
-                fprintf(MR_mdb_out, "Trusting ");
-                MR_print_pred_id_and_nl(MR_mdb_out, matches.match_procs[0]);
-            } else {
-                int     i;
-                char    buf[80];
-                char    *line2;
-
-                fprintf(MR_mdb_out, "Ambiguous predicate or function"
-                    " specification. The matches are:\n");
-                for (i = 0; i < matches.match_proc_next; i++) {
-                    fprintf(MR_mdb_out, "%d: ", i);
-                    MR_print_pred_id_and_nl(MR_mdb_out,
-                        matches.match_procs[i]);
-                }
-                sprintf(buf, "\nWhich predicate or function "
-                    "do you want to trust (0-%d or *)? ",
-                    matches.match_proc_next - 1);
-                line2 = MR_trace_getline(buf, MR_mdb_in, MR_mdb_out);
-                if (line2 == NULL) {
-                    /* This means the user input EOF. */
-                    fprintf(MR_mdb_out, "none of them\n");
-                } else if (MR_streq(line2, "*")) {
-                    for (i = 0; i < matches.match_proc_next; i++) {
-                        MR_decl_add_trusted_pred_or_func(
-                            matches.match_procs[i]);
-
-                        fprintf(MR_mdb_out, "Trusting ");
-                        MR_print_pred_id_and_nl(MR_mdb_out,
-                            matches.match_procs[i]);
-                    }
-                    MR_free(line2);
-                } else if(MR_trace_is_natural_number(line2, &i)) {
-                    if (0 <= i && i < matches.match_proc_next) {
-                        MR_decl_add_trusted_pred_or_func(
-                            matches.match_procs[i]);
-
-                        fprintf(MR_mdb_out, "Trusting ");
-                        MR_print_pred_id_and_nl(MR_mdb_out,
-                            matches.match_procs[i]);
-                    } else {
-                        fprintf(MR_mdb_out, "no such match\n");
-                    }
-                    MR_free(line2);
-                } else {
-                    fprintf(MR_mdb_out, "none of them\n");
-                    MR_free(line2);
-                }
-            }
-        }
-    } else if (word_count == 3 &&
-        ((MR_streq(words[1], "std") && MR_streq(words[2], "lib"))
-        || (MR_streq(words[1], "standard") && MR_streq(words[2], "library"))))
-    {
-        MR_decl_trust_standard_library();
-        fprintf(MR_mdb_out, "Trusting the Mercury standard library\n");
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_untrust(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    int i;
-
-    if (word_count == 2 && MR_trace_is_natural_number(words[1], &i)) {
-        if (!MR_decl_remove_trusted(i)) {
-            fprintf(MR_mdb_err, "mdb: no such trusted object\n");
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_trusted(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    if (word_count == 1) {
-        MR_decl_print_all_trusted(MR_mdb_out, MR_FALSE);
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-    return KEEP_INTERACTING;
-}
-
-static MR_Next
-MR_trace_cmd_dice(char **words, int word_count, MR_Trace_Cmd_Info *cmd,
-    MR_Event_Info *event_info, MR_Code **jumpaddr)
-{
-    char    *pass_trace_counts_file;
-    char    *fail_trace_counts_file;
-    char    *sort_str;
-    char    *out_file;
-    char    *module;
-    int     number_of_lines;
-
-    sort_str = NULL;
-    out_file = NULL;
-    module = NULL;
-    number_of_lines = MR_DEFAULT_DICE_LINES;
-
-    pass_trace_counts_file = MR_dice_pass_trace_counts_file;
-    fail_trace_counts_file = MR_dice_fail_trace_counts_file;
-
-    if (! MR_trace_options_dice(&pass_trace_counts_file,
-        &fail_trace_counts_file, &sort_str, &number_of_lines, &out_file,
-        &module, &words, &word_count))
-    {
-        ; /* the usage message has already been printed */
-    } else if (word_count == 1) {
-        if (pass_trace_counts_file == NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: No passing trace counts file specified."
-                "\nmdb: Specify one with the -p option or using the `set' "
-                "command.\n");
-        } else if (fail_trace_counts_file == NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: No failing trace counts file specified."
-                "\nmdb: Specify one with the -f option or using the `set' "
-                "command.\n");
-        } else {
-            if (sort_str == NULL) {
-                sort_str = MR_copy_string("");
-            }
-
-            if (module == NULL) {
-                module = MR_copy_string("");
-            }
-
-            MR_trace_print_dice(pass_trace_counts_file, fail_trace_counts_file,
-                sort_str, number_of_lines, out_file, module);
-        }
-    } else {
-        MR_trace_usage_cur_cmd();
-    }
-
-    if (out_file != NULL) {
-        free(out_file);
-    }
-
-    if (sort_str != NULL) {
-        free(sort_str);
-    }
-
-    if (module != NULL) {
-        free(module);
-    }
-
-    return KEEP_INTERACTING;
-}
-
-static  void
-MR_trace_print_dice(char *pass_trace_counts_file,
-    char *fail_trace_count_file, char *sort_str, int number_of_lines,
-    char *out_file, char *module)
-{
-    MR_String   dice;
-    MR_String   problem;
-    MR_String   aligned_pass_trace_counts_file;
-    MR_String   aligned_fail_trace_count_file;
-    MR_String   aligned_sort_str;
-    MR_String   aligned_module;
-    FILE        *fp;
-
-    MR_TRACE_USE_HP(
-        MR_make_aligned_string(aligned_pass_trace_counts_file,
-            (MR_String) pass_trace_counts_file);
-        MR_make_aligned_string(aligned_fail_trace_count_file,
-            (MR_String) fail_trace_count_file);
-        MR_make_aligned_string(aligned_sort_str, (MR_String) sort_str);
-        if (module == NULL) {
-            MR_make_aligned_string(aligned_module, (MR_String) "");
-        } else {
-            MR_make_aligned_string(aligned_module, (MR_String) module);
-        }
-    );
-
-    MR_TRACE_CALL_MERCURY(
-        MR_MDB_read_dice_to_string(aligned_pass_trace_counts_file,
-            aligned_fail_trace_count_file, aligned_sort_str,
-            number_of_lines, aligned_module, &dice, &problem);
-    );
-
-    /* The string in dice is a sequence of complete lines */
-    if (MR_streq(problem, "")) {
-        if (out_file == NULL) {
-            fprintf(MR_mdb_out, "%s", dice);
-        } else {
-            fp = fopen(out_file, "w");
-            if (fp != NULL) {
-                fprintf(fp, "%s", dice);
-                if (fclose(fp) != 0) {
-                    fflush(MR_mdb_out);
-                    fprintf(MR_mdb_err, "mdb: Error closing file `%s': %s\n",
-                        out_file, strerror(errno));
-                }
-            } else {
-                fflush(MR_mdb_out);
-                fprintf(MR_mdb_err, "mdb: Error opening file `%s': %s\n",
-                    out_file, strerror(errno));
-            }
-        }
-    } else {
-        fflush(MR_mdb_out);
-        fprintf(MR_mdb_err, "mdb: %s\n", problem);
-    }
-}
-
-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, MR_TRUE);
-    }
-}
-
-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);
-}
-
-static MR_bool
-MR_parse_source_locn(char *word, const char **file, int *line)
-{
-    char        *s;
-    const char  *t;
-
-    if ((s = strrchr(word, ':')) != NULL) {
-        for (t = s+1; *t != '\0'; t++) {
-            if (! MR_isdigit(*t)) {
-                return MR_FALSE;
-            }
-        }
-
-        *s = '\0';
-        *file = word;
-        *line = atoi(s+1);
-        return MR_TRUE;
-    }
-
-    return MR_FALSE;
-}
-
-/*
-** Implement the `view' command.  First, check if there is a server
-** attached.  If so, either stop it or abort the command, depending
-** on whether '-f' was given.  Then, if a server name was not supplied,
-** start a new server with a unique name (which has been MR_malloc'd),
-** otherwise attach to the server with the supplied name (and make a
-** MR_malloc'd copy of the name).
-*/
-static const char *
-MR_trace_new_source_window(const char *window_cmd, const char *server_cmd,
-    const char *server_name, int timeout, MR_bool force,
-    MR_bool verbose, MR_bool split)
-{
-    const char  *msg;
-
-    if (MR_trace_source_server.server_name != NULL) {
-        /*
-        ** We are already attached to a server.
-        */
-        if (force) {
-            MR_trace_maybe_close_source_window(verbose);
-        } else {
-            return "error: server already open (use '-f' to force)";
-        }
-    }
-
-    MR_trace_source_server.split = split;
-    if (server_cmd != NULL) {
-        MR_trace_source_server.server_cmd = MR_copy_string(server_cmd);
-    } else {
-        MR_trace_source_server.server_cmd = NULL;
-    }
-
-    if (server_name == NULL) {
-        msg = MR_trace_source_open_server(&MR_trace_source_server,
-                window_cmd, timeout, verbose);
-    } else {
-        MR_trace_source_server.server_name = MR_copy_string(server_name);
-        msg = MR_trace_source_attach(&MR_trace_source_server, timeout,
-            verbose);
-        if (msg != NULL) {
-            /*
-            ** Something went wrong, so we should free the
-            ** strings we allocated just above.
-            */
-            MR_free(MR_trace_source_server.server_name);
-            MR_trace_source_server.server_name = NULL;
-            MR_free(MR_trace_source_server.server_cmd);
-            MR_trace_source_server.server_cmd = NULL;
-        }
-    }
-
-    return msg;
-}
-
-/*
-** If we are attached to a source server, then find the appropriate
-** context and ask the server to point to it, otherwise do nothing.
-*/
-static  void
-MR_trace_maybe_sync_source_window(MR_Event_Info *event_info, MR_bool verbose)
-{
-    const MR_Label_Layout   *parent;
-    const char              *filename;
-    int                     lineno;
-    const char              *parent_filename;
-    int                     parent_lineno;
-    const char              *problem; /* not used */
-    MR_Word                 *base_sp, *base_curfr;
-    const char              *msg;
-
-    if (MR_trace_source_server.server_name != NULL) {
-        lineno = 0;
-        filename = "";
-        parent_lineno = 0;
-        parent_filename = "";
-
-        /*
-        ** At interface ports we send both the parent context and
-        ** the current context.  Otherwise, we just send the current
-        ** context.
-        */
-        if (MR_port_is_interface(event_info->MR_trace_port)) {
-            base_sp = MR_saved_sp(event_info->MR_saved_regs);
-            base_curfr = MR_saved_curfr(event_info->MR_saved_regs);
-            parent = MR_find_nth_ancestor(event_info->MR_event_sll, 1,
-                &base_sp, &base_curfr, &problem);
-            if (parent != NULL) {
-                (void) MR_find_context(parent, &parent_filename,
-                   &parent_lineno);
-            }
-        }
-
-        if (filename[0] == '\0') {
-            (void) MR_find_context(event_info->MR_event_sll,
-                    &filename, &lineno);
-        }
-
-        msg = MR_trace_source_sync(&MR_trace_source_server, filename, lineno,
-            parent_filename, parent_lineno, verbose);
-        if (msg != NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: %s.\n", msg);
-        }
-    }
-}
-
-/*
-** Close a source server, if there is one attached.
-*/
-static  void
-MR_trace_maybe_close_source_window(MR_bool verbose)
-{
-    const char  *msg;
-
-    if (MR_trace_source_server.server_name != NULL) {
-        msg = MR_trace_source_close(&MR_trace_source_server, verbose);
-        if (msg != NULL) {
-            fflush(MR_mdb_out);
-            fprintf(MR_mdb_err, "mdb: %s.\n", msg);
-        }
-
-        MR_free(MR_trace_source_server.server_name);
-        MR_trace_source_server.server_name = NULL;
-        MR_free(MR_trace_source_server.server_cmd);
-        MR_trace_source_server.server_cmd = NULL;
-    }
-}
-
-static struct MR_option MR_trace_movement_cmd_opts[] =
-{
-    { "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' },
-#ifdef  MR_TRACE_CHECK_INTEGRITY
-    { "integrity",  MR_no_argument, NULL,   'i' },
-#endif
-    { NULL,         MR_no_argument, NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_movement_cmd(MR_Trace_Cmd_Info *cmd,
-    char ***words, int *word_count)
-{
-    int c;
-
-#ifdef  MR_TRACE_CHECK_INTEGRITY
-  #define   MR_TRACE_MOVEMENT_OPTS  "NSains"
-#else
-  #define   MR_TRACE_MOVEMENT_OPTS  "NSans"
-#endif
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, MR_TRACE_MOVEMENT_OPTS,
-        MR_trace_movement_cmd_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'N':
-                cmd->MR_trace_strict = MR_FALSE;
-                break;
-
-            case 'S':
-                cmd->MR_trace_strict = MR_TRUE;
-                break;
-
-            case 'a':
-                cmd->MR_trace_print_level = MR_PRINT_LEVEL_ALL;
-                break;
-
-            case 'n':
-                cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE;
-                break;
-
-            case 's':
-                cmd->MR_trace_print_level = MR_PRINT_LEVEL_SOME;
-                break;
-
-#ifdef  MR_TRACE_CHECK_INTEGRITY
-            case 'i':
-                cmd->MR_trace_check_integrity = MR_TRUE;
-                break;
-#endif
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_retry_opts[] =
-{
-    { "assume-all-io-is-tabled",    MR_no_argument, NULL,   'a' },
-    { "force",                      MR_no_argument, NULL,   'f' },
-    { "interactive",                MR_no_argument, NULL,   'i' },
-    { "only-if-safe",               MR_no_argument, NULL,   'o' },
-    { NULL,                         MR_no_argument, NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_retry(MR_Retry_Across_Io *across_io,
-    MR_bool *assume_all_io_is_tabled, char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "afio",
-        MR_trace_retry_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'a':
-                *assume_all_io_is_tabled = MR_TRUE;
-                break;
-
-            case 'f':
-                *across_io = MR_RETRY_IO_FORCE;
-                break;
-
-            case 'i':
-                *across_io = MR_RETRY_IO_INTERACTIVE;
-                break;
-
-            case 'o':
-                *across_io = MR_RETRY_IO_ONLY_IF_SAFE;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_when_action_multi_ignore_opts[] =
-{
-    { "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-list",         MR_required_argument,   NULL,   'p' },
-    { "no-warn",            MR_no_argument,         NULL,   'n' },
-    { "print",              MR_no_argument,         NULL,   'P' },
-    { "stop",               MR_no_argument,         NULL,   'S' },
-    { "select-all",         MR_no_argument,         NULL,   'A' },
-    { "select-one",         MR_no_argument,         NULL,   'O' },
-    { NULL,                 MR_no_argument,         NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_when_action_multi_ignore(MR_Spy_When *when,
-    MR_Spy_Action *action, MR_MultiMatch *multi_match,
-    MR_Spy_Ignore_When*ignore_when, int *ignore_count,
-    MR_Spy_Print_List *print_list,
-    char ***words, int *word_count)
-{
-    int                 c;
-    MR_Spy_Print        node;
-    MR_Spy_Print_List   list;
-    MR_bool             warn;
-
-    warn = MR_TRUE;
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "AE:I:OPSaeinp:",
-        MR_trace_when_action_multi_ignore_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'a':
-                *when = MR_SPY_ALL;
-                break;
-
-            case 'e':
-                *when = MR_SPY_ENTRY;
-                break;
-
-            case 'i':
-                *when = MR_SPY_INTERFACE;
-                break;
-
-            case 'n':
-                warn = MR_FALSE;
-                break;
-
-            case 'p':
-                *print_list = MR_add_to_print_list_end(MR_BROWSE_FORMAT_FLAT,
-                    MR_optarg, warn, *print_list);
-                break;
-
-            case 'E':
-                if (! MR_trace_is_natural_number(MR_optarg, ignore_count)) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                *ignore_when = MR_SPY_IGNORE_ENTRY;
-                break;
-
-            case 'I':
-                if (! MR_trace_is_natural_number(MR_optarg, ignore_count)) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                *ignore_when = MR_SPY_IGNORE_INTERFACE;
-                break;
-
-            case 'A':
-                *multi_match = MR_MULTIMATCH_ALL;
-                break;
-
-            case 'O':
-                *multi_match = MR_MULTIMATCH_ONE;
-                break;
-
-            case 'P':
-                *action = MR_SPY_PRINT;
-                break;
-
-            case 'S':
-                *action = MR_SPY_STOP;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    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)
-{
-    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_cur_cmd();
-                    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_cur_cmd();
-                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' },
-    { "ignore-interface",   MR_required_argument,   NULL,   'I' },
-    { NULL,                 MR_no_argument,         NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_ignore_count(MR_Spy_Ignore_When *ignore_when,
-    int *ignore_count, char ***words, int *word_count)
-{
-    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 (! MR_trace_is_natural_number(MR_optarg, ignore_count)) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                *ignore_when = MR_SPY_IGNORE_ENTRY;
-                break;
-
-            case 'I':
-                if (! MR_trace_is_natural_number(MR_optarg, ignore_count)) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                *ignore_when = MR_SPY_IGNORE_INTERFACE;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_break_print_opts[] =
-{
-    { "end",        MR_no_argument, NULL,   'e' },
-    { "no-warn",    MR_no_argument, NULL,   'n' },
-    { "flat",       MR_no_argument, NULL,   'f' },
-    { "raw-pretty", MR_no_argument, NULL,   'r' },
-    { "verbose",    MR_no_argument, NULL,   'v' },
-    { "pretty",     MR_no_argument, NULL,   'p' },
-    { NULL,         MR_no_argument, NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_break_print(MR_Browse_Format *format, MR_bool *at_start,
-    MR_bool *warn, char ***words, int *word_count)
-{
-    int c;
-
-    *format = MR_BROWSE_FORMAT_FLAT;
-    *at_start = MR_TRUE;
-    *warn = MR_TRUE;
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "enfrvp",
-        MR_trace_break_print_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'e':
-                *at_start = MR_FALSE;
-                break;
-
-            case 'n':
-                *warn = MR_FALSE;
-                break;
-
-            case 'f':
-                *format = MR_BROWSE_FORMAT_FLAT;
-                break;
-
-            case 'r':
-                *format = MR_BROWSE_FORMAT_RAW_PRETTY;
-                break;
-
-            case 'v':
-                *format = MR_BROWSE_FORMAT_VERBOSE;
-                break;
-
-            case 'p':
-                *format = MR_BROWSE_FORMAT_PRETTY;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_detailed_opts[] =
-{
-    { "detailed",   MR_no_argument, NULL,   'd' },
-    { NULL,         MR_no_argument, NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_detailed(MR_bool *detailed, char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "d",
-        MR_trace_detailed_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'd':
-                *detailed = MR_TRUE;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static MR_bool
-MR_trace_options_stack_trace(MR_bool *detailed, int *frame_limit,
-    char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "df:",
-        MR_trace_detailed_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'd':
-                *detailed = MR_TRUE;
-                break;
-
-            case 'f':
-                if (! MR_trace_is_natural_number(MR_optarg, frame_limit)) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static MR_bool
-MR_trace_options_confirmed(MR_bool *confirmed, char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt(*word_count, *words, "NYny")) != EOF) {
-        switch (c) {
-
-            case 'n':
-            case 'N':
-                *confirmed = MR_FALSE;
-                break;
-
-            case 'y':
-            case 'Y':
-                *confirmed = MR_TRUE;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_quiet_opts[] =
-{
-    { "quiet",      MR_no_argument, NULL,   'q' },
-    { "verbose",    MR_no_argument, NULL,   'v' },
-    { NULL,         MR_no_argument, NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_quiet(MR_bool *verbose, char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "qv",
-        MR_trace_quiet_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'q':
-                *verbose = MR_FALSE;
-                break;
-
-            case 'v':
-                *verbose = MR_TRUE;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                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_opts[] =
-{
-    { "ignore-errors",  MR_no_argument, NULL,   'i' },
-    { NULL,             MR_no_argument, NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_ignore(MR_bool *ignore_errors, char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "i",
-        MR_trace_ignore_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'i':
-                *ignore_errors = MR_TRUE;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_format_opts[] =
-{
-    { "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' },
-    { "xml",        MR_no_argument, NULL,   'x' },
-    { NULL,         MR_no_argument, NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_format(MR_Browse_Format *format, MR_bool *xml, char ***words,
-    int *word_count)
-{
-    int c;
-
-    *format = MR_BROWSE_DEFAULT_FORMAT;
-    *xml = MR_FALSE;
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "frvpx",
-        MR_trace_format_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'f':
-                *format = MR_BROWSE_FORMAT_FLAT;
-                break;
-
-            case 'r':
-                *format = MR_BROWSE_FORMAT_RAW_PRETTY;
-                break;
-
-            case 'v':
-                *format = MR_BROWSE_FORMAT_VERBOSE;
-                break;
-
-            case 'p':
-                *format = MR_BROWSE_FORMAT_PRETTY;
-                break;
-
-            case 'x':
-                *xml = MR_TRUE;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_param_set_opts[] =
-{
-    { "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 MR_bool
-MR_trace_options_param_set(MR_Word *print_set, MR_Word *browse_set,
-    MR_Word *print_all_set, MR_Word *flat_format,
-    MR_Word *raw_pretty_format, MR_Word *verbose_format,
-    MR_Word *pretty_format, char ***words, int *word_count)
-{
-    int     c;
-    MR_Word mercury_bool_yes;
-    MR_Word mercury_bool_no;
-
-    MR_TRACE_CALL_MERCURY(
-        mercury_bool_yes = ML_BROWSE_mercury_bool_yes();
-        mercury_bool_no = ML_BROWSE_mercury_bool_no();
-    );
-
-    *print_set = mercury_bool_no;
-    *browse_set = mercury_bool_no;
-    *print_all_set = mercury_bool_no;
-    *flat_format = mercury_bool_no;
-    *raw_pretty_format = mercury_bool_no;
-    *verbose_format = mercury_bool_no;
-    *pretty_format = mercury_bool_no;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "PBAfrvp",
-        MR_trace_param_set_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'f':
-                *flat_format = mercury_bool_yes;
-                break;
-
-            case 'r':
-                *raw_pretty_format = mercury_bool_yes;
-                break;
-
-            case 'v':
-                *verbose_format = mercury_bool_yes;
-                break;
-
-            case 'p':
-                *pretty_format = mercury_bool_yes;
-                break;
-
-            case 'P':
-                *print_set = mercury_bool_yes;
-                break;
-
-            case 'B':
-                *browse_set = mercury_bool_yes;
-                break;
-
-            case 'A':
-                *print_all_set = mercury_bool_yes;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_view_opts[] =
-{
-    { "close",          MR_no_argument,         NULL,   'c' },
-    { "window-command", MR_required_argument,   NULL,   'w' },
-    { "server-command", MR_required_argument,   NULL,   's' },
-    { "server-name",    MR_required_argument,   NULL,   'n' },
-    { "timeout",        MR_required_argument,   NULL,   't' },
-    { "force",          MR_no_argument,         NULL,   'f' },
-    { "verbose",        MR_no_argument,         NULL,   'v' },
-    { "split-screen",   MR_no_argument,         NULL,   '2' },
-    { NULL,             MR_no_argument,         NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_view(const char **window_cmd, const char **server_cmd,
-    const char **server_name, int *timeout, MR_bool *force,
-    MR_bool *verbose, MR_bool *split, MR_bool *close_window,
-    char ***words, int *word_count)
-{
-    int c;
-    MR_bool no_close = MR_FALSE;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "cw:s:n:t:fv2",
-        MR_trace_view_opts, NULL)) != EOF)
-    {
-        /*
-        ** Option '-c' is mutually incompatible with '-f', '-t',
-        ** '-s', '-n', '-w' and '-2'.
-        */
-        switch (c) {
-
-            case 'c':
-                if (no_close) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                *close_window = MR_TRUE;
-                break;
-
-            case 'w':
-                if (*close_window) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                *window_cmd = MR_optarg;
-                no_close = MR_TRUE;
-                break;
-
-            case 's':
-                if (*close_window) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                *server_cmd = MR_optarg;
-                no_close = MR_TRUE;
-                break;
-
-            case 'n':
-                if (*close_window) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                *server_name = MR_optarg;
-                no_close = MR_TRUE;
-                break;
-
-            case 't':
-                if (*close_window ||
-                    ! MR_trace_is_natural_number(MR_optarg, timeout))
-                {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                no_close = MR_TRUE;
-                break;
-
-            case 'f':
-                if (*close_window) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                *force = MR_TRUE;
-                no_close = MR_TRUE;
-                break;
-
-            case 'v':
-                *verbose = MR_TRUE;
-                break;
-
-            case '2':
-                if (*close_window) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                *split = MR_TRUE;
-                no_close = MR_TRUE;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_dd_opts[] =
-{
-    { "assume-all-io-is-tabled",    MR_no_argument,         NULL,   'a' },
-    { "debug",                      MR_no_argument,         NULL,   'z' },
-    { "depth",                      MR_required_argument,   NULL,   'd' },
-    { "nodes",                      MR_required_argument,   NULL,   'n' },
-    { "resume",                     MR_no_argument,         NULL,   'r' },
-    { "search-mode",                MR_required_argument,   NULL,   's' },
-    { "pass-trace-counts",          MR_required_argument,   NULL,   'p' },
-    { "pass-trace-count",           MR_required_argument,   NULL,   'p' },
-    { "fail-trace-counts",          MR_required_argument,   NULL,   'f' },
-    { "fail-trace-count",           MR_required_argument,   NULL,   'f' },
-    { "resume",                     MR_no_argument,         NULL,   'r' },
-    { "test",                       MR_no_argument,         NULL,   't' },
-    { NULL,                         MR_no_argument,         NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_dd(MR_bool *assume_all_io_is_tabled,
-    MR_Unsigned *default_depth, MR_Unsigned *num_nodes,
-    MR_Decl_Search_Mode *search_mode, MR_bool *search_mode_was_set,
-    MR_bool *search_mode_requires_trace_counts,
-    char **pass_trace_counts_file, char **fail_trace_counts_file,
-    MR_bool *new_session, MR_bool *testing,  MR_bool *debug,
-    char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "ad:f:n:p:rs:tz",
-        MR_trace_dd_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'a':
-                *assume_all_io_is_tabled = MR_TRUE;
-                break;
-
-            case 'd':
-                if (! MR_trace_is_unsigned(MR_optarg, default_depth)) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                break;
-
-            case 'f':
-                *fail_trace_counts_file = MR_copy_string(MR_optarg);
-                break;
-
-            case 'n':
-                if (! MR_trace_is_unsigned(MR_optarg, num_nodes)) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                break;
-
-            case 'p':
-                *pass_trace_counts_file = MR_copy_string(MR_optarg);
-                break;
-
-            case 'r':
-                *new_session = MR_FALSE;
-                break;
-
-            case 's':
-                if (MR_trace_is_valid_search_mode_string(MR_optarg,
-                    search_mode, search_mode_requires_trace_counts))
-                {
-                    *search_mode_was_set = MR_TRUE;
-                } else {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                break;
-
-            case 't':
-                *testing = MR_TRUE;
-                break;
-
-            case 'z':
-                *debug = MR_TRUE;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_dice_opts[] =
-{
-    { "pass-trace-counts",      MR_required_argument,   NULL,   'p' },
-    { "pass-trace-count",       MR_required_argument,   NULL,   'p' },
-    { "fail-trace-counts",      MR_required_argument,   NULL,   'f' },
-    { "fail-trace-count",       MR_required_argument,   NULL,   'f' },
-    { "sort",                   MR_required_argument,   NULL,   's' },
-    { "top",                    MR_required_argument,   NULL,   'n' },
-    { "output-to-file",         MR_required_argument,   NULL,   'o' },
-    { "module",                 MR_required_argument,   NULL,   'm' },
-    { NULL,                     MR_no_argument,         NULL,   0   }
-};
-
-static MR_bool
-MR_trace_options_dice(char **pass_trace_counts_file,
-    char **fail_trace_counts_file, char **sort_str, int *n, char **out_file,
-    char **module, char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "p:f:s:n:o:m:",
-        MR_trace_dice_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'p':
-                /*
-                ** Don't free *pass_trace_counts_file even if non-NULL,
-                ** since its initial value comes from a global variable,
-                ** and thus will still be used after the dice command.
-                ** The waste of not freeing of the string allocated by
-                ** MR_copy_string if this option is duplicated can be
-                ** easily lived with.
-                */
-
-                *pass_trace_counts_file = MR_copy_string(MR_optarg);
-                break;
-
-            case 'f':
-                /*
-                ** Don't free *fail_trace_counts_file even if non-NULL,
-                ** since its initial value comes from a global variable,
-                ** and thus will still be used after the dice command.
-                ** The waste of not freeing of the string allocated by
-                ** MR_copy_string if this option is duplicated can be
-                ** easily lived with.
-                */
-
-                *fail_trace_counts_file = MR_copy_string(MR_optarg);
-                break;
-
-            case 's':
-                *sort_str = MR_copy_string(MR_optarg);
-                break;
-
-            case 'n':
-                if (! MR_trace_is_natural_number(MR_optarg, n)) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                break;
-
-            case 'o':
-                *out_file = MR_copy_string(MR_optarg);
-                break;
-
-            case 'm':
-                *module = MR_copy_string(MR_optarg);
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_stats_opts[] =
-{
-    { "file",      MR_required_argument,    NULL,   'f' },
-    { NULL,        MR_no_argument,          NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_stats(char **filename, char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "f:",
-        MR_trace_stats_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'f':
-                *filename = MR_optarg;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_type_ctor_opts[] =
-{
-    { "print-rep",      MR_no_argument,     NULL,   'r' },
-    { "print-functors", MR_no_argument,     NULL,   'f' },
-    { NULL,             MR_no_argument,     NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_type_ctor(MR_bool *print_rep, MR_bool *print_functors,
-    char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "rf",
-        MR_trace_type_ctor_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'f':
-                *print_functors = MR_TRUE;
-                break;
-
-            case 'r':
-                *print_rep = MR_TRUE;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_class_decl_opts[] =
-{
-    { "print-methods",      MR_no_argument,     NULL,   'm' },
-    { "print-instances",    MR_no_argument,     NULL,   'i' },
-    { NULL,                 MR_no_argument,     NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_class_decl(MR_bool *print_methods, MR_bool *print_instances,
-    char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "mi",
-        MR_trace_class_decl_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'm':
-                *print_methods = MR_TRUE;
-                break;
-
-            case 'i':
-                *print_instances = MR_TRUE;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_all_procedures_opts[] =
-{
-    { "separate",   MR_no_argument,         NULL,   's' },
-    { "uci",        MR_no_argument,         NULL,   'u' },
-    { "module",     MR_required_argument,   NULL,   'm' },
-    { NULL,         MR_no_argument,         NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_all_procedures(MR_bool *separate, MR_bool *uci, char **module,
-    char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "sum:",
-        MR_trace_all_procedures_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 's':
-                *separate = MR_TRUE;
-                break;
-
-            case 'u':
-                *uci = MR_TRUE;
-                break;
-
-            case 'm':
-                *module = MR_optarg;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_ambiguity_opts[] =
-{
-    { "outputfile", MR_required_argument,   NULL,   'o' },
-    { NULL,         MR_no_argument,         NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_ambiguity(const char **outfile,
-    char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "o:",
-        MR_trace_ambiguity_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'o':
-                *outfile = MR_optarg;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_diff_opts[] =
-{
-    { "start",      MR_required_argument,   NULL,   's' },
-    { "max",        MR_required_argument,   NULL,   'm' },
-    { NULL,         MR_no_argument,         NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_diff(int *start, int *max, char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "m:s:", MR_trace_diff_opts,
-        NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'm':
-                if (! MR_trace_is_natural_number(MR_optarg, max)) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                break;
-
-            case 's':
-                if (! MR_trace_is_natural_number(MR_optarg, start)) {
-                    MR_trace_usage_cur_cmd();
-                    return MR_FALSE;
-                }
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static struct MR_option MR_trace_dump_opts[] =
-{
-    { "xml",        MR_no_argument,     NULL,   'x' },
-    { NULL,         MR_no_argument,     NULL,   0 }
-};
-
-static MR_bool
-MR_trace_options_dump(MR_bool *xml, char ***words, int *word_count)
-{
-    int c;
-
-    MR_optind = 0;
-    while ((c = MR_getopt_long(*word_count, *words, "x",
-        MR_trace_dump_opts, NULL)) != EOF)
-    {
-        switch (c) {
-
-            case 'x':
-                *xml = MR_TRUE;
-                break;
-
-            default:
-                MR_trace_usage_cur_cmd();
-                return MR_FALSE;
-        }
-    }
-
-    *words = *words + MR_optind - 1;
-    *word_count = *word_count - MR_optind + 1;
-    return MR_TRUE;
-}
-
-static void
-MR_trace_usage_cur_cmd(void)
-{
-    /* MR_current_cmd_category is unused now, for but could be used later. */
-    fflush(MR_mdb_out);
-    fprintf(MR_mdb_err,
-        "mdb: %s: usage error -- type `help %s' for help.\n",
-        MR_current_cmd_name, MR_current_cmd_name);
-}
-
-/*
-** Read lines until we find one that contains only "end".
-** Return the lines concatenated together.
-** The memory returned is allocated with MR_malloc();
-** it is the caller's responsibility to MR_free() it when appropriate.
-*/
-
-static const char *
-MR_trace_read_help_text(void)
-{
-    char    *text;
-    char    *doc_chars = NULL;
-    int     doc_char_max = 0;
-    int     next_char_slot;
-    int     line_len;
-    int     i;
-
-    next_char_slot = 0;
-    while ((text = MR_trace_getline("cat> ", MR_mdb_in, MR_mdb_out)) != NULL) {
-        if (MR_streq(text, "end")) {
-            MR_free(text);
-            break;
-        }
-
-        line_len = strlen(text);
-        MR_ensure_big_enough(next_char_slot + line_len + 2, doc_char, char,
-            MR_INIT_DOC_CHARS);
-        for (i = 0; i < line_len; i++) {
-            doc_chars[next_char_slot + i] = text[i];
-        }
-
-        next_char_slot += line_len;
-        doc_chars[next_char_slot] = '\n';
-        next_char_slot += 1;
-        MR_free(text);
-    }
-
-    MR_ensure_big_enough(next_char_slot, doc_char, char, MR_INIT_DOC_CHARS);
-    doc_chars[next_char_slot] = '\0';
-    return doc_chars;
-}
-
-/*
-** Given a text line, break it up into words composed of non-space characters
-** separated by space characters. Make each word a NULL-terminated string,
-** overwriting some spaces in the line array in the process.
-**
-** If the first word is a number but the second is not, swap the two.
-** If the first word has a number prefix, separate it out.
-**
-** On return *words will point to an array of strings, with space for
-** *words_max strings. The number of strings (words) filled in will be
-** given by *word_count.
-**
-** The space for the *words array is allocated with MR_malloc().
-** It is the caller's responsibility to free it when appropriate.
-** The elements of the *words array point to memory from the line array.
-** The lifetime of the elements of the *words array expires when
-** the line array is MR_free()'d or further modified or when
-** MR_trace_parse_line is called again, whichever comes first.
-**
-** The return value is NULL if everything went OK, and an error message
-** otherwise.
-*/
-
-static const char *
-MR_trace_parse_line(char *line, char ***words, int *word_max, int *word_count)
-{
-    char        **raw_words;
-    int         raw_word_max;
-    int         raw_word_count;
-    static char count_buf[MR_NUMBER_LEN + 1];
-    char        *s;
-    int         i;
-    const char  *problem;
-
-    /*
-    ** Handle a possible number prefix on the first word on the line,
-    ** separating it out into a word on its own.
-    */
-
-    problem = MR_trace_break_into_words(line, &raw_words, &raw_word_max,
-        &raw_word_count);
-    if (problem != NULL) {
-        return problem;
-    }
+    problem = MR_trace_break_into_words(line, &raw_words, &raw_word_max,
+        &raw_word_count);
+    if (problem != NULL) {
+        return problem;
+    }
 
     if (raw_word_count > 0 && MR_isdigit(*raw_words[0])) {
         i = 0;
@@ -7927,99 +1130,6 @@
     return NULL;
 }
 
-static void
-MR_trace_expand_aliases(char ***words, int *word_max, int *word_count)
-{
-    const char  *alias_key;
-    char        **alias_words;
-    int         alias_word_count;
-    int         alias_copy_start;
-    int         i;
-    int         n;
-
-    if (*word_count == 0) {
-        alias_key = "EMPTY";
-        alias_copy_start = 0;
-    } else if (MR_trace_is_natural_number(*words[0], &n)) {
-        alias_key = "NUMBER";
-        alias_copy_start = 0;
-    } else {
-        alias_key = *words[0];
-        alias_copy_start = 1;
-    }
-
-    if (MR_trace_lookup_alias(alias_key, &alias_words, &alias_word_count)) {
-        MR_ensure_big_enough(*word_count + alias_word_count, *word, char *,
-            MR_INIT_WORD_COUNT);
-
-        /* Move the original words (except the alias key) up. */
-        for (i = *word_count - 1; i >= alias_copy_start; i--) {
-            (*words)[i + alias_word_count - alias_copy_start] = (*words)[i];
-        }
-
-        /* Move the alias body to the words array. */
-        for (i = 0; i < alias_word_count; i++) {
-            (*words)[i] = alias_words[i];
-        }
-
-        *word_count += alias_word_count - alias_copy_start;
-    }
-}
-
-static MR_bool
-MR_trace_source(const char *filename, MR_bool ignore_errors)
-{
-    FILE    *fp;
-
-    if ((fp = fopen(filename, "r")) != NULL) {
-        MR_trace_source_from_open_file(fp);
-        fclose(fp);
-        return MR_TRUE;
-    } else {
-        fflush(MR_mdb_out);
-        fprintf(MR_mdb_err, "%s: %s.\n", filename, strerror(errno));
-        return MR_FALSE;
-    }
-}
-
-static void
-MR_trace_source_from_open_file(FILE *fp)
-{
-    char    *contents;
-    MR_Line *line;
-    MR_Line *prev_line;
-    MR_Line *old_head;
-
-    prev_line = NULL;
-    old_head = MR_line_head;
-
-    /*
-    ** Insert the sourced commands at the front of the command queue,
-    ** preserving their order in the sourced file.
-    */
-    while ((contents = MR_trace_readline_raw(fp)) != NULL) {
-        line = MR_NEW(MR_Line);
-        line->MR_line_contents = MR_copy_string(contents);
-
-        if (prev_line == NULL) {
-            MR_line_head = line;
-        } else {
-            prev_line->MR_line_next = line;
-        }
-
-        prev_line = line;
-    }
-
-    if (prev_line != NULL) {
-        prev_line->MR_line_next = old_head;
-        if (MR_line_tail == NULL) {
-            MR_line_tail = prev_line;
-        }
-    }
-
-    MR_trace_internal_interacting = MR_FALSE;
-}
-
 /*
 ** Call MR_trace_getline to get the next line of input, then do some
 ** further processing.  If the input has reached EOF, return the command
@@ -8130,7 +1240,7 @@
 ** If there are no lines in the queue, this function returns NULL.
 */
 
-static char *
+char *
 MR_trace_getline_queue(void)
 {
     if (MR_line_head != NULL) {
@@ -8151,7 +1261,7 @@
     }
 }
 
-static void
+void
 MR_insert_line_at_head(const char *contents)
 {
     MR_Line *line;
@@ -8166,7 +1276,7 @@
     }
 }
 
-static void
+void
 MR_insert_line_at_tail(const char *contents)
 {
     MR_Line *line;
@@ -8301,7 +1411,7 @@
     return NULL;
 }
 
-static void
+void
 MR_trace_event_print_internal_report(MR_Event_Info *event_info)
 {
     const MR_Label_Layout   *parent;
@@ -8358,90 +1468,6 @@
         parent_filename, parent_lineno, indent);
 }
 
-static const char *const    MR_trace_movement_cmd_args[] =
-    { "-N", "-S", "-a", "-i", "-n", "-s",
-    "--none", "--some", "--all", "--integrity",
-    "--strict", "--no-strict", NULL };
-
-/*
-** "retry --assume-all-io-is-tabled" is deliberately not documented as
-** it is for developers only.
-*/
-static const char *const    MR_trace_retry_cmd_args[] =
-    { "--force", "--interactive", "--only-if-safe", NULL };
-
-static const char *const    MR_trace_print_cmd_args[] =
-    { "-f", "-p", "-v", "--flat", "--pretty", "--verbose",
-    "exception", "goal", "*", NULL };
-
-/*
-** It's better to have a single completion where possible,
-** so don't include `-d' here.
-*/
-static const char *const    MR_trace_stack_cmd_args[] =
-    { "--detailed", NULL };
-
-static const char *const    MR_trace_set_cmd_args[] =
-    { "-A", "-B", "-P", "-f", "-p", "-v",
-    "--print-all", "--print", "--browse",
-    "--flat", "--pretty", "--verbose", "xml_tmp_filename",
-    "xml_browser_cmd", "format", "depth", "size", "width", "lines", "flat",
-    "pretty", "verbose", NULL };
-
-static const char *const    MR_trace_view_cmd_args[] =
-    { "-c", "-f", "-n", "-s", "-t", "-v", "-w", "-2",
-    "--close", "--verbose", "--force", "--split-screen",
-    "--window-command", "--server-command", "--server-name",
-    "--timeout", NULL };
-
-static const char *const    MR_trace_break_cmd_args[] =
-    { "-A", "-E", "-I", "-O", "-P", "-S", "-a", "-e", "-i",
-    "--all", "--entry", "--ignore-entry", "--ignore-interface",
-    "--interface", "--print", "--select-all", "--select-one",
-    "--stop", "here", "info", NULL };
-
-static const char *const    MR_trace_ignore_cmd_args[] =
-    { "-E", "-I", "--ignore-entry", "--ignore-interface", NULL };
-
-static const char *const    MR_trace_printlevel_cmd_args[] =
-    { "none", "some", "all", NULL };
-
-static const char *const    MR_trace_on_off_args[] =
-    { "on", "off", NULL };
-
-static const char *const    MR_trace_context_cmd_args[] =
-    { "none", "before", "after", "prevline", "nextline", NULL };
-
-static const char *const    MR_trace_scope_cmd_args[] =
-    { "all", "interface", "entry", NULL };
-
-static const char *const    MR_trace_dd_cmd_args[] =
-    { "-s", "-a", "-d", "-n", "--search-mode",
-    "--assume-all-io-is-tabled", "--depth", "--nodes",
-    "td", "top_down", "dq" "divide_and_query", "sdq",
-    "suspicion_divide_and_query", NULL };
-
-/*
-** "table_io allow" is deliberately not documented as it is developer only
-** "table_io begin" and "table_io end" are deliberately not documented in an
-** effort to encourage consistent use of start/stop.
-*/
-static const char *const    MR_trace_table_io_cmd_args[] =
-    { "stats", "start", "stop", NULL };
-
-/*
-** It's better to have a single completion where possible,
-** so don't include `-i' here.
-*/
-static const char *const    MR_trace_source_cmd_args[] =
-    { "--ignore-errors", NULL };
-
-static const char *const    MR_trace_quit_cmd_args[] =
-    { "-y", NULL };
-
-static const char *const    MR_trace_stats_cmd_args[] =
-    { "procs", "labels", "var_names", "io_tabling", NULL };
-
 static const MR_Trace_Command_Info  MR_trace_command_infos[] =
 {
     /*
@@ -8501,10 +1527,6 @@
         NULL, MR_trace_var_completer },
     { "browsing", "list", MR_trace_cmd_list,
         NULL, MR_trace_null_completer },
-    { "browsing", "push_list_dir", MR_trace_cmd_push_list_dir,
-        NULL, MR_trace_null_completer },
-    { "browsing", "pop_list_dir", MR_trace_cmd_pop_list_dir,
-        NULL, MR_trace_null_completer },
 
     { "breakpoint", "break", MR_trace_cmd_break,
         MR_trace_break_cmd_args, MR_trace_proc_spec_completer },
@@ -8541,22 +1563,44 @@
     { "table_io", "table_io", MR_trace_cmd_table_io,
         MR_trace_table_io_cmd_args, MR_trace_null_completer },
 
-    { "parameter", "printlevel", MR_trace_cmd_printlevel,
-        MR_trace_printlevel_cmd_args, MR_trace_null_completer },
     { "parameter", "mmc_options", MR_trace_cmd_mmc_options,
         NULL, MR_trace_null_completer },
+    { "parameter", "printlevel", MR_trace_cmd_printlevel,
+        MR_trace_printlevel_cmd_args, MR_trace_null_completer },
     { "parameter", "scroll", MR_trace_cmd_scroll,
         MR_trace_on_off_args, MR_trace_null_completer },
     { "parameter", "stack_default_limit", MR_trace_cmd_stack_default_limit,
         NULL, MR_trace_null_completer },
-    { "parameter", "context", MR_trace_cmd_context,
-        MR_trace_context_cmd_args, MR_trace_null_completer },
     { "parameter", "goal_paths", MR_trace_cmd_goal_paths,
         MR_trace_on_off_args, MR_trace_null_completer },
     { "parameter", "scope", MR_trace_cmd_scope,
         MR_trace_scope_cmd_args, MR_trace_null_completer },
     { "parameter", "echo", MR_trace_cmd_echo,
         MR_trace_on_off_args, MR_trace_null_completer },
+    { "parameter", "context", MR_trace_cmd_context,
+        MR_trace_context_cmd_args, MR_trace_null_completer },
+    { "parameter", "list_context_lines", MR_trace_cmd_list_context_lines,
+        NULL, MR_trace_null_completer },
+    { "parameter", "list_path", MR_trace_cmd_list_path,
+        NULL, MR_trace_null_completer },
+    { "parameter", "push_list_dir", MR_trace_cmd_push_list_dir,
+        NULL, MR_trace_null_completer },
+    { "parameter", "pop_list_dir", MR_trace_cmd_pop_list_dir,
+        NULL, MR_trace_null_completer },
+    { "parameter", "fail_trace_counts", MR_trace_cmd_fail_trace_counts,
+        NULL, MR_trace_filename_completer },
+    { "parameter", "pass_trace_counts", MR_trace_cmd_pass_trace_counts,
+        NULL, MR_trace_filename_completer },
+    { "parameter", "max_io_actions", MR_trace_cmd_max_io_actions,
+        NULL, MR_trace_null_completer },
+    { "parameter", "xml_browser_cmd", MR_trace_cmd_xml_browser_cmd,
+        NULL, MR_trace_null_completer },
+    { "parameter", "xml_tmp_filename", MR_trace_cmd_xml_tmp_filename,
+        NULL, MR_trace_null_completer },
+    { "parameter", "format", MR_trace_cmd_format,
+        MR_trace_format_cmd_args, MR_trace_null_completer },
+    { "parameter", "format_param", MR_trace_cmd_format_param,
+        MR_trace_format_param_cmd_args, MR_trace_null_completer },
     { "parameter", "alias", MR_trace_cmd_alias,
         NULL, MR_trace_command_completer },
     { "parameter", "unalias", MR_trace_cmd_unalias,
@@ -8575,11 +1619,9 @@
         NULL, MR_trace_proc_spec_completer },
     { "dd", "untrust", MR_trace_cmd_untrust,
         NULL, MR_trace_null_completer },
-    { "dd", "trusted", MR_trace_cmd_trusted, NULL,
-        MR_trace_null_completer },
+    { "dd", "trusted", MR_trace_cmd_trusted,
+        NULL, MR_trace_null_completer },
 
-    { "misc", "set", MR_trace_cmd_set,
-        MR_trace_set_cmd_args, MR_trace_null_completer },
     { "misc", "source", MR_trace_cmd_source,
         MR_trace_source_cmd_args, MR_trace_filename_completer },
     { "misc", "save", MR_trace_cmd_save,
@@ -8615,7 +1657,7 @@
     { "developer", "mm_stacks", MR_trace_cmd_mm_stacks,
         NULL, MR_trace_null_completer },
     { "developer", "nondet_stack", MR_trace_cmd_nondet_stack,
-        MR_trace_stack_cmd_args, MR_trace_null_completer },
+        MR_trace_nondet_stack_cmd_args, MR_trace_null_completer },
     { "developer", "stack_regs", MR_trace_cmd_stack_regs,
         NULL, MR_trace_null_completer },
     { "developer", "all_regs", MR_trace_cmd_all_regs,
@@ -8668,7 +1710,7 @@
     }
 }
 
-static const MR_Trace_Command_Info *
+const MR_Trace_Command_Info *
 MR_trace_valid_command(const char *word)
 {
     int i;
Index: trace/mercury_trace_internal.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_internal.h,v
retrieving revision 1.20
diff -u -b -r1.20 mercury_trace_internal.h
--- trace/mercury_trace_internal.h	12 Aug 2005 02:01:28 -0000	1.20
+++ trace/mercury_trace_internal.h	3 Apr 2006 12:28:15 -0000
@@ -1,4 +1,7 @@
 /*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
 ** Copyright (C) 1998-2002, 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.
@@ -8,10 +11,14 @@
 #define	MERCURY_TRACE_INTERNAL_H
 
 #include "mercury_types.h"		/* for MR_Code */
+#include "mercury_trace_base.h"         /* for MR_SavedDebugState */
+
 #include "mercury_trace.h"		/* for MR_Event_Info, etc. */
 #include "mercury_std.h"		/* for MR_bool */
+#include "mercury_trace_cmds.h"         /* for MR_Spy_Print_List */
 #include "mercury_trace_completion.h"	/* for MR_Make_Completer */
 #include "mercury_trace_spy.h"		/* for MR_Spy_Print_List */
+#include "mercury_trace_source.h"       /* for MR_Trace_Source_Server */
 
 #include <stdio.h>			/* for FILE */
 
@@ -19,6 +26,10 @@
 			MR_bool interactive, MR_Spy_Print_List print_list,
 			MR_Event_Info *event_info);
 
+extern  void        MR_trace_event_print_internal_report(
+                        MR_Event_Info *event_info);
+
+
 /*
 ** Debugger I/O streams.
 ** Replacements for stdin/stdout/stderr respectively.
@@ -34,6 +45,78 @@
 extern FILE *MR_mdb_err;
 
 /*
+** We print confirmation of commands (e.g. new aliases) if this is MR_TRUE.
+*/ 
+
+MR_bool         MR_trace_internal_interacting;
+
+/*
+** The structure of the input queue, and the operations that work on it.
+*/
+
+typedef struct MR_Line_Struct {
+    char                    *MR_line_contents;
+    struct MR_Line_Struct   *MR_line_next;
+} MR_Line;
+
+extern  void        MR_insert_line_at_head(const char *contents);
+extern  void        MR_insert_line_at_tail(const char *contents);
+
+/*
+** If there any lines waiting in the queue, return the first of these.
+** The memory for the line will have been allocated with MR_malloc(),
+** and it is the caller's resposibility to MR_free() it when appropriate.
+** If there are no lines in the queue, this function returns NULL.
+*/
+        
+extern  char        *MR_trace_getline_queue(void);
+
+/*  
+** The details of the source server, if any.
+*/
+
+extern  MR_Trace_Source_Server  MR_trace_source_server;
+
+/*
+** Source commands from the given file. Print an error message if the file
+** cannot be read, unless ignore_errors is true.
+*/
+
+extern  MR_bool     MR_trace_source(const char *filename,
+                        MR_bool ignore_errors);
+
+/*
+** Source commands from the given file.
+*/
+
+extern  void        MR_trace_source_from_open_file(FILE *fp);
+
+/*
+** Print a usage message for the currently executing command.
+*/
+
+extern  void    MR_trace_usage_cur_cmd(void);
+
+/*
+** Print a message about this command being a no-op from this port.
+*/
+
+extern  void    MR_trace_do_noop(void);
+
+/*
+** If the given word is the name of a valid command, return its info.
+*/
+
+extern  const MR_Trace_Command_Info
+                *MR_trace_valid_command(const char *word);
+
+/*
+** Close a source server, if there is one attached.
+*/
+
+extern  void    MR_trace_maybe_close_source_window(MR_bool verbose);
+
+/*
 ** This just prints to MR_mdb_out a message telling the user
 ** that the debugger caught an interrupt.
 */
@@ -45,6 +128,9 @@
 extern	char	*MR_trace_get_command(const char *prompt, FILE *mdb_in,
 				FILE *mdb_out);
 
+extern  MR_SavedDebugState
+                MR_saved_debug_state;
+
 /*
 ** If word is a valid command, return information about the
 ** completer for the command.
@@ -58,7 +144,7 @@
 ** A Readline completer for command names.
 */
 
-extern  MR_Completer_List *MR_trace_command_completer(const char *word,
-				size_t word_len);
+extern  MR_Completer_List
+                *MR_trace_command_completer(const char *word, size_t word_len);
 
 #endif	/* MERCURY_TRACE_INTERNAL_H */
Index: trace/mercury_trace_tables.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_tables.c,v
retrieving revision 1.41
diff -u -b -r1.41 mercury_trace_tables.c
--- trace/mercury_trace_tables.c	1 Mar 2006 22:58:51 -0000	1.41
+++ trace/mercury_trace_tables.c	2 Apr 2006 05:56:15 -0000
@@ -775,9 +775,10 @@
     ** Search backwards for the end of the final module qualifier.
     ** There must be at least one character before the qualifier.
     */
+
     while (end > str) {
-        if (*end == ':' || *end == '.' || (*end == '_' && *(end + 1) == '_')) {
-            if (*end  == ':' || *end == '.') {
+        if (*end == '.' || (*end == '_' && *(end + 1) == '_')) {
+            if (*end == '.') {
                 spec->MR_proc_name = end + 1;
             } else {
                 spec->MR_proc_name = end + 2;
@@ -812,6 +813,7 @@
 /*
 ** Convert all occurrences of `__' to `.'.
 */
+
 static void
 MR_translate_double_underscores(char *start)
 {
@@ -1078,6 +1080,11 @@
         data->MR_complete_pf = MR_FUNCTION;
         word += 5;
     } else {
+        /*
+        ** We don't complete on the names of special (unify, index compare,
+        ** or init) predicates.
+        */
+
         data->MR_complete_pf = -1;
     }
 
@@ -1091,21 +1098,19 @@
     data->MR_complete_current_proc= -1;
 
     /*
-    ** Handle the case where the word matches the first part of
-    ** a module name. If the word unambiguously determines the
-    ** module name we want to return module qualified completions
-    ** for all the procedures in that module. Otherwise, we just
-    ** complete on the names of all of the matching modules and
-    ** unqualified procedure names.
+    ** Handle the case where the word matches the first part of a module name.
+    ** If the word unambiguously determines the module name we want to return
+    ** module qualified completions for all the procedures in that module.
+    ** Otherwise, we just complete on the names of all of the matching modules
+    ** and unqualified procedure names.
     **
-    ** For example, given word to complete `f' and modules `foo'
-    ** and `bar', we want to return all the procedures in module
-    ** `foo' as completions, as well as all procedures whose
-    ** unqualified names begin with `f'.
-    ** Given word to complete `foo.' and modules `foo' and `foo.bar'
-    ** we want to return `foo.bar.' and all the procedures in
-    ** module `foo' as completions.
+    ** For example, given word to complete `f' and modules `foo' and `bar',
+    ** we want to return all the procedures in module `foo' as completions,
+    ** as well as all procedures whose unqualified names begin with `f'.
+    ** Given word to complete `foo.' and modules `foo' and `foo.bar' we want to
+    ** return `foo.bar.' and all the procedures in module `foo' as completions.
     */
+
     MR_bsearch(MR_module_info_next, slot, found,
         strncmp(MR_module_infos[slot]->MR_ml_name,
             data->MR_complete_name, data->MR_complete_name_len));
@@ -1157,6 +1162,7 @@
         /*
         ** Move on to the next module.
         */
+
         data->MR_complete_current_module++;
         if (data->MR_complete_current_module >= MR_module_info_next) {
             return NULL;
@@ -1167,6 +1173,7 @@
         ** Complete on the module name if we aren't finding
         ** qualified completions in this module.
         */
+
         module_name = MR_module_infos[data->MR_complete_current_module]
             ->MR_ml_name;
         if (data->MR_complete_word_matches_module == 0 &&
@@ -1194,6 +1201,7 @@
 /*
 ** Set up the completer data for processing a module.
 */
+
 static void
 MR_trace_proc_spec_completer_init_module(MR_Proc_Completer_Data *data)
 {
@@ -1213,6 +1221,7 @@
     ** Work out whether we should find qualified completions
     ** for procedures in this module.
     */
+
     if (MR_strneq(module_name, name, module_name_len)
         && name_len > module_name_len
         && name[module_name_len] == '.'
@@ -1223,6 +1232,7 @@
         ** When searching for qualified completions skip past
         ** the module name and the trailing '.'.
         */
+
         data->MR_complete_word_matches_module = module_name_len + 1;
     } else if (data->MR_complete_current_module ==
         data->MR_unambiguous_matching_module)
@@ -1233,6 +1243,7 @@
         ** matching all procedures, use the empty string as the
         ** name to match against.
         */
+
         data->MR_complete_word_matches_module = name_len;
     } else {
         data->MR_complete_word_matches_module = 0;
@@ -1255,6 +1266,7 @@
 ** Check whether the current procedure matches the word to be completed.
 ** To do: complete on arity and mode number.
 */
+
 static char *
 MR_trace_complete_proc(MR_Proc_Completer_Data *data)
 {
@@ -1298,6 +1310,7 @@
     /*
     ** Move on to the next procedure in the current module.
     */
+
     data->MR_complete_current_proc++;
 
     if (data->MR_complete_word_matches_module != 0
Index: trace/mercury_trace_util.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_util.h,v
retrieving revision 1.14
diff -u -b -r1.14 mercury_trace_util.h
--- trace/mercury_trace_util.h	8 Feb 2006 21:54:34 -0000	1.14
+++ trace/mercury_trace_util.h	3 Apr 2006 11:29:41 -0000
@@ -74,6 +74,7 @@
 ** and false otherwise.  Because builtin_catch creates a stack frame, but no
 ** events, it must be handled specially by some parts of the debugger.
 */
+
 extern	MR_bool	MR_trace_proc_layout_is_builtin_catch(
 			const MR_Proc_Layout *layout);
 
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