[m-dev.] for review: new browser parameters

Mark Anthony BROWN dougl at cs.mu.OZ.AU
Thu Oct 19 03:36:25 AEDT 2000


Hi,

This implements the changes for the browser discussed on this list
recently.  This is for review by Zoltan.

Cheers,
Mark.


Estimated hours taken: 24

Enhance the configuration parameters of the browser.  The browser is now
sensitive to the type of caller (print, browse, or print *) and can have
different settings for each type.  E.g., the default line limit per variable
can be made shorter for `print *' than for `print'.  The browser also allows
different settings for each format.

The browser also accepts an optional format, which overrides the current
setting for the duration of the call.

To make use of these features, mdb has a new `set' command that allows the
settings to be updated in various ways.  The browser version of `set'
still works, although it doesn't yet accept the options that the former does.
Also, `print' and `browse' can now take options that override the default
format.

browser/browser_info.m:
	New module which defines the key browser data structures.  The
	`browser_state' previously used by browse.m has been split into
	two parts: the transient state (browser_info) and the persistent
	state (browser_state).  The persistent state is created when the
	browser is first called, and is saved between calls to the browser,
	whereas a new transient state is created each time the browser is
	called, and lasts for the duration of the call.

	The persistent state contains settings for each possible combination
	of format and caller type.

	This module exports C functions that update the persistent state.

browser/browse.m:
	Move the browser_state into the new module.
	
	Change the interface so that it allows optional format and caller
	type input arguments.  This allows its behaviour to vary depending on
	whether the caller is implementing `print', `browse', or `print *'.
	It also allows the default format to be overridden by options to
	these commands.

	General rearrangement of the browser code to avoid code duplication.
	This addresses the following comment from the module:
	% XXX: could abstract out the code common to the following preds.
	along with other similar problems.

	The code for testing the size of a term and deciding between 
	`io__write' and a depth limited printer has been moved from `print'
	to `portray_flat'.  This allows `print' to be used with formats
	other than flat.

	TODO: allow browser commands to take format options; currently only
	mdb commands can.

browser/declarative_user.m:
	Update this for the changed interfaces.

browser/mdb.m:
	Add the new module.

browser/parse.m:
	Move the definitions of `dir', `setting', and `portray_format'
	to the interface of the new module.

browser/*.m:
tests/debugger/browse_pretty.inp:
tests/debugger/browse_pretty.exp:
	s/clipx/width/g
	s/clipy/lines/g

	The reason for this change is that the names are used in the
	context of all formats, but only verbose format actually clips
	the output, so `clipx' and `clipy' are misleading.

tests/debugger/browser_test.inp:
tests/debugger/browser_test.exp:
	Test the new features.

doc/user_guide.texi:
	Document the new features.

trace/mercury_trace_browse.c:
trace/mercury_trace_browse.h:
	Allow extra arguments for the print and browse functions, to specify
	the format and the caller type (in the case of print).

	Export the function MR_trace_set_browser_param, which calls the
	browser to do the work of mdb's set command.

	Export the types MR_Browse_Caller_Type and MR_Browse_Format, which
	mirror two of the types in the new browser module.

trace/mercury_trace_external.c:
	Update for the change to MR_trace_browse_one: pass `browse' as
	the caller type, and always use the default format.

trace/mercury_trace_internal.c:
	Add functions to parse the format and caller type options.  Update
	the print and browse commands to expect format options.  Add the
	`set' command.

	Replace MR_trace_print_var and MR_trace_browse_var with one function,
	MR_trace_browse_internal.  This function takes the caller type as an
	argument, so there is no need for two functions.

	Remove occurrences of:
	/* XXX should use MR_mdb_in and MR_mdb_out */
	since we already do this.

trace/mercury_trace_vars.c:
trace/mercury_trace_vars.h:
	Change the function type MR_Browser so that it also expects a caller
	type and a format.  These arguments are now required by the browser.
	This means that some of the functions that take an MR_Browser
	argument needed to be updated to also take a caller and/or format,
	so they can pass this on to the browser function when it is called.

Index: browser/browse.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/browse.m,v
retrieving revision 1.15
diff -u -r1.15 browse.m
--- browser/browse.m	2000/08/17 08:06:55	1.15
+++ browser/browse.m	2000/10/18 15:51:13
@@ -21,29 +21,43 @@
 :- interface.
 
 :- import_module io, std_util.
+:- import_module mdb__browser_info.
 
-	% an abstract data type that holds persistent browser settings,
-	% e.g. the maximum print depth
-:- type browser_state.
-
-	% initialize the browser state with default values
-:- pred browse__init_state(browser_state).
-:- mode browse__init_state(out) is det.
-
-	% The interactive term browser.
+	% The interactive term browser.  The caller type will be `browse', and
+	% the default format for the `browse' caller type will be used.
+	%
 :- pred browse__browse(T, io__input_stream, io__output_stream,
 			browser_state, browser_state, io__state, io__state).
 :- mode browse__browse(in, in, in, in, out, di, uo) is det.
 
+	% As above, except that the supplied format will override the default.
+	%
+:- pred browse__browse_format(T, io__input_stream, io__output_stream,
+			portray_format, browser_state, browser_state,
+			io__state, io__state).
+:- mode browse__browse_format(in, in, in, in, in, out, di, uo) is det.
+
+	% The browser interface for the external debugger.  The caller type
+	% will be `browse', and the default format will be used.
+	%
 :- pred browse__browse_external(T, io__input_stream, io__output_stream,
 			browser_state, browser_state, io__state, io__state).
 :- mode browse__browse_external(in, in, in, in, out, di, uo) is det.
 
-	% The non-interactive term browser.
-:- pred browse__print(T, io__output_stream, browser_state,
+	% The non-interactive term browser.  The caller type should be either
+	% `print' or `print_all'.  The default portray format for that
+	% caller type is used.
+	%
+:- pred browse__print(T, io__output_stream, browse_caller_type, browser_state,
 			io__state, io__state).
-:- mode browse__print(in, in, in, di, uo) is det.
+:- mode browse__print(in, in, in, in, di, uo) is det.
 
+	% As above, except that the supplied format will override the default.
+	%
+:- pred browse__print_format(T, io__output_stream, browse_caller_type,
+			portray_format, browser_state, io__state, io__state).
+:- mode browse__print_format(in, in, in, in, in, di, uo) is det.
+
 	% Estimate the total term size, in characters,
 	% We count the number of characters in the functor,
 	% plus two characters for each argument: "(" and ")"
@@ -67,6 +81,7 @@
 
 :- import_module mdb__parse, mdb__util, mdb__frame.
 :- import_module string, list, parser, require, std_util, int, char, pprint.
+:- import_module bool.
 
 %---------------------------------------------------------------------------%
 %
@@ -74,17 +89,16 @@
 % they are used in trace/mercury_trace_browser.c.
 %
 
-:- pragma export(browse__init_state(out),
-	"ML_BROWSE_init_state").
 :- pragma export(browse__browse(in, in, in, in, out, di, uo),
 	"ML_BROWSE_browse").
-:- pragma export(browse__print(in, in, in, di, uo),
-	"ML_BROWSE_print").
-:- pragma export(browse__browser_state_type(out),
-	"ML_BROWSE_browser_state_type").
-
+:- pragma export(browse__browse_format(in, in, in, in, in, out, di, uo),
+	"ML_BROWSE_browse_format").
 :- pragma export(browse__browse_external(in, in, in, in, out, di, uo),
 	"ML_BROWSE_browse_external").
+:- pragma export(browse__print(in, in, in, in, di, uo),
+	"ML_BROWSE_print").
+:- pragma export(browse__print_format(in, in, in, in, in, di, uo),
+	"ML_BROWSE_print_format").
 
 %---------------------------------------------------------------------------%
 % If the term browser is called from the internal debugger, input is
@@ -107,101 +121,38 @@
 	;	external.
 
 %---------------------------------------------------------------------------%
-
-browse__init_state(State) :-
-	% We need to supply an object to initialize the state,
-	% but this object won't be used, since the first call
-	% to browse__browse will overwrite it.  So we just supply
-	% a dummy object -- it doesn't matter what its type or value is.
-	DummyObject = "",
-	type_to_univ(DummyObject, Univ),
-	default_depth(DefaultDepth),
-	MaxTermSize = 10,
-	DefaultFormat = verbose,
-	ClipX = 79,
-	ClipY = 25,
-	State = browser_state(Univ, DefaultDepth, MaxTermSize, [],
-			DefaultFormat, ClipX, ClipY).
-
-
-% return the type_info for a browser_state type
-:- pred browse__browser_state_type(type_desc).
-:- mode browse__browser_state_type(out) is det.
-
-browse__browser_state_type(Type) :-
-	browse__init_state(State),
-	Type = type_of(State).
-
-%---------------------------------------------------------------------------%
 %
 % Non-interactive display
 %
 
-browse__print(Term, OutputStream, State0) -->
-	{ set_term(Term, State0, State) },
-	io__set_output_stream(OutputStream, OldStream),
-	browse__print(State),
-	io__set_output_stream(OldStream, _).
+browse__print(Term, OutputStream, Caller, State) -->
+	browse__print_common(Term, OutputStream, Caller, no, State).
+
+browse__print_format(Term, OutputStream, Caller, Format, State) -->
+	browse__print_common(Term, OutputStream, Caller, yes(Format), State).
 
-:- pred browse__print(browser_state, io__state, io__state).
-:- mode browse__print(in, di, uo) is det.
+:- pred browse__print_common(T, io__output_stream, browse_caller_type,
+		maybe(portray_format), browser_state, io__state, io__state).
+:- mode browse__print_common(in, in, in, in, in, di, uo) is det.
 
-browse__print(State) -->
+browse__print_common(Term, OutputStream, Caller, MaybeFormat, State) -->
+	{ browser_info__init(Term, MaybeFormat, State, Info) },
+	io__set_output_stream(OutputStream, OldStream),
+	{ browser_info__get_format(Info, Caller, MaybeFormat, Format) },
 	%
-	% io__write handles the special cases such as lists,
-	% operators, etc. better, so we prefer to use it if we
-	% can.  However, io__write doesn't have a depth or size limit,
-	% so we need to check the size first; if the term is small
-	% enough, we use io__write (actually io__write_univ), otherwise
-	% we use portray_fmt(..., flat).
+	% We assume that the variable name has been printed on the
+	% first part of the line.  If the format is something other than
+	% `flat', then we need to start on the next line.
 	%
-	{ get_term(State, Univ) },
-	{ max_print_size(MaxSize) },
-	{ term_size_left_from_max(Univ, MaxSize, RemainingSize) },
-	( { RemainingSize >= 0 } ->
-		io__write_univ(Univ),
-		io__nl
-	;
-		portray_fmt(internal, State, flat)
-	).
-
-:- pred browse__print_external(browser_state, io__state, io__state).
-:- mode browse__print_external(in, di, uo) is det.
-
-browse__print_external(State) -->
-	portray_fmt(external, State, flat).
-
-	% The maximum estimated size for which we use `io__write'.
-:- pred max_print_size(int::out) is det.
-max_print_size(60).
-
-	% Estimate the total term size, in characters.
-	% We count the number of characters in the functor,
-	% plus two characters for each argument: "(" and ")"
-	% for the first, and ", " for each of the rest,
-	% plus the sizes of the arguments themselves.
-	% This is only approximate since it doesn't take into
-	% account all the special cases such as operators.
-:- pred term_size(univ::in, int::out) is det.
-term_size(Univ, TotalSize) :-
-	deconstruct(Univ, Functor, Arity, Args),
-	string__length(Functor, FunctorSize),
-	list__map(term_size, Args, ArgSizes),
-	AddSizes = (pred(X::in, Y::in, Z::out) is det :- Z = X + Y),
-	list__foldl(AddSizes, ArgSizes, Arity * 2, TotalArgsSize),
-	TotalSize = TotalArgsSize + FunctorSize.
-
-term_size_left_from_max(Univ, MaxSize, RemainingSize) :-
-	( MaxSize < 0 ->
-		RemainingSize = MaxSize
+	(
+		{ Format = flat }
+	->
+		[]
 	;
-		deconstruct(Univ, Functor, Arity, Args),
-		string__length(Functor, FunctorSize),
-		PrincipalSize = FunctorSize + Arity * 2,
-		MaxArgsSize = MaxSize - PrincipalSize,
-		list__foldl(term_size_left_from_max,
-			Args, MaxArgsSize, RemainingSize)
-	).
+		io__nl
+	),
+	portray(internal, Caller, no, Info),
+	io__set_output_stream(OldStream, _).
 
 %---------------------------------------------------------------------------%
 %
@@ -210,31 +161,40 @@
 
 browse__browse(Object, InputStream, OutputStream, State0, State) -->
 	browse_common(internal, Object, InputStream, OutputStream, 
-		State0, State).
+		no, State0, State).
+
+browse__browse_format(Object, InputStream, OutputStream, Format,
+		State0, State) -->
 
+	browse_common(internal, Object, InputStream, OutputStream,
+		yes(Format), State0, State).
+
 browse__browse_external(Object, InputStream, OutputStream, State0, State) -->
 	browse_common(external, Object, InputStream, OutputStream, 
-		State0, State).
-
+		no, State0, State).
 
 :- pred browse_common(debugger, T, io__input_stream, io__output_stream,
-			browser_state, browser_state, io__state, io__state).
-:- mode browse_common(in, in, in, in, in, out, di, uo) is det.
+		maybe(portray_format), browser_state, browser_state,
+		io__state, io__state).
+:- mode browse_common(in, in, in, in, in, in, out, di, uo) is det.
 
-browse_common(Debugger, Object, InputStream, OutputStream, State0, State) -->
-	{ type_to_univ(Object, Univ) },
-	{ set_term(Univ, State0, State1) },
+browse_common(Debugger, Object, InputStream, OutputStream, MaybeFormat,
+		State0, State) -->
+	
+	{ browser_info__init(Object, MaybeFormat, State0, Info0) },
 	io__set_input_stream(InputStream, OldInputStream),
 	io__set_output_stream(OutputStream, OldOutputStream),
 	% startup_message,
-	browse_main_loop(Debugger, State1, State),
+	browse_main_loop(Debugger, Info0, Info),
 	io__set_input_stream(OldInputStream, _),
-	io__set_output_stream(OldOutputStream, _).
+	io__set_output_stream(OldOutputStream, _),
+	{ State = Info ^ state }.
 
-:- pred browse_main_loop(debugger, browser_state, browser_state, 
-	io__state, io__state).
+:- pred browse_main_loop(debugger, browser_info, browser_info, 
+		io__state, io__state).
 :- mode browse_main_loop(in, in, out, di, uo) is det.
-browse_main_loop(Debugger, State0, State) -->
+
+browse_main_loop(Debugger, Info0, Info) -->
 	(
 		{ Debugger = internal },
 		{ prompt(Prompt) },
@@ -251,10 +211,10 @@
 		;
 			{ Debugger = internal }
 		),
-		{ State = State0 }
+		{ Info = Info0 }
 	;
-		run_command(Debugger, Command, State0, State1),
-		browse_main_loop(Debugger, State1, State)
+		run_command(Debugger, Command, Info0, Info1),
+		browse_main_loop(Debugger, Info1, Info)
 	).
 
 :- pred startup_message(debugger::in, io__state::di, io__state::uo) is det.
@@ -266,71 +226,55 @@
 prompt("browser> ").
 
 
-:- pred run_command(debugger, command, browser_state, browser_state,
-	io__state, io__state).
+:- pred run_command(debugger, command, browser_info, browser_info,
+		io__state, io__state).
 :- mode run_command(in, in, in, out, di, uo) is det.
-run_command(Debugger, Command, State, NewState) -->
+
+run_command(Debugger, Command, Info0, Info) -->
+	% XXX The commands `set', `ls' and `print' should allow the format
+	% to be specified by an option.  In each case we instead pass `no' to
+	% the respective handler.
 	( { Command = unknown } ->
 		write_string_debugger(Debugger, 
 			"Error: unknown command or syntax error.\n"),
 		write_string_debugger(Debugger, "Type \"help\" for help.\n"),
-		{ NewState = State }
+		{ Info = Info0 }
 	; { Command = help } ->
 		help(Debugger),
-		{ NewState = State }
+		{ Info = Info0 }
 	; { Command = set } ->
-		show_settings(Debugger, State),
-		{ NewState = State }
+		show_settings(Debugger, Info0, no),
+		{ Info = Info0 }
 	; { Command = set(Setting) } ->
-		( { Setting = depth(MaxDepth) } ->
-			{ set_depth(MaxDepth, State, NewState) }
-		; { Setting = size(MaxSize) } ->
-			{ set_size(MaxSize, State, NewState) }
-		; { Setting = clipx(X) } ->
-			{ set_clipx(X, State, NewState) }
-		; { Setting = clipy(Y) } ->
-			{ set_clipy(Y, State, NewState) }
-		; { Setting = format(Fmt) } ->
-			{ set_fmt(Fmt, State, NewState) }
-		;
-			write_string_debugger(Debugger, 
-				"error: unknown setting.\n"),
-			{ NewState = State }
-		)
+		{ set_browse_param(Setting, Info0, Info) }
 	; { Command = ls } ->
-		portray(Debugger, State),
-		{ NewState = State }
+		portray(Debugger, browse, no, Info0),
+		{ Info = Info0 }
 	; { Command = ls(Path) } ->
-		portray_path(Debugger, State, Path),
-		{ NewState = State }
+		portray_path(Debugger, browse, no, Info0, Path),
+		{ Info = Info0 }
 	; { Command = cd } ->
-		{ set_path(root_rel([]), State, NewState) }
+		{ set_path(root_rel([]), Info0, Info) }
 	; { Command = cd(Path) } ->
-		{ get_dirs(State, Pwd) },
-		{ get_term(State, Univ) },
-		{ change_dir(Pwd, Path, NewPwd) },
-		( { deref_subterm(Univ, NewPwd, _SubUniv) } ->
-			{ set_path(Path, State, NewState) }
+		{ change_dir(Info0 ^ dirs, Path, NewPwd) },
+		( { deref_subterm(Info0 ^ term, NewPwd, _SubUniv) } ->
+			{ Info = Info0 ^ dirs := NewPwd }
 		;
 			write_string_debugger(Debugger, 
 				"error: cannot change to subterm\n"),
-			{ NewState = State }
+			{ Info = Info0 }
 		)
 	; { Command = print } ->
-		( { Debugger = internal} ->
-			browse__print(State)
-		;
-			browse__print_external(State)
-		),
-		{ NewState = State }
+		portray(Debugger, print, no, Info0),
+		{ Info = Info0 }
 	; { Command = pwd } ->
-		{ get_dirs(State, Path) },
-		write_path(Debugger, Path),
+		write_path(Debugger, Info0 ^ dirs),
 		nl_debugger(Debugger),
-		{ NewState = State }
+		{ Info = Info0 }
 	;	
-		write_string_debugger(Debugger, "command not yet implemented\n"),
-		{ NewState = State }
+		write_string_debugger(Debugger,
+				"command not yet implemented\n"),
+		{ Info = Info0 }
 	),
 	( { Debugger = external } ->
 		send_term_to_socket(browser_end_command)
@@ -338,10 +282,20 @@
 		{ true }
 	).
 
+:- pred set_browse_param(setting, browser_info, browser_info).
+:- mode set_browse_param(in, in, out) is det.
+
+set_browse_param(Setting, Info0, Info) :-
+	%
+	% XXX We can't yet give options to the `set' command.
+	%
+	No = bool__no,
+	browser_info__set_param(No, No, No, No, No, No, Setting, Info0 ^ state,
+			NewState),
+	Info = Info0 ^ state := NewState.
+
 :- pred help(debugger::in, io__state::di, io__state::uo) is det.
 help(Debugger) -->
-	{ default_depth(Default) },
-	{ string__int_to_string(Default, DefaultStr) },
 	{ string__append_list([
 "Commands are:\n",
 "\tls [path]      -- list subterm (expanded)\n",
@@ -353,13 +307,13 @@
 "\tquit           -- quit browser\n",
 "SICStus Prolog style commands are:\n",
 "\tp              -- print\n",
-"\t< [n]          -- set depth (default is ", DefaultStr, ")\n",
+"\t< [n]          -- set depth\n",
 "\t^ [path]       -- cd [path]\n",
 "\t?              -- help\n",
 "\th              -- help\n",
 "\n",
 "-- settings:\n",
-"--    size; depth; path; format (flat pretty verbose); clipx; clipy\n",
+"--    size; depth; path; format (flat pretty verbose); width; lines\n",
 "--    Paths can be Unix-style or SICStus-style: /2/3/1 or ^2^3^1\n",
 "\n"],
 		HelpMessage) },
@@ -370,92 +324,110 @@
 % Various pretty-print routines
 %
 
-:- pred portray(debugger, browser_state, io__state, io__state).
-:- mode portray(in, in, di, uo) is det.
-portray(Debugger, State) -->
-	{ get_fmt(State, Fmt) },
+:- pred portray(debugger, browse_caller_type, maybe(portray_format),
+		browser_info, io__state, io__state).
+:- mode portray(in, in, in, in, di, uo) is det.
+
+portray(Debugger, Caller, MaybeFormat, Info) -->
+	{ browser_info__get_format(Info, Caller, MaybeFormat, Format) },
+	{ browser_info__get_format_params(Info, Caller, Format, Params) },
 	(
-		{ Fmt = flat },
-		portray_flat(Debugger, State)
-	;
-		{ Fmt = pretty },
-		portray_pretty(Debugger, State)
+		{ deref_subterm(Info ^ term, Info ^ dirs, SubUniv) }
+	->
+		(
+			{ Format = flat },
+			portray_flat(Debugger, SubUniv, Params)
+		;
+			{ Format = pretty },
+			portray_pretty(Debugger, SubUniv, Params)
+		;
+			{ Format = verbose },
+			portray_verbose(Debugger, SubUniv, Params)
+		)
 	;
-		{ Fmt = verbose },
-		portray_verbose(Debugger, State)
-	).
+		write_string_debugger(Debugger, "error: no such subterm")
+	),
+	nl_debugger(Debugger).
 
 
-:- pred portray_path(debugger, browser_state, path, io__state, io__state).
-:- mode portray_path(in, in, in, di, uo) is det.
-portray_path(Debugger, State, Path) -->
-	{ set_path(Path, State, NewState) },
-	portray(Debugger, NewState).
+:- pred portray_path(debugger, browse_caller_type, maybe(portray_format),
+		browser_info, path, io__state, io__state).
+:- mode portray_path(in, in, in, in, in, di, uo) is det.
+
+portray_path(Debugger, Caller, MaybeFormat, Info0, Path) -->
+	{ set_path(Path, Info0, Info) },
+	portray(Debugger, Caller, MaybeFormat, Info).
 
-:- pred portray_fmt(debugger, browser_state, portray_format, 
-	io__state, io__state).
-:- mode portray_fmt(in, in, in, di, uo) is det.
-portray_fmt(Debugger, State, Format) -->
-	(
-		{ Format = flat },
-		portray_flat(Debugger, State)
-	;
-		{ Format = pretty },
-		portray_pretty(Debugger, State)
+:- pred portray_flat(debugger, univ, format_params, io__state, io__state).
+:- mode portray_flat(in, in, in, di, uo) is det.
+
+portray_flat(Debugger, Univ, Params) -->
+	%
+	% io__write handles the special cases such as lists,
+	% operators, etc. better, so we prefer to use it if we
+	% can.  However, io__write doesn't have a depth or size limit,
+	% so we need to check the size first; if the term is small
+	% enough, we use io__write (actually io__write_univ), otherwise
+	% we use term_to_string/4.
+	%
+	% XXX this ignores the maximum number of lines
+	%
+	{ max_print_size(MaxSize) },
+	{ term_size_left_from_max(Univ, MaxSize, RemainingSize) },
+	( { RemainingSize >= 0 } ->
+		io__write_univ(Univ)
 	;
-		{ Format = verbose },
-		portray_verbose(Debugger, State)
+		{ term_to_string(Univ, Params ^ size, Params ^ depth, Str) },
+		write_string_debugger(Debugger, Str)
 	).
 
-	% XXX: could abstract out the code common to the following preds.
-:- pred portray_flat(debugger, browser_state, io__state, io__state).
-:- mode portray_flat(in, in, di, uo) is det.
-portray_flat(Debugger, State) -->
-	{ get_term(State, Univ) },
-	{ get_size(State, MaxSize) },
-	{ get_depth(State, MaxDepth) },
-	{ get_dirs(State, Dir) },
-	( { deref_subterm(Univ, Dir, SubUniv) } ->
-		{ term_to_string(SubUniv, MaxSize, MaxDepth, Str) },
-		write_string_debugger(Debugger, Str)
-	;
-		write_string_debugger(Debugger, "error: no such subterm")
-	),
-	nl_debugger(Debugger).
+:- pred portray_verbose(debugger, univ, format_params, io__state, io__state).
+:- mode portray_verbose(in, in, in, di, uo) is det.
 
-:- pred portray_verbose(debugger, browser_state, io__state, io__state).
-:- mode portray_verbose(in, in, di, uo) is det.
-portray_verbose(Debugger, State) -->
-	{ get_size(State, MaxSize) },
-	{ get_depth(State, MaxDepth) },
-	{ get_term(State, Univ) },
-	{ get_dirs(State, Dir) },
-	{ get_clipx(State, X) },
-	{ get_clipy(State, Y) },
-	( { deref_subterm(Univ, Dir, SubUniv) } ->
-		{ term_to_string_verbose(SubUniv, MaxSize,
-			MaxDepth, X, Y, Str) },
-		write_string_debugger(Debugger, Str)
-	;
-		write_string_debugger(Debugger, "error: no such subterm")
-	),
-	nl_debugger(Debugger).
+portray_verbose(Debugger, Univ, Params) -->
+	{ term_to_string_verbose(Univ, Params ^ size, Params ^ depth,
+			Params ^ width, Params ^ lines, Str) },
+	write_string_debugger(Debugger, Str).
+
+:- pred portray_pretty(debugger, univ, format_params, io__state, io__state).
+:- mode portray_pretty(in, in, in, di, uo) is det.
+
+portray_pretty(Debugger, Univ, Params) -->
+	{ term_to_string_pretty(Univ, Params ^ width, Params ^ depth, Str) },
+	write_string_debugger(Debugger, Str).
 
 
-:- pred portray_pretty(debugger, browser_state, io__state, io__state).
-:- mode portray_pretty(in, in, di, uo) is det.
-portray_pretty(Debugger, State) -->
-	{ get_clipx(State, Width) },
-	{ get_depth(State, MaxDepth) },
-	{ get_term(State, Univ) },
-	{ get_dirs(State, Dir) },
-	( { deref_subterm(Univ, Dir, SubUniv) } ->
-		{ term_to_string_pretty(SubUniv, Width, MaxDepth, Str) },
-		write_string_debugger(Debugger, Str)
+	% The maximum estimated size for which we use `io__write'.
+:- pred max_print_size(int::out) is det.
+max_print_size(60).
+
+	% Estimate the total term size, in characters.
+	% We count the number of characters in the functor,
+	% plus two characters for each argument: "(" and ")"
+	% for the first, and ", " for each of the rest,
+	% plus the sizes of the arguments themselves.
+	% This is only approximate since it doesn't take into
+	% account all the special cases such as operators.
+:- pred term_size(univ::in, int::out) is det.
+term_size(Univ, TotalSize) :-
+	deconstruct(Univ, Functor, Arity, Args),
+	string__length(Functor, FunctorSize),
+	list__map(term_size, Args, ArgSizes),
+	AddSizes = (pred(X::in, Y::in, Z::out) is det :- Z = X + Y),
+	list__foldl(AddSizes, ArgSizes, Arity * 2, TotalArgsSize),
+	TotalSize = TotalArgsSize + FunctorSize.
+
+term_size_left_from_max(Univ, MaxSize, RemainingSize) :-
+	( MaxSize < 0 ->
+		RemainingSize = MaxSize
 	;
-		write_string_debugger(Debugger, "error: no such subterm")
-	),
-	nl_debugger(Debugger).
+		deconstruct(Univ, Functor, Arity, Args),
+		string__length(Functor, FunctorSize),
+		PrincipalSize = FunctorSize + Arity * 2,
+		MaxArgsSize = MaxSize - PrincipalSize,
+		list__foldl(term_size_left_from_max,
+			Args, MaxArgsSize, RemainingSize)
+	).
 
 %---------------------------------------------------------------------------%
 %
@@ -716,86 +688,16 @@
 	).
 
 %---------------------------------------------------------------------------%
-%
-% The definition of the browser_state type and its access routines.
-%
 
-:- type browser_state
-	--->	browser_state(
-			univ,	% term to browse (as univ)
-			int,	% depth of tree
-			int,	% max nodes printed
-			list(dir),	% root rel `present working directory'
-			portray_format,	% format for ls.
-			int,	% X clipping for verbose display
-			int	% Y clipping for verbose display
-		).
-
-	% access predicates
-
-:- pred get_term(browser_state, univ).
-:- mode get_term(in, out) is det.
-get_term(browser_state(Univ, _Depth, _Size, _Path, _Fmt, _X, _Y), Univ).
-
-:- pred get_depth(browser_state, int).
-:- mode get_depth(in, out) is det.
-get_depth(browser_state(_Univ, Depth, _Size, _Path, _Fmt, _X, _Y), Depth).
-
-:- pred get_size(browser_state, int).
-:- mode get_size(in, out) is det.
-get_size(browser_state(_Univ, _Depth, Size, _Path, _Fmt, _X, _Y), Size).
-
-:- pred get_clipx(browser_state, int).
-:- mode get_clipx(in, out) is det.
-get_clipx(browser_state(_Univ, _Depth, _Size, _Path, _Fmt, X, _Y), X).
-
-:- pred get_clipy(browser_state, int).
-:- mode get_clipy(in, out) is det.
-get_clipy(browser_state(_Univ, _Depth, _Size, _Path, _Fmt, _X, Y), Y).
-
-:- pred get_dirs(browser_state, list(dir)).
-:- mode get_dirs(in, out) is det.
-get_dirs(browser_state(_Univ, _Depth, _Size, Dirs, _Fmt, _X, _Y), Dirs).
-
-:- pred get_path(browser_state, path).
+:- pred get_path(browser_info, path).
 :- mode get_path(in, out) is det.
-get_path(browser_state(_Univ, _Depth, _Size, Dirs, _Fmt, _X, _Y),
-	root_rel(Dirs)).
-
-:- pred get_fmt(browser_state, portray_format).
-:- mode get_fmt(in, out) is det.
-get_fmt(browser_state(_Univ, _Depth, _Size, _Path, Fmt, _X, _Y), Fmt).
-
-:- pred set_depth(int, browser_state, browser_state).
-:- mode set_depth(in, in, out) is det.
-set_depth(NewMaxDepth, State, NewState) :-
-	State = browser_state(Univ, _MaxDepth, MaxSize, Dirs, Fmt, X, Y),
-	NewState = browser_state(Univ, NewMaxDepth, MaxSize, Dirs, Fmt, X, Y).
-
-:- pred set_size(int, browser_state, browser_state).
-:- mode set_size(in, in, out) is det.
-set_size(NewMaxSize, State, NewState) :-
-	State = browser_state(Univ, MaxDepth, _MaxSize, Dirs, Fmt, X, Y),
-	NewState = browser_state(Univ, MaxDepth, NewMaxSize, Dirs, Fmt, X, Y).
-
-:- pred set_clipx(int, browser_state, browser_state).
-:- mode set_clipx(in, in, out) is det.
-set_clipx(NewX, State, NewState) :-
-	State = browser_state(Univ, MaxDepth, MaxSize, Dirs, Fmt, _X, Y),
-	NewState = browser_state(Univ, MaxDepth, MaxSize, Dirs, Fmt, NewX, Y).
-
-:- pred set_clipy(int, browser_state, browser_state).
-:- mode set_clipy(in, in, out) is det.
-set_clipy(NewY, State, NewState) :-
-	State = browser_state(Univ, MaxDepth, MaxSize, Dirs, Fmt, X, _Y),
-	NewState = browser_state(Univ, MaxDepth, MaxSize, Dirs, Fmt, X, NewY).
+get_path(Info, root_rel(Info ^ dirs)).
 
-:- pred set_path(path, browser_state, browser_state).
+:- pred set_path(path, browser_info, browser_info).
 :- mode set_path(in, in, out) is det.
-set_path(NewPath, State, NewState) :-
-	State = browser_state(Univ, MaxDepth, MaxSize, Dirs, Fmt, X, Y),
-	change_dir(Dirs, NewPath, NewDirs),
-	NewState = browser_state(Univ, MaxDepth, MaxSize, NewDirs, Fmt, X, Y).
+set_path(NewPath, Info0, Info) :-
+	change_dir(Info0 ^ dirs, NewPath, NewDirs),
+	Info = Info0 ^ dirs := NewDirs.
 
 :- pred change_dir(list(dir), path, list(dir)).
 :- mode change_dir(in, in, out) is det.
@@ -809,50 +711,53 @@
 	),
 	simplify_dirs(NewDirs, RootRelDirs).
 
-:- pred set_fmt(portray_format, browser_state, browser_state).
-:- mode set_fmt(in, in, out) is det.
-set_fmt(NewFmt, browser_state(Univ, Depth, Size, Path, _OldFmt, X, Y),
-	browser_state(Univ, Depth, Size, Path, NewFmt, X, Y)).
-
-:- pred set_term(T, browser_state, browser_state).
+:- pred set_term(T, browser_info, browser_info).
 :- mode set_term(in, in, out) is det.
-set_term(Term, State0, State) :-
+set_term(Term, Info0, Info) :-
 	type_to_univ(Term, Univ),
-	set_univ(Univ, State0, State1),
+	set_univ(Univ, Info0, Info1),
 	% Display from the root term.
 	% This avoid errors due to dereferencing non-existent subterms.
-	set_path(root_rel([]), State1, State).
+	set_path(root_rel([]), Info1, Info).
 
-:- pred set_univ(univ, browser_state, browser_state).
+:- pred set_univ(univ, browser_info, browser_info).
 :- mode set_univ(in, in, out) is det.
-set_univ(NewUniv, browser_state(_OldUniv, Dep, Siz, Path, Fmt, X, Y),
-	browser_state(NewUniv, Dep, Siz, Path, Fmt, X, Y)).
+set_univ(NewUniv, Info, Info ^ term := NewUniv).
 
 %---------------------------------------------------------------------------%
 %
 % Display predicates.
 %
 
-:- pred show_settings(debugger, browser_state, io__state, io__state).
-:- mode show_settings(in, in, di, uo) is det.
-show_settings(Debugger, State) -->
-	{ State = browser_state(_Univ, MaxDepth, MaxSize,
-		CurPath, Fmt, X, Y) },
+:- pred show_settings(debugger, browser_info, maybe(portray_format),
+		io__state, io__state).
+:- mode show_settings(in, in, in, di, uo) is det.
+
+show_settings(Debugger, Info, MaybeFormat) -->
+	{ browser_info__get_format(Info, browse, MaybeFormat, Format) },
+	{ browser_info__get_format_params(Info, browse, Format, Params) },
 	write_string_debugger(Debugger, "Max depth is: "), 
-		write_int_debugger(Debugger, MaxDepth), 
+		write_int_debugger(Debugger, Params ^ depth), 
 		nl_debugger(Debugger),
 	write_string_debugger(Debugger, "Max size is: "), 
-		write_int_debugger(Debugger, MaxSize), 
+		write_int_debugger(Debugger, Params ^ size), 
 		nl_debugger(Debugger),
 	write_string_debugger(Debugger, "X clip is: "), 
-		write_int_debugger(Debugger, X), 
+		write_int_debugger(Debugger, Params ^ width), 
 		nl_debugger(Debugger),
 	write_string_debugger(Debugger, "Y clip is: "), 
-		write_int_debugger(Debugger, Y), nl_debugger(Debugger),
+		write_int_debugger(Debugger, Params ^ lines),
+		nl_debugger(Debugger),
 	write_string_debugger(Debugger, "Current path is: "),
-		write_path(Debugger, CurPath), nl_debugger(Debugger),
+		write_path(Debugger, Info ^ dirs),
+		nl_debugger(Debugger),
+	{ browser_info__get_format(Info, browse, no, LsFormat) },
+	write_string_debugger(Debugger, "Ls format is "),
+		print_format_debugger(Debugger, LsFormat),
+		nl_debugger(Debugger),
+	{ browser_info__get_format(Info, print, no, PrintFormat) },
 	write_string_debugger(Debugger, "Print format is "),
-		print_format_debugger(Debugger, Fmt),
+		print_format_debugger(Debugger, PrintFormat),
 		nl_debugger(Debugger).
 
 :- pred string_to_path(string, path).
Index: browser/declarative_user.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/declarative_user.m,v
retrieving revision 1.11
diff -u -r1.11 declarative_user.m
--- browser/declarative_user.m	2000/10/01 03:13:40	1.11
+++ browser/declarative_user.m	2000/10/18 15:51:18
@@ -45,7 +45,8 @@
 %-----------------------------------------------------------------------------%
 
 :- implementation.
-:- import_module mdb__declarative_execution, mdb__browse, mdb__util.
+:- import_module mdb__browser_info, mdb__browse, mdb__util.
+:- import_module mdb__declarative_execution.
 :- import_module std_util, char, string, bool, int.
 
 :- type user_state
@@ -56,7 +57,7 @@
 		).
 
 user_state_init(InStr, OutStr, User) :-
-	browse__init_state(Browser),
+	browser_info__init_state(Browser),
 	User = user(InStr, OutStr, Browser).
 
 %-----------------------------------------------------------------------------%
@@ -433,7 +434,7 @@
 
 print_decl_atom_arg(User, yes(Arg)) -->
 	io__write_string(User^outstr, "\t"),
-	browse__print(univ_value(Arg), User^outstr, User^browser).
+	browse__print(univ_value(Arg), User^outstr, print_all, User^browser).
 print_decl_atom_arg(User, no) -->
 	io__write_string(User^outstr, "\t_\n").
 
Index: browser/mdb.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/mdb.m,v
retrieving revision 1.3
diff -u -r1.3 mdb.m
--- browser/mdb.m	2000/10/16 01:33:23	1.3
+++ browser/mdb.m	2000/10/18 15:51:19
@@ -12,7 +12,7 @@
 
 	% These interface modules are used directly by the test programs
 	% or the libmer_trace library.
-:- include_module browse, help.
+:- include_module browser_info, browse, help.
 :- include_module interactive_query.
 :- include_module debugger_interface, collect_lib.
 :- include_module declarative_debugger, declarative_execution.
Index: browser/parse.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/parse.m,v
retrieving revision 1.8
diff -u -r1.8 parse.m
--- browser/parse.m	2000/08/26 04:33:54	1.8
+++ browser/parse.m	2000/10/18 15:51:22
@@ -63,7 +63,8 @@
 
 :- interface.
 
-:- import_module io, list, string.
+:- import_module io, string, list.
+:- import_module mdb__browser_info.
 
 :- type command
 	--->	ls(path)
@@ -85,22 +86,6 @@
 	--->	root_rel(list(dir))
 	;	dot_rel(list(dir)).
 
-:- type dir
-	--->	parent
-	;	child(int).
-
-:- type setting
-	--->	depth(int)
-	;	size(int)
-	;	format(portray_format)
-	;	clipx(int)
-	;	clipy(int)
-	.
-
-:- type portray_format
-	--->	flat
-	;	pretty
-	;	verbose.
 
 % If the term browser is called from the external debugger, the term browser
 % commands are send through the socket via terms of type external_request.
@@ -119,7 +104,7 @@
 %---------------------------------------------------------------------------%
 :- implementation.
 
-:- import_module char, int, std_util.
+:- import_module list, char, int, std_util.
 :- import_module mdb__util.
 
 
@@ -346,12 +331,12 @@
 	; Tok = name("size") ->
 		Toks = [num(Size)],
 		Setting = size(Size)
-	; Tok = name("clipx") ->
+	; Tok = name("width") ->
 		Toks = [num(X)],
-		Setting = clipx(X)
-	; Tok = name("clipy") ->
+		Setting = width(X)
+	; Tok = name("lines") ->
 		Toks = [num(Y)],
-		Setting = clipy(Y)
+		Setting = lines(Y)
 	; Tok = name("format") ->
 		Toks = [Fmt],
 		( Fmt = name("flat") ->
@@ -434,12 +419,12 @@
 	io__write_string("size "),
 	io__write_int(Size),
 	io__nl.
-show_setting(clipx(X)) -->
-	io__write_string("clipx "),
+show_setting(width(X)) -->
+	io__write_string("width "),
 	io__write_int(X),
 	io__nl.
-show_setting(clipy(Y)) -->
-	io__write_string("clipy "),
+show_setting(lines(Y)) -->
+	io__write_string("lines "),
 	io__write_int(Y),
 	io__nl.
 show_setting(format(Fmt)) -->
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.224
diff -u -r1.224 user_guide.texi
--- doc/user_guide.texi	2000/10/16 02:09:33	1.224
+++ doc/user_guide.texi	2000/10/18 15:52:22
@@ -1967,25 +1967,34 @@
 Prints the names of all the known variables in the current environment,
 together with an ordinal number for each variable.
 @sp 1
- at item print @var{name}
- at itemx print @var{num}
+ at item print [-fpv] @var{name}
+ at itemx print [-fpv] @var{num}
 Prints the value of the variable in the current environment
 with the given name, or with the given ordinal number.
 This is a non-interactive version of the @samp{browse}
 command (see below).  Various settings
 which affect the way that terms are printed out
 (including e.g. the maximum term depth) can be set using
-the @samp{set} command in the browser.
+the @samp{set} command.
 @sp 1
- at item print *
+The options @samp{-f} or @samp{--flat}, @samp{-p} or @samp{--pretty},
+and @samp{-v} or @samp{--verbose} specify the format to use for printing.
+ at sp 1
+ at item print [-fpv] *
 Prints the values of all the known variables in the current environment.
+ at sp 1
+The options @samp{-f} or @samp{--flat}, @samp{-p} or @samp{--pretty},
+and @samp{-v} or @samp{--verbose} specify the format to use for printing.
 @sp 1
- at item print exception
+ at item print [-fpv] exception
 Prints the value of the exception at an EXCP port.
 Reports an error if the current event does not refer to such a port.
+ at sp 1
+The options @samp{-f} or @samp{--flat}, @samp{-p} or @samp{--pretty},
+and @samp{-v} or @samp{--verbose} specify the format to use for printing.
 @sp 1
- at item browse @var{name}
- at itemx browse @var{num}
+ at item browse [-fpv] @var{name}
+ at itemx browse [-fpv] @var{num}
 Invokes an interactive term browser to browse the value of the
 variable in the current environment with the given ordinal number or
 with the given name.
@@ -1997,15 +2006,21 @@
 The displayed terms may also be clipped to fit
 within a single screen.
 @sp 1
+The options @samp{-f} or @samp{--flat}, @samp{-p} or @samp{--pretty},
+and @samp{-v} or @samp{--verbose} specify the format to use for browsing.
+ at sp 1
 For further documentation on the interactive term browser,
 invoke the @samp{browse} command from within @samp{mdb} and then
 type @samp{help} at the @samp{browser>} prompt.
 @sp 1
- at item browse exception
+ at item browse [-fpv] exception
 Invokes the interactive term browser to browse
 the value of the exception at an EXCP port.
 Reports an error if the current event does not refer to such a port.
 @sp 1
+The options @samp{-f} or @samp{--flat}, @samp{-p} or @samp{--pretty},
+and @samp{-v} or @samp{--verbose} specify the format to use for browsing.
+ at sp 1
 @item stack [-d]
 Prints the names of the ancestors of the call
 specified by the current event.
@@ -2076,6 +2091,49 @@
 This is useful if the details of the event,
 which were printed when control arrived at the event,
 have since scrolled off the screen.
+ at sp 1
+ at item set [-APBfpv] @var{param} @var{value}
+Updates the configuration parameters of the browser.
+The parameters that can be configured are
+ at samp{format}, @samp{depth}, @samp{size}, @samp{width} and @samp{lines}.
+ 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.
+ at sp 1
+ at item
+ at samp{size} is the suggested maximum number of functors to display.
+Beyond this limit, the browser will abbreviate the output.
+ 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 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.
+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.
 @end table
 @sp 1
 @node Breakpoint commands
Index: tests/debugger/browse_pretty.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/browse_pretty.exp,v
retrieving revision 1.2
diff -u -r1.2 browse_pretty.exp
--- tests/debugger/browse_pretty.exp	2000/05/26 07:03:37	1.2
+++ tests/debugger/browse_pretty.exp	2000/10/18 15:52:30
@@ -19,7 +19,7 @@
       big(small, .(1, .(2, .(3, .(4, .(5, []))))), small)), 
     .(1, .(2, .(3, .(4, .(5, .(6, [])))))), 
     small))
-browser> set clipx 131
+browser> set width 131
 browser> ls
 big(
   big(big(small, .(1, []), small), .(1, .(2, [])), small), 
@@ -28,7 +28,7 @@
     big(small, .(1, .(2, .(3, .(4, [])))), big(small, .(1, .(2, .(3, .(4, .(5, []))))), small)), 
     .(1, .(2, .(3, .(4, .(5, .(6, [])))))), 
     small))
-browser> set clipx 30
+browser> set width 30
 browser> ls
 big(
   big(
@@ -73,7 +73,7 @@
               5, 
               .(6, [])))))), 
     small))
-browser> set clipx 10
+browser> set width 10
 browser> ls
 big(
   big(
@@ -136,7 +136,7 @@
                 6, 
                 [])))))), 
     small))
-browser> set clipx 79
+browser> set width 79
 browser> set depth 3
 browser> ls
 big(
Index: tests/debugger/browse_pretty.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/browse_pretty.inp,v
retrieving revision 1.1
diff -u -r1.1 browse_pretty.inp
--- tests/debugger/browse_pretty.inp	2000/05/22 06:46:13	1.1
+++ tests/debugger/browse_pretty.inp	2000/10/18 15:52:30
@@ -5,13 +5,13 @@
 set format pretty
 set depth 10
 ls
-set clipx 131
+set width 131
 ls
-set clipx 30
+set width 30
 ls
-set clipx 10
+set width 10
 ls
-set clipx 79
+set width 79
 set depth 3
 ls
 quit
Index: tests/debugger/browser_test.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/browser_test.exp,v
retrieving revision 1.8
diff -u -r1.8 browser_test.exp
--- tests/debugger/browser_test.exp	2000/08/26 04:34:18	1.8
+++ tests/debugger/browser_test.exp	2000/10/18 15:52:30
@@ -3,12 +3,38 @@
 Command echo enabled.
 mdb> goto 3
        3:      2  2 EXIT pred browser_test:big_data/1-0 (det) browser_test.m:18 (browser_test.m:12)
+mdb> set format pretty
 mdb> print *
+       HeadVar__1             	
+big(
+  big(big(small, 1, small), 2, small), 
+  3, 
+  big(big(small, 4, big/3), 6, small))
+mdb> set -A format verbose
+mdb> print *
+       HeadVar__1             	
+big
+1-big
+| 1-big
+| | 1-small
+| | 2-1
+
+mdb> browse 1; ls; quit
+big(
+  big(big(small, 1, small), 2, small), 
+  3, 
+  big(big(small, 4, big(small, 5, small)), 6, small))
+mdb> set -AP format flat
+mdb> print -f 1
        HeadVar__1             	big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
-mdb> browse 1; print; quit
-big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
-mdb> browse HeadVar__1
-browser> ls
+mdb> print -p 1
+       HeadVar__1             	
+big(
+  big(big(small, 1, small), 2, small), 
+  3, 
+  big(big(small, 4, big/3), 6, small))
+mdb> print -v 1
+       HeadVar__1             	
 big
 1-big
 | 1-big
@@ -26,57 +52,46 @@
   2-6
   3-small
 
+mdb> print --xyzzy 1
+print: unrecognized option `--xyzzy'
+mdb: print: usage error -- type `help print' for help.
+mdb> browse 1; print; quit
+big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
+mdb> browse -f 1; ls; quit
+big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big(small, 5, small)), 6, small))
+mdb> browse HeadVar__1
+browser> ls
+big(
+  big(big(small, 1, small), 2, small), 
+  3, 
+  big(big(small, 4, big(small, 5, small)), 6, small))
 browser> cd /1
 browser> ls
-big
-1-big
-| 1-small
-| 2-1
-| 3-small
-2-2
-3-small
-
+big(big(small, 1, small), 2, small)
 browser> cd /1/2
 browser> ls
 2
-
 browser> cd /3
 browser> ls
-big
-1-big
-| 1-small
-| 2-4
-| 3-big
-|   1-small
-|   2-5
-|   3-small
-2-6
-3-small
-
+big(big(small, 4, big(small, 5, small)), 6, small)
 browser> cd 1/3/2
 browser> ls
 5
-
 browser> cd
 browser> ls
-big
-1-big
-| 1-big
-| | 1-small
-| | 2-1
-| | 3-small
-| 2-2
-| 3-small
-2-3
-3-big
-  1-big
-  | 1-small
-  | 2-4
-  | 3-big/3
-  2-6
-  3-small
-
+big(
+  big(big(small, 1, small), 2, small), 
+  3, 
+  big(big(small, 4, big(small, 5, small)), 6, small))
 browser> quit
+mdb> set -A -f depth 1
+mdb> print *
+       HeadVar__1             	big(big/3, 3, big/3)
+mdb> print HeadVar__1/1
+       HeadVar__1             	big(big(small, 1, small), 2, small)
+mdb> set -f depth 3
+mdb> print 1
+       HeadVar__1             	big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
 mdb> print HeadVar__1/1/2
        HeadVar__1             	2
 mdb> print 1^1^2^3
Index: tests/debugger/browser_test.exp2
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/browser_test.exp2,v
retrieving revision 1.9
diff -u -r1.9 browser_test.exp2
--- tests/debugger/browser_test.exp2	2000/08/26 04:34:19	1.9
+++ tests/debugger/browser_test.exp2	2000/10/18 15:52:30
@@ -3,12 +3,38 @@
 Command echo enabled.
 mdb> goto 3
        3:      2  2 EXIT pred browser_test:big_data/1-0 (det) browser_test.m:18 (browser_test.m:12)
+mdb> set format pretty
 mdb> print *
+       HeadVar__1             	
+big(
+  big(big(small, 1, small), 2, small), 
+  3, 
+  big(big(small, 4, big/3), 6, small))
+mdb> set -A format verbose
+mdb> print *
+       HeadVar__1             	
+big
+1-big
+| 1-big
+| | 1-small
+| | 2-1
+
+mdb> browse 1; ls; quit
+big(
+  big(big(small, 1, small), 2, small), 
+  3, 
+  big(big(small, 4, big(small, 5, small)), 6, small))
+mdb> set -AP format flat
+mdb> print -f 1
        HeadVar__1             	big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
-mdb> browse 1; print; quit
-big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
-mdb> browse HeadVar__1
-browser> ls
+mdb> print -p 1
+       HeadVar__1             	
+big(
+  big(big(small, 1, small), 2, small), 
+  3, 
+  big(big(small, 4, big/3), 6, small))
+mdb> print -v 1
+       HeadVar__1             	
 big
 1-big
 | 1-big
@@ -26,57 +52,46 @@
   2-6
   3-small
 
+mdb> print --xyzzy 1
+print: unrecognized option `--xyzzy'
+mdb: print: usage error -- type `help print' for help.
+mdb> browse 1; print; quit
+big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
+mdb> browse -f 1; ls; quit
+big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big(small, 5, small)), 6, small))
+mdb> browse HeadVar__1
+browser> ls
+big(
+  big(big(small, 1, small), 2, small), 
+  3, 
+  big(big(small, 4, big(small, 5, small)), 6, small))
 browser> cd /1
 browser> ls
-big
-1-big
-| 1-small
-| 2-1
-| 3-small
-2-2
-3-small
-
+big(big(small, 1, small), 2, small)
 browser> cd /1/2
 browser> ls
 2
-
 browser> cd /3
 browser> ls
-big
-1-big
-| 1-small
-| 2-4
-| 3-big
-|   1-small
-|   2-5
-|   3-small
-2-6
-3-small
-
+big(big(small, 4, big(small, 5, small)), 6, small)
 browser> cd 1/3/2
 browser> ls
 5
-
 browser> cd
 browser> ls
-big
-1-big
-| 1-big
-| | 1-small
-| | 2-1
-| | 3-small
-| 2-2
-| 3-small
-2-3
-3-big
-  1-big
-  | 1-small
-  | 2-4
-  | 3-big/3
-  2-6
-  3-small
-
+big(
+  big(big(small, 1, small), 2, small), 
+  3, 
+  big(big(small, 4, big(small, 5, small)), 6, small))
 browser> quit
+mdb> set -A -f depth 1
+mdb> print *
+       HeadVar__1             	big(big/3, 3, big/3)
+mdb> print HeadVar__1/1
+       HeadVar__1             	big(big(small, 1, small), 2, small)
+mdb> set -f depth 3
+mdb> print 1
+       HeadVar__1             	big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big/3), 6, small))
 mdb> print HeadVar__1/1/2
        HeadVar__1             	2
 mdb> print 1^1^2^3
Index: tests/debugger/browser_test.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/browser_test.inp,v
retrieving revision 1.4
diff -u -r1.4 browser_test.inp
--- tests/debugger/browser_test.inp	2000/08/26 04:34:19	1.4
+++ tests/debugger/browser_test.inp	2000/10/18 15:52:30
@@ -1,7 +1,17 @@
 echo on
 goto 3
+set format pretty
 print *
+set -A format verbose
+print *
+browse 1; ls; quit
+set -AP format flat
+print -f 1
+print -p 1
+print -v 1
+print --xyzzy 1
 browse 1; print; quit
+browse -f 1; ls; quit
 browse HeadVar__1
 ls
 cd /1
@@ -15,6 +25,11 @@
 cd
 ls
 quit
+set -A -f depth 1
+print *
+print HeadVar__1/1
+set -f depth 3
+print 1
 print HeadVar__1/1/2
 print 1^1^2^3
 retry
Index: tests/debugger/mdb_command_test.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/mdb_command_test.inp,v
retrieving revision 1.11
diff -u -r1.11 mdb_command_test.inp
--- tests/debugger/mdb_command_test.inp	2000/09/01 00:50:25	1.11
+++ tests/debugger/mdb_command_test.inp	2000/10/18 15:52:31
@@ -20,6 +20,7 @@
 down                 xyzzy xyzzy xyzzy xyzzy xyzzy
 level                xyzzy xyzzy xyzzy xyzzy xyzzy
 current              xyzzy xyzzy xyzzy xyzzy xyzzy
+set                  xyzzy xyzzy xyzzy xyzzy xyzzy
 break                xyzzy xyzzy xyzzy xyzzy xyzzy
 disable              xyzzy xyzzy xyzzy xyzzy xyzzy
 enable               xyzzy xyzzy xyzzy xyzzy xyzzy
Index: trace/mercury_trace_browse.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_browse.c,v
retrieving revision 1.16
diff -u -r1.16 mercury_trace_browse.c
--- trace/mercury_trace_browse.c	2000/10/16 23:07:47	1.16
+++ trace/mercury_trace_browse.c	2000/10/18 15:52:57
@@ -30,6 +30,7 @@
 #include "mercury_trace_external.h"
 
 #include "mdb.browse.h"
+#include "mdb.browser_info.h"
 #include "mdb.interactive_query.h"
 #ifdef MR_HIGHLEVEL_CODE
   #include "mercury.std_util.h"
@@ -44,6 +45,9 @@
 
 static	void		MR_trace_browse_ensure_init(void);
 
+static	bool		MR_trace_is_portray_format(const char *str,
+				MR_Browse_Format *format);
+
 static void
 MR_c_file_to_mercury_file(FILE *c_file, MercuryFile *mercury_file)
 {
@@ -51,7 +55,7 @@
 }
 
 void
-MR_trace_browse(MR_Word type_info, MR_Word value)
+MR_trace_browse(MR_Word type_info, MR_Word value, MR_Browse_Format format)
 {
 	MercuryFile mdb_in, mdb_out;
 
@@ -59,13 +63,23 @@
 
 	MR_c_file_to_mercury_file(MR_mdb_in, &mdb_in);
 	MR_c_file_to_mercury_file(MR_mdb_out, &mdb_out);
-
-	MR_TRACE_CALL_MERCURY(
-		ML_BROWSE_browse(type_info, value,
-			(MR_Word) &mdb_in, (MR_Word) &mdb_out,
-			MR_trace_browser_state, &MR_trace_browser_state);
-	);
 
+	if (format != MR_BROWSE_DEFAULT_FORMAT) {
+		MR_TRACE_CALL_MERCURY(
+			ML_BROWSE_browse_format(type_info, value,
+				(MR_Word) &mdb_in, (MR_Word) &mdb_out,
+				(MR_Word) format,
+				MR_trace_browser_state,
+				&MR_trace_browser_state);
+		);
+	} else {
+		MR_TRACE_CALL_MERCURY(
+			ML_BROWSE_browse(type_info, value,
+				(MR_Word) &mdb_in, (MR_Word) &mdb_out,
+				MR_trace_browser_state,
+				&MR_trace_browser_state);
+		);
+	}
 	MR_trace_browser_state = MR_make_permanent(MR_trace_browser_state,
 			MR_trace_browser_state_type);
 }
@@ -80,7 +94,8 @@
 #ifdef MR_USE_EXTERNAL_DEBUGGER
 
 void
-MR_trace_browse_external(MR_Word type_info, MR_Word value)
+MR_trace_browse_external(MR_Word type_info, MR_Word value,
+		MR_Browse_Caller_Type caller, MR_Browse_Format format)
 {
 	MR_trace_browse_ensure_init();
 
@@ -97,7 +112,8 @@
 #endif
 
 void
-MR_trace_print(MR_Word type_info, MR_Word value)
+MR_trace_print(MR_Word type_info, MR_Word value, MR_Browse_Caller_Type caller,
+		MR_Browse_Format format)
 {
 	MercuryFile mdb_out;
 
@@ -105,10 +121,103 @@
 
 	MR_c_file_to_mercury_file(MR_mdb_out, &mdb_out);
 
-	MR_TRACE_CALL_MERCURY(
-		ML_BROWSE_print(type_info, value, (MR_Word) &mdb_out,
-			MR_trace_browser_state);
-	);
+	if (format != MR_BROWSE_DEFAULT_FORMAT) {
+		MR_TRACE_CALL_MERCURY(
+			ML_BROWSE_print_format(type_info, value,
+				(MR_Word) &mdb_out, (MR_Word) caller,
+				(MR_Word) format, MR_trace_browser_state);
+		);
+	} else {
+		MR_TRACE_CALL_MERCURY(
+			ML_BROWSE_print(type_info, value,
+				(MR_Word) &mdb_out, (MR_Word) caller,
+				MR_trace_browser_state);
+		);
+	}
+}
+
+bool
+MR_trace_set_browser_param(MR_Bool print, MR_Bool browse, MR_Bool print_all,
+		MR_Bool flat, MR_Bool pretty, MR_Bool verbose,
+		const char *param, const char *value)
+{
+	int			depth, size, width, lines;
+	MR_Browse_Format	new_format;
+
+	MR_trace_browse_ensure_init();
+
+	if (streq(param, "depth") && MR_trace_is_number(value, &depth))
+	{
+		MR_TRACE_CALL_MERCURY(
+			ML_BROWSE_set_param_depth(print, browse, print_all,
+				flat, pretty, verbose, depth,
+				MR_trace_browser_state,
+				&MR_trace_browser_state);
+		);
+	}
+	else if (streq(param, "size") && MR_trace_is_number(value, &size))
+	{
+		MR_TRACE_CALL_MERCURY(
+			ML_BROWSE_set_param_size(print, browse, print_all,
+				flat, pretty, verbose, size,
+				MR_trace_browser_state,
+				&MR_trace_browser_state);
+		);
+	}
+	else if (streq(param, "format") &&
+			MR_trace_is_portray_format(value, &new_format))
+	{
+		MR_TRACE_CALL_MERCURY(
+			ML_BROWSE_set_param_format(print, browse, print_all,
+				new_format, MR_trace_browser_state,
+				&MR_trace_browser_state);
+		);
+	}
+	else if (streq(param, "width") && MR_trace_is_number(value, &width))
+	{
+		MR_TRACE_CALL_MERCURY(
+			ML_BROWSE_set_param_width(print, browse, print_all,
+				flat, pretty, verbose, width,
+				MR_trace_browser_state,
+				&MR_trace_browser_state);
+		);
+	}
+	else if (streq(param, "lines") && MR_trace_is_number(value, &lines))
+	{
+		MR_TRACE_CALL_MERCURY(
+			ML_BROWSE_set_param_lines(print, browse, print_all,
+				flat, pretty, verbose, lines,
+				MR_trace_browser_state,
+				&MR_trace_browser_state);
+		);
+	}
+	else
+	{
+		return FALSE;
+	}
+
+	MR_trace_browser_state = MR_make_permanent(MR_trace_browser_state,
+				MR_trace_browser_state_type);
+	return TRUE;
+}
+
+static bool
+MR_trace_is_portray_format(const char *str, MR_Browse_Format *format)
+{
+	*format = MR_BROWSE_DEFAULT_FORMAT;
+
+	if (streq(str, "flat")) {
+		*format = MR_BROWSE_FORMAT_FLAT;
+		return TRUE;
+	} else if (streq(str, "pretty")) {
+		*format = MR_BROWSE_FORMAT_PRETTY;
+		return TRUE;
+	} else if (streq(str, "verbose")) {
+		*format = MR_BROWSE_FORMAT_VERBOSE;
+		return TRUE;
+	}
+
+	return FALSE;
 }
 
 static void
@@ -123,13 +232,11 @@
 			ML_get_type_info_for_type_info(&typeinfo_type_word);
 			ML_BROWSE_browser_state_type(
 				&MR_trace_browser_state_type_word);
-			MR_trace_browser_state_type = (MR_TypeInfo)
-				MR_trace_browser_state_type_word;
 			ML_BROWSE_init_state(&MR_trace_browser_state);
 		);
 
 		MR_trace_browser_state_type = (MR_TypeInfo) MR_make_permanent(
-					(MR_Word) MR_trace_browser_state_type,
+					MR_trace_browser_state_type_word,
 					(MR_TypeInfo) typeinfo_type_word);
 		MR_trace_browser_state = MR_make_permanent(
 					MR_trace_browser_state,
Index: trace/mercury_trace_browse.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_browse.h,v
retrieving revision 1.8
diff -u -r1.8 mercury_trace_browse.h
--- trace/mercury_trace_browse.h	2000/08/03 06:19:24	1.8
+++ trace/mercury_trace_browse.h	2000/10/18 15:52:57
@@ -18,18 +18,48 @@
 #include "mercury_types.h"	/* for MR_Word, MR_String */
 
 /*
+** The following types must correspond with browse_caller_type and
+** portray_format in browser/browser_info.m.
+*/
+typedef enum {
+	MR_BROWSE_CALLER_PRINT,
+	MR_BROWSE_CALLER_BROWSE,
+	MR_BROWSE_CALLER_PRINT_ALL
+} MR_Browse_Caller_Type;
+
+typedef enum {
+	MR_BROWSE_FORMAT_FLAT,
+	MR_BROWSE_FORMAT_PRETTY,
+	MR_BROWSE_FORMAT_VERBOSE
+} MR_Browse_Format;
+
+/*
+** This value must be different from any of the MR_BROWSE_FORMAT_* values.
+*/
+#define MR_BROWSE_DEFAULT_FORMAT	-1
+
+/*
 ** Interactively browse a term.
 */
-extern 	void	MR_trace_browse(MR_Word type_info, MR_Word value);
+extern 	void	MR_trace_browse(MR_Word type_info, MR_Word value,
+			MR_Browse_Format format);
 #ifdef MR_USE_EXTERNAL_DEBUGGER
-extern 	void	MR_trace_browse_external(MR_Word type_info, MR_Word value);
+extern 	void	MR_trace_browse_external(MR_Word type_info, MR_Word value,
+			MR_Browse_Caller_Type caller, MR_Browse_Format format);
 #endif
 
 /*
 ** Display a term (non-interactively).
 */
-extern	void	MR_trace_print(MR_Word type_info, MR_Word value);
+extern	void	MR_trace_print(MR_Word type_info, MR_Word value,
+			MR_Browse_Caller_Type caller, MR_Browse_Format format);
 
+/*
+** Set browser parameters.
+*/
+extern	bool	MR_trace_set_browser_param(MR_Bool print, MR_Bool browse,
+			MR_Bool print_all, MR_Bool flat, MR_Bool pretty,
+			MR_Bool verbose, const char *param, const char *value);
 
 /*
 ** Invoke an interactive query.
Index: trace/mercury_trace_external.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_external.c,v
retrieving revision 1.44
diff -u -r1.44 mercury_trace_external.c
--- trace/mercury_trace_external.c	2000/10/16 01:34:11	1.44
+++ trace/mercury_trace_external.c	2000/10/18 15:53:12
@@ -1460,6 +1460,7 @@
 	const char	*problem;
 
 	problem = MR_trace_browse_one(NULL, var_spec, MR_trace_browse_external,
+			MR_BROWSE_CALLER_BROWSE, MR_BROWSE_DEFAULT_FORMAT,
 			TRUE);
 
 	if (problem != NULL) {
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.84
diff -u -r1.84 mercury_trace_internal.c
--- trace/mercury_trace_internal.c	2000/10/16 01:34:12	1.84
+++ trace/mercury_trace_internal.c	2000/10/18 15:53:35
@@ -170,15 +170,24 @@
 			int *word_count, const char *cat, const char *item);
 static	bool	MR_trace_options_confirmed(bool *confirmed, char ***words,
 			int *word_count, const char *cat, const char *item);
+static	bool	MR_trace_options_format(MR_Browse_Format *format,
+			char ***words, int *word_count, const char *cat,
+			const char *item);
+static	bool	MR_trace_options_param_set(MR_Bool *print_set,
+			MR_Bool *browse_set, MR_Bool *print_all_set,
+			MR_Bool *flat_format, MR_Bool *pretty_format,
+			MR_Bool *verbose_format, char ***words,
+			int *word_count, const char *cat, const char *item);
 static	void	MR_trace_usage(const char *cat, const char *item);
 static	void	MR_trace_do_noop(void);
 
 static	void	MR_trace_set_level_and_report(int ancestor_level,
 			bool detailed);
-static	void	MR_trace_print_var(MR_Word type_info, MR_Word value);
-static	void	MR_trace_browse_var(MR_Word type_info, MR_Word value);
+static	void	MR_trace_browse_internal(MR_Word type_info, MR_Word value,
+			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_Browser browser, 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,
@@ -416,23 +425,31 @@
 }
 
 static void
-MR_trace_print_var(MR_Word type_info, MR_Word value)
+MR_trace_browse_internal(MR_Word type_info, MR_Word value,
+		MR_Browse_Caller_Type caller, MR_Browse_Format format)
 {
-	fprintf(MR_mdb_out, "\t");
-	fflush(MR_mdb_out);
-	/* XXX should use MR_mdb_out */
-	MR_trace_print(type_info, value);
-}
+	switch (caller) {
+		
+		case MR_BROWSE_CALLER_BROWSE:
+			MR_trace_browse(type_info, value, format);
+			break;
 
-static void
-MR_trace_browse_var(MR_Word type_info, MR_Word value)
-{
-	/* XXX should use MR_mdb_in and MR_mdb_out */
-	MR_trace_browse(type_info, value);
+		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");
+	}
 }
 
 static const char *
-MR_trace_browse_exception(MR_Event_Info *event_info, MR_Browser browser)
+MR_trace_browse_exception(MR_Event_Info *event_info, MR_Browser browser,
+		MR_Browse_Caller_Type caller, MR_Browse_Format format)
 {
 	MR_Word		type_info;
 	MR_Word		value;
@@ -450,7 +467,7 @@
 	type_info = MR_field(MR_mktag(0), exception, UNIV_OFFSET_FOR_TYPEINFO);
 	value = MR_field(MR_mktag(0), exception, UNIV_OFFSET_FOR_DATA);
 
-	(*browser)(type_info, value);
+	(*browser)(type_info, value, caller, format);
 
 	return (const char *) NULL;
 }
@@ -957,18 +974,26 @@
 			MR_trace_usage("browsing", "vars");
 		}
 	} else if (streq(words[0], "print")) {
-		if (word_count == 2) {
+		MR_Browse_Format	format;
+
+		if (! MR_trace_options_format(&format, &words, &word_count,
+					"browsing", "print"))
+		{
+			; /* the usage message has already been printed */
+		} else if (word_count == 2) {
 			const char	*problem;
 
 			if (streq(words[1], "*")) {
 				problem = MR_trace_browse_all(MR_mdb_out,
-					MR_trace_print_var);
+					MR_trace_browse_internal, format);
 			} else if (streq(words[1], "exception")) {
 				problem = MR_trace_browse_exception(event_info,
-					MR_trace_print_var);
+					MR_trace_browse_internal,
+					MR_BROWSE_CALLER_PRINT, format);
 			} else {
 				problem = MR_trace_parse_browse_one(MR_mdb_out,
-					words[1], MR_trace_print_var, FALSE);
+					words[1], MR_trace_browse_internal,
+					MR_BROWSE_CALLER_PRINT, format, FALSE);
 			}
 
 			if (problem != NULL) {
@@ -979,15 +1004,23 @@
 			MR_trace_usage("browsing", "print");
 		}
 	} else if (streq(words[0], "browse")) {
-		if (word_count == 2) {
+		MR_Browse_Format	format;
+
+		if (! MR_trace_options_format(&format, &words, &word_count,
+					"browsing", "browse"))
+		{
+			; /* the usage message has already been printed */
+		} else if (word_count == 2) {
 			const char	*problem;
 
 			if (streq(words[1], "exception")) {
 				problem = MR_trace_browse_exception(event_info,
-					MR_trace_browse_var);
+					MR_trace_browse_internal,
+					MR_BROWSE_CALLER_BROWSE, format);
 			} else {
 				problem = MR_trace_parse_browse_one(NULL,
-					words[1], MR_trace_browse_var, TRUE);
+					words[1], MR_trace_browse_internal,
+					MR_BROWSE_CALLER_BROWSE, format, TRUE);
 			}
 
 			if (problem != NULL) {
@@ -1028,6 +1061,30 @@
 		} else {
 			MR_trace_usage("browsing", "current");
 		}
+	} else if (streq(words[0], "set")) {
+		MR_Browse_Format	format;
+		MR_Bool			print_set;
+		MR_Bool			browse_set;
+		MR_Bool			print_all_set;
+		MR_Bool			flat_format;
+		MR_Bool			pretty_format;
+		MR_Bool			verbose_format;
+
+		if (! MR_trace_options_param_set(&print_set, &browse_set,
+				&print_all_set, &flat_format, &pretty_format,
+				&verbose_format, &words, &word_count,
+				"browsing", "set"))
+		{
+			; /* 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,
+					pretty_format, verbose_format,
+					words[1], words[2]))
+		{
+			MR_trace_usage("browsing", "set");
+		}
 	} else if (streq(words[0], "break")) {
 		MR_Proc_Spec	spec;
 		MR_Spy_When	when;
@@ -1684,9 +1741,11 @@
 			fprintf(MR_mdb_out,
 				"current procedure has no body info\n");
 		} else {
-			MR_trace_print_var(
+			MR_trace_browse_internal(
 				(MR_Word) &mercury_data_mdb__program_representation__type_ctor_info_goal_rep_0,
-				entry->MR_sle_proc_rep);
+				entry->MR_sle_proc_rep,
+				MR_BROWSE_CALLER_PRINT,
+				MR_BROWSE_DEFAULT_FORMAT);
 		}
 #ifdef	MR_TRACE_HISTOGRAM
 	} else if (streq(words[0], "histogram_all")) {
@@ -2209,6 +2268,117 @@
 	return TRUE;
 }
 
+static struct MR_option MR_trace_format_opts[] = 
+{
+	{ "flat",	FALSE,	NULL,	'f' },
+	{ "pretty",	FALSE,	NULL,	'p' },
+	{ "verbose",	FALSE,	NULL,	'v' },
+	{ NULL,		FALSE,	NULL,	0 }
+};
+
+static bool
+MR_trace_options_format(MR_Browse_Format *format, char ***words,
+	int *word_count, const char *cat, const char *item)
+{
+	int	c;
+
+	*format = MR_BROWSE_DEFAULT_FORMAT;
+	MR_optind = 0;
+	while ((c = MR_getopt_long(*word_count, *words, "fpv",
+			MR_trace_format_opts, NULL)) != EOF)
+	{
+		switch (c) {
+
+			case 'f':
+				*format = MR_BROWSE_FORMAT_FLAT;
+				break;
+
+			case 'p':
+				*format = MR_BROWSE_FORMAT_PRETTY;
+				break;
+
+			case 'v':
+				*format = MR_BROWSE_FORMAT_VERBOSE;
+				break;
+
+			default:
+				MR_trace_usage(cat, item);
+				return FALSE;
+		}
+	}
+
+	*words = *words + MR_optind - 1;
+	*word_count = *word_count - MR_optind + 1;
+	return TRUE;
+}
+
+static struct MR_option MR_trace_param_set_opts[] = 
+{
+	{ "flat",	FALSE,	NULL,	'f' },
+	{ "pretty",	FALSE,	NULL,	'p' },
+	{ "verbose",	FALSE,	NULL,	'v' },
+	{ "print",	FALSE,	NULL,	'P' },
+	{ "browse",	FALSE,	NULL,	'B' },
+	{ "print-all",	FALSE,	NULL,	'A' },
+	{ NULL,		FALSE,	NULL,	0 }
+};
+
+static bool
+MR_trace_options_param_set(MR_Bool *print_set, MR_Bool *browse_set,
+	MR_Bool *print_all_set, MR_Bool *flat_format, MR_Bool *pretty_format,
+	MR_Bool *verbose_format, char ***words, int *word_count,
+	const char *cat, const char *item)
+{
+	int	c;
+
+	*print_set = FALSE;
+	*browse_set = FALSE;
+	*print_all_set = FALSE;
+	*flat_format = FALSE;
+	*pretty_format = FALSE;
+	*verbose_format = FALSE;
+
+	MR_optind = 0;
+	while ((c = MR_getopt_long(*word_count, *words, "PBAfpv",
+			MR_trace_param_set_opts, NULL)) != EOF)
+	{
+		switch (c) {
+
+			case 'f':
+				*flat_format = TRUE;
+				break;
+
+			case 'p':
+				*pretty_format = TRUE;
+				break;
+
+			case 'v':
+				*verbose_format = TRUE;
+				break;
+
+			case 'P':
+				*print_set = TRUE;
+				break;
+
+			case 'B':
+				*browse_set = TRUE;
+				break;
+
+			case 'A':
+				*print_all_set = TRUE;
+				break;
+
+			default:
+				MR_trace_usage(cat, item);
+				return FALSE;
+		}
+	}
+
+	*words = *words + MR_optind - 1;
+	*word_count = *word_count - MR_optind + 1;
+	return TRUE;
+}
+
 static void
 MR_trace_usage(const char *cat, const char *item)
 /* cat is unused now, but could be used later */
@@ -2738,6 +2908,7 @@
 	{ "browsing", "down" },
 	{ "browsing", "level" },
 	{ "browsing", "current" },
+	{ "browsing", "set" },
 	{ "breakpoint", "break" },
 	{ "breakpoint", "enable" },
 	{ "breakpoint", "disable" },
Index: trace/mercury_trace_vars.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_vars.c,v
retrieving revision 1.22
diff -u -r1.22 mercury_trace_vars.c
--- trace/mercury_trace_vars.c	2000/09/22 06:00:04	1.22
+++ trace/mercury_trace_vars.c	2000/10/18 15:53:43
@@ -111,10 +111,14 @@
 static	int		MR_trace_compare_var_details(const void *arg1,
 				const void *arg2);
 static	const char *	MR_trace_browse_one_path(FILE *out,
-			MR_Var_Spec var_spec, char *path, MR_Browser browser,
-			bool must_be_unique);
+				MR_Var_Spec var_spec, char *path,
+				MR_Browser browser,
+				MR_Browse_Caller_Type caller,
+				MR_Browse_Format format, bool must_be_unique);
 static	char *		MR_trace_browse_var(FILE *out, MR_Var_Details *var,
-				char *path, MR_Browser browser);
+				char *path, MR_Browser browser,
+				MR_Browse_Caller_Type caller,
+				MR_Browse_Format format);
 static	const char *	MR_trace_bad_path(const char *path);
 static	int		MR_trace_print_var_name(FILE *out, MR_Var_Details *var);
 static	const char *	MR_trace_valid_var_number(int var_number);
@@ -644,6 +648,7 @@
 
 const char *
 MR_trace_parse_browse_one(FILE *out, char *word_spec, MR_Browser browser,
+	MR_Browse_Caller_Type caller, MR_Browse_Format format,
 	bool must_be_unique)
 {
 	MR_Var_Spec	var_spec;
@@ -684,26 +689,28 @@
 		var_spec.MR_var_spec_kind = MR_VAR_SPEC_NUMBER;
 		var_spec.MR_var_spec_number = n;
 		return MR_trace_browse_one_path(out, var_spec, path,
-			browser, must_be_unique);
+			browser, caller, format, must_be_unique);
 	} else {
 		var_spec.MR_var_spec_kind = MR_VAR_SPEC_NAME;
 		var_spec.MR_var_spec_name = word_spec;
 		return MR_trace_browse_one_path(out, var_spec, path,
-			browser, must_be_unique);
+			browser, caller, format, must_be_unique);
 	}
 }
 
 const char *
 MR_trace_browse_one(FILE *out, MR_Var_Spec var_spec, MR_Browser browser,
+	MR_Browse_Caller_Type caller, MR_Browse_Format format,
 	bool must_be_unique)
 {
 	return MR_trace_browse_one_path(out, var_spec, NULL, browser,
-		must_be_unique);
+		caller, format, must_be_unique);
 }
 
 static const char *
 MR_trace_browse_one_path(FILE *out, MR_Var_Spec var_spec, char *path,
-	MR_Browser browser, bool must_be_unique)
+	MR_Browser browser, MR_Browse_Caller_Type caller,
+	MR_Browse_Format format, bool must_be_unique)
 {
 	int		i;
 	bool		found;
@@ -726,7 +733,7 @@
 		varno = var_spec.MR_var_spec_number - 1;
 		bad_path = MR_trace_browse_var(out,
 				&MR_point.MR_point_vars[varno],
-				path, browser);
+				path, browser, caller, format);
 		if (bad_path != NULL) {
 			return MR_trace_bad_path(bad_path);
 		}
@@ -756,7 +763,7 @@
 			do {
 				bad_path = MR_trace_browse_var(out,
 					&MR_point.MR_point_vars[i], path,
-					browser);
+					browser, caller, format);
 
 				if (bad_path == NULL) {
 					success_count++;
@@ -773,7 +780,7 @@
 		} else {
 			bad_path = MR_trace_browse_var(out,
 				&MR_point.MR_point_vars[i], path,
-				browser);
+				browser, caller, format);
 			if (bad_path != NULL) {
 				return MR_trace_bad_path(bad_path);
 			}
@@ -806,7 +813,7 @@
 }
 
 const char *
-MR_trace_browse_all(FILE *out, MR_Browser browser)
+MR_trace_browse_all(FILE *out, MR_Browser browser, MR_Browse_Format format)
 {
 	int				i;
 
@@ -820,7 +827,7 @@
 
 	for (i = 0; i < MR_point.MR_point_var_count; i++) {
 		(void) MR_trace_browse_var(out, &MR_point.MR_point_vars[i],
-			NULL, browser);
+			NULL, browser, MR_BROWSE_CALLER_PRINT_ALL, format);
 	}
 
 	return NULL;
@@ -832,7 +839,8 @@
 
 static char *
 MR_trace_browse_var(FILE *out, MR_Var_Details *var, char *path,
-	MR_Browser browser)
+	MR_Browser browser, MR_Browse_Caller_Type caller,
+	MR_Browse_Format format)
 {
 	MR_TypeInfo	typeinfo;
 	MR_TypeInfo	new_typeinfo;
@@ -892,7 +900,7 @@
 		fflush(out);
 	}
 
-	(*browser)((MR_Word) typeinfo, *value);
+	(*browser)((MR_Word) typeinfo, *value, caller, format);
 	return NULL;
 }
 
Index: trace/mercury_trace_vars.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_vars.h,v
retrieving revision 1.9
diff -u -r1.9 mercury_trace_vars.h
--- trace/mercury_trace_vars.h	2000/08/03 06:19:31	1.9
+++ trace/mercury_trace_vars.h	2000/10/18 15:53:44
@@ -38,8 +38,10 @@
 #include <stdio.h>
 #include "mercury_types.h"
 #include "mercury_stack_layout.h"
+#include "mercury_trace_browse.h"
 
-typedef	void	(*MR_Browser)(MR_Word type_info, MR_Word value);
+typedef	void	(*MR_Browser)(MR_Word type_info, MR_Word value,
+			MR_Browse_Caller_Type caller, MR_Browse_Format format);
 
 typedef	enum {
 	MR_VAR_SPEC_NUMBER,
@@ -106,7 +108,9 @@
 */
 
 extern	const char	*MR_trace_parse_browse_one(FILE *out, char *word_spec,
-				MR_Browser browser, bool must_be_unique);
+				MR_Browser browser,
+				MR_Browse_Caller_Type caller,
+				MR_Browse_Format format, bool must_be_unique);
 
 /*
 ** Print the (names and) values of the specified variables.
@@ -117,7 +121,9 @@
 */
 
 extern	const char	*MR_trace_browse_one(FILE *out, MR_Var_Spec var_spec,
-				MR_Browser browser, bool must_be_unique);
+				MR_Browser browser,
+				MR_Browse_Caller_Type caller,
+				MR_Browse_Format format, bool must_be_unique);
 
 /*
 ** Print the list of the names and values of all variables live at the current
@@ -126,6 +132,7 @@
 ** printed by calling the given browser function on them.
 */
 
-extern	const char 	*MR_trace_browse_all(FILE *out, MR_Browser browser);
+extern	const char 	*MR_trace_browse_all(FILE *out, MR_Browser browser,
+				MR_Browse_Format format);
 
 #endif	/* MERCURY_TRACE_VARS_H */


New file: browser/browser_info.m:

%---------------------------------------------------------------------------%
% Copyright (C) 2000 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.
%---------------------------------------------------------------------------%
%
% File: browser_info.m
% Main author: Mark Brown
%
% Basic data structures used by the browser.
%

:- module mdb__browser_info.

:- interface.
:- import_module bool, list, std_util.

	% The non-persistent browser information.  A new one of these is
	% created every time the browser is called, based on the contents
	% of the persistent state, and lasts for the duration of the call.
	%
:- type browser_info
	--->	browser_info(
			term	:: univ,		% Term to browse.
			dirs	:: list(dir),		% Root rel `present
							% working directory'.
			format	:: maybe(portray_format),
							% Format specified as
							% an option to the mdb
							% command.
			state	:: browser_state	% Persistent settings.
		).

:- type dir
	--->	parent
	;	child(int).

	% The browser is required to behave differently for different
	% caller circumstances.  The following type enumerates the
	% various possibilities.
	%
:- type browse_caller_type
	--->	print		% Non-interactively called via mdb's `print'
				% command, to print a single value.
	;	browse		% Interactively called via mdb's `browse'
				% command.
	;	print_all.	% Non-interactively called via mdb's `print *'
				% command, to print one of a sequence of
				% values.

	% The various ways of representing terms by the browser.
	%
:- type portray_format
	--->	flat
	;	pretty
	;	verbose.

:- type format_params
	--->	format_params(
			depth	:: int,
			size	:: int,
			width	:: int,
			lines	:: int
		).

:- type setting
	--->	depth(int)
	;	size(int)
	;	format(portray_format)
	;	width(int)
	;	lines(int)
	.

	% Initialise a new browser_info.  The optional portray_format
	% overrides the default format.
	%
:- pred browser_info__init(T, maybe(portray_format), browser_state,
		browser_info).
:- mode browser_info__init(in, in, in, out) is det.

	% Get the format to use for the given caller type.  The optional
	% portray_format overrides the current default.
	%
:- pred browser_info__get_format(browser_info, browse_caller_type,
		maybe(portray_format), portray_format).
:- mode browser_info__get_format(in, in, in, out) is det.

	% Get the format parameters for the given caller type and format.
	%
:- pred browser_info__get_format_params(browser_info, browse_caller_type,
		portray_format, format_params).
:- mode browser_info__get_format_params(in, in, in, out) is det.

%---------------------------------------------------------------------------%

	% An abstract data type that holds persistent browser settings.
	% This state must be saved by the caller of the browse module
	% between calls.
	%
:- type browser_state.

	% Initialize the persistent browser state with default values.
	%
:- pred browser_info__init_state(browser_state).
:- mode browser_info__init_state(out) is det.

	% Update a setting in the browser state.  The first six arguments
	% indicate the presence of the `set' options -P, -B, -A, -f, -p,
	% and -v, in that order.
	%
:- pred browser_info__set_param(bool, bool, bool, bool, bool, bool, setting,
		browser_state, browser_state).
:- mode browser_info__set_param(in, in, in, in, in, in, in, in, out) is det.

%---------------------------------------------------------------------------%

:- implementation.
:- import_module require.

:- pragma export(browser_info__init_state(out), "ML_BROWSE_init_state").

	%
	% The following exported predicates are a convenient way to
	% call browser_info__set_param from C code.
	%

:- pred set_param_depth(bool, bool, bool, bool, bool, bool, int,
		browser_state, browser_state).
:- mode set_param_depth(in, in, in, in, in, in, in, in, out) is det.
:- pragma export(set_param_depth(in, in, in, in, in, in, in, in, out),
		"ML_BROWSE_set_param_depth").

set_param_depth(P, B, A, F, Pr, V, Depth) -->
	browser_info__set_param(P, B, A, F, Pr, V, depth(Depth)).

:- pred set_param_size(bool, bool, bool, bool, bool, bool, int,
		browser_state, browser_state).
:- mode set_param_size(in, in, in, in, in, in, in, in, out) is det.
:- pragma export(set_param_size(in, in, in, in, in, in, in, in, out),
		"ML_BROWSE_set_param_size").

set_param_size(P, B, A, F, Pr, V, Size) -->
	browser_info__set_param(P, B, A, F, Pr, V, size(Size)).

:- pred set_param_width(bool, bool, bool, bool, bool, bool, int,
		browser_state, browser_state).
:- mode set_param_width(in, in, in, in, in, in, in, in, out) is det.
:- pragma export(set_param_width(in, in, in, in, in, in, in, in, out),
		"ML_BROWSE_set_param_width").

set_param_width(P, B, A, F, Pr, V, Width) -->
	browser_info__set_param(P, B, A, F, Pr, V, width(Width)).

:- pred set_param_lines(bool, bool, bool, bool, bool, bool, int,
		browser_state, browser_state).
:- mode set_param_lines(in, in, in, in, in, in, in, in, out) is det.
:- pragma export(set_param_lines(in, in, in, in, in, in, in, in, out),
		"ML_BROWSE_set_param_lines").

set_param_lines(P, B, A, F, Pr, V, Lines) -->
	browser_info__set_param(P, B, A, F, Pr, V, lines(Lines)).

:- pred set_param_format(bool, bool, bool, portray_format, browser_state,
		browser_state).
:- mode set_param_format(in, in, in, in, in, out) is det.
:- pragma export(set_param_format(in, in, in, in, in, out),
		"ML_BROWSE_set_param_format").

set_param_format(P, B, A, Format) -->
	%
	% Any format flags are ignored for this parameter.
	%
	browser_info__set_param(P, B, A, no, no, no, format(Format)).

%---------------------------------------------------------------------------%

browser_info__init(Term, MaybeFormat, State, Info) :-
	Info = browser_info(univ(Term), [], MaybeFormat, State).

browser_info__get_format(Info, Caller, MaybeFormat, Format) :-
	(
		MaybeFormat = yes(Format)
	;
		MaybeFormat = no,
		Override = Info ^ format,
		(
			Override = yes(Format)
		;
			Override = no,
			get_caller_params(Info ^ state, Caller, Params),
			Format = Params ^ default_format
		)
	).

browser_info__get_format_params(Info, Caller, Format, Params) :-
	get_caller_params(Info ^ state, Caller, CallerParams),
	get_caller_format_params(CallerParams, Format, Params).

%---------------------------------------------------------------------------%

:- type browser_state
	--->	browser_state(
			print_params		:: caller_params,
			browse_params		:: caller_params,
			print_all_params	:: caller_params
		).

:- type caller_params
	--->	caller_params(
			default_format		:: portray_format,
			flat_params		:: format_params,
			pretty_params		:: format_params,
			verbose_params		:: format_params
		).

	% Initialise the persistent settings with default values.  The
	% rationale for the default values is:
	% 	Depth and Size:
	%		For non-interactive display, these are 3 and 10 resp.,
	%		so that terms will generally fit on one line.  For
	%		interactive browsing these values are increased.
	%
	%	Width:
	%		Defaults to 80 characters in any situation.
	%
	%	Lines:
	%		If one term is printed then it is limited to 25 lines.
	%		If there can be more than one term (i.e., with
	%		`print *') then a much lower limit is imposed.  For
	%		verbose format, there is not much point setting this to
	%		less than about 5 since otherwise very little of the
	%		term will be shown.
	%
browser_info__init_state(browser_state(Print, Browse, PrintAll)) :-
	caller_type_print_defaults(Print),
	caller_type_browse_defaults(Browse),
	caller_type_print_all_defaults(PrintAll).

:- pred caller_type_print_defaults(caller_params).
:- mode caller_type_print_defaults(out) is det.

caller_type_print_defaults(Params) :-
	DefaultFormat = flat,
	Flat	= format_params(3, 10, 80, 25),
	Pretty	= format_params(3, 10, 80, 25),
	Verbose	= format_params(3, 10, 80, 25),
	Params	= caller_params(DefaultFormat, Flat, Pretty, Verbose).

:- pred caller_type_browse_defaults(caller_params).
:- mode caller_type_browse_defaults(out) is det.

caller_type_browse_defaults(Params) :-
	DefaultFormat = verbose,
	Flat	= format_params(10, 30, 80, 25),
	Pretty	= format_params(10, 30, 80, 25),
	Verbose	= format_params(10, 30, 80, 25),
	Params	= caller_params(DefaultFormat, Flat, Pretty, Verbose).

:- pred caller_type_print_all_defaults(caller_params).
:- mode caller_type_print_all_defaults(out) is det.

caller_type_print_all_defaults(Params) :-
	DefaultFormat = flat,
	Flat	= format_params(3, 10, 80, 2),
	Pretty	= format_params(3, 10, 80, 2),
	Verbose	= format_params(3, 10, 80, 5),
	Params	= caller_params(DefaultFormat, Flat, Pretty, Verbose).

browser_info__set_param(P0, B0, A0, F0, Pr0, V0, Setting, State0, State) :-
	default_all_yes(P0, B0, A0, P, B, A),
	default_all_yes(F0, Pr0, V0, F, Pr, V),
	maybe_set_param(P, F, Pr, V, Setting, State0 ^ print_params, PParams),
	maybe_set_param(B, F, Pr, V, Setting, State0 ^ browse_params, BParams),
	maybe_set_param(A, F, Pr, V, Setting, State0 ^ print_all_params,
			AParams),
	State = browser_state(PParams, BParams, AParams).

:- pred default_all_yes(bool, bool, bool, bool, bool, bool).
:- mode default_all_yes(in, in, in, out, out, out) is det.

default_all_yes(A0, B0, C0, A, B, C) :-
	%
	% If none of the flags are set, the command by default
	% applies to _all_ caller types/formats.
	%
	(
		A0 = no,
		B0 = no,
		C0 = no
	->
		A = yes,
		B = yes,
		C = yes
	;
		A = A0,
		B = B0,
		C = C0
	).

:- pred maybe_set_param(bool, bool, bool, bool, setting, caller_params,
		caller_params).
:- mode maybe_set_param(in, in, in, in, in, in, out) is det.

maybe_set_param(no, _, _, _, _, Params, Params).
maybe_set_param(yes, F, Pr, V, Setting, Params0, Params) :-
	(
		Setting = format(NewFormat)
	->
		Params = Params0 ^ default_format := NewFormat
	;
		maybe_set_param_2(F, Setting, Params0 ^ flat_params, FParams),
		maybe_set_param_2(Pr, Setting, Params0 ^ pretty_params,
				PrParams),
		maybe_set_param_2(V, Setting, Params0 ^ verbose_params,
				VParams),
		Params = caller_params(Params0 ^ default_format, FParams,
				PrParams, VParams)
	).

:- pred maybe_set_param_2(bool, setting, format_params, format_params).
:- mode maybe_set_param_2(in, in, in, out) is det.

maybe_set_param_2(no, _, Params, Params).
maybe_set_param_2(yes, depth(D), Params, Params ^ depth := D).
maybe_set_param_2(yes, size(S), Params, Params ^ size := S).
maybe_set_param_2(yes, format(_), _, _) :-
	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).

:- pred get_caller_params(browser_state, browse_caller_type, caller_params).
:- mode get_caller_params(in, in, out) is det.

get_caller_params(State, print, State ^ print_params).
get_caller_params(State, browse, State ^ browse_params).
get_caller_params(State, print_all, State ^ print_all_params).

:- pred get_caller_format_params(caller_params, portray_format, format_params).
:- mode get_caller_format_params(in, in, out) is det.

get_caller_format_params(Params, flat, Params ^ flat_params).
get_caller_format_params(Params, pretty, Params ^ pretty_params).
get_caller_format_params(Params, verbose, Params ^ verbose_params).

%---------------------------------------------------------------------------%

:- pred browser_state_type(type_info).
:- mode browser_state_type(out) is det.
:- pragma export(browser_state_type(out), "ML_BROWSE_browser_state_type").

browser_state_type(type_of(State)) :-
	browser_info__init_state(State).

--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list