for review: new debugger command set (part 3 of 4)

Zoltan Somogyi zs at cs.mu.OZ.AU
Thu Oct 1 18:49:36 AEST 1998


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/exceptions
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing library
Index: library/io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/io.m,v
retrieving revision 1.164
diff -u -u -r1.164 io.m
FIX BUG: MAKE THE DEBUGGER PRINT TO STDOUT, NOT THE CURRENT STREAM
--- io.m	1998/09/19 05:32:46	1.164
+++ io.m	1998/09/21 06:39:19
@@ -1736,11 +1736,15 @@
 	io__write_float(Stream, F),
 	io__write_many(Stream, Rest).
 
+:- pragma export(io__print(in, in, di, uo), "ML_io_print_to_stream").
+
 io__print(Stream, Term) -->
 	io__set_output_stream(Stream, OrigStream),
 	io__print(Term),
 	io__set_output_stream(OrigStream, _Stream).
 
+:- pragma export(io__print(in, di, uo), "ML_io_print_to_cur_stream").
+
 io__print(Term) -->
 	% `string', `char' and `univ' are special cases for io__print
 	{ type_to_univ(Term, Univ) },
@@ -2833,6 +2837,10 @@
 }").
 
 /* stream predicates */
+
+:- pragma export(io__stdin_stream(out, di, uo), "ML_io_stdin_stream").
+:- pragma export(io__stdout_stream(out, di, uo), "ML_io_stdout_stream").
+:- pragma export(io__stderr_stream(out, di, uo), "ML_io_stderr_stream").
 
 :- pragma c_code(io__stdin_stream(Stream::out, IO0::di, IO::uo),
 		[will_not_call_mercury, thread_safe], "
cvs diff: Diffing lp_solve
cvs diff: Diffing lp_solve/lp_examples
cvs diff: Diffing profiler
cvs diff: Diffing runtime
Index: runtime/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/Mmakefile,v
retrieving revision 1.39
diff -u -u -r1.39 Mmakefile
RECAST MERCURY_TRACE_UTIL AS MERCURY_LAYOUT_UTIL
--- Mmakefile	1998/09/29 05:10:54	1.39
+++ Mmakefile	1998/09/29 05:53:11
@@ -45,6 +45,7 @@
 			mercury_imp.h		\
 			mercury_init.h		\
 			mercury_label.h		\
+			mercury_layout_util.h	\
 			mercury_library_types.h	\
 			mercury_memory.h	\
 			mercury_memory_zones.h	\
@@ -70,7 +71,6 @@
 			mercury_thread.h	\
 			mercury_timing.h	\
 			mercury_trace_base.h	\
-			mercury_trace_util.h	\
 			mercury_trail.h		\
 			mercury_types.h		\
 			mercury_type_info.h	\
@@ -108,6 +108,7 @@
 			mercury_heap_profile.c	\
 			mercury_ho_call.c	\
 			mercury_label.c		\
+			mercury_layout_util.c	\
 			mercury_memory.c	\
 			mercury_memory_zones.c	\
 			mercury_memory_handlers.c	\
@@ -124,7 +125,6 @@
 			mercury_thread.c	\
 			mercury_timing.c	\
 			mercury_trace_base.c	\
-			mercury_trace_util.c	\
 			mercury_trail.c 	\
 			mercury_type_info.c	\
 			mercury_wrapper.c
Index: runtime/mercury_accurate_gc.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_accurate_gc.c,v
retrieving revision 1.1
diff -u -u -r1.1 mercury_accurate_gc.c
--- mercury_accurate_gc.c	1998/07/22 07:52:21	1.1
+++ mercury_accurate_gc.c	1998/09/29 06:23:51
@@ -12,8 +12,8 @@
RECAST MERCURY_TRACE_UTIL AS MERCURY_LAYOUT_UTIL
 
 #ifdef NATIVE_GC
 
-#include "mercury_trace_util.h"
 #include "mercury_deep_copy.h"
+#include "mercury_layout_util.h"
 #include "mercury_agc_debug.h"
 
 /*
@@ -144,7 +144,7 @@
DELETE EASY-TO-MISUSE MACROS
 		/*
 		** Save the old succip and its location.
 		*/
-		saved_success_location = &based_detstackvar(sp_at_signal,
+		saved_success_location = &MR_based_stackvar(sp_at_signal,
 			number);
 		saved_success = (Code *) *saved_success_location;
 
@@ -292,8 +292,10 @@
RECAST MERCURY_TRACE_UTIL AS MERCURY_LAYOUT_UTIL
 
         /* Get the type parameters from the stack frame. */
 
-        type_params = MR_trace_materialize_typeinfos_base(vars,
-            top_frame, stack_pointer, current_frame);
+	/* XXX We must pass NULL since the registers have not been saved */
+	/* XXX This is probably a bug; Tyson should look into it */
+        type_params = MR_materialize_typeinfos_base(vars,
+            NULL, stack_pointer, current_frame);
         
         /* Copy each live variable */
 
@@ -392,8 +394,8 @@
DELETE EASY-TO-MISUSE MACROS
 			break;
 
 		case MR_LVAL_TYPE_STACKVAR:
-			based_detstackvar(stack_pointer, locn_num) =
-				agc_deep_copy(&based_detstackvar(
+			MR_based_stackvar(stack_pointer, locn_num) =
+				agc_deep_copy(&MR_based_stackvar(
 						stack_pointer,locn_num),
 					type_info, MR_ENGINE(heap_zone2->min),
 					MR_ENGINE(heap_zone2->hardmax));
Index: runtime/mercury_agc_debug.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_agc_debug.c,v
retrieving revision 1.3
diff -u -u -r1.3 mercury_agc_debug.c
--- mercury_agc_debug.c	1998/09/21 13:17:42	1.3
+++ mercury_agc_debug.c	1998/09/22 02:28:12
@@ -9,7 +9,7 @@
RECAST MERCURY_TRACE_UTIL AS MERCURY_LAYOUT_UTIL
 */
 
 #include "mercury_imp.h"
-#include "mercury_trace_util.h"
+#include "mercury_layout_util.h"
 #include "mercury_deep_copy.h"
 #include "mercury_agc_debug.h"
 
@@ -26,6 +26,8 @@
 void
 MR_agc_dump_roots(MR_RootList roots)
 {
+	Word	saved_regs[MAX_FAKE_REG];
+
 	fflush(NULL);
 	fprintf(stderr, "Dumping roots\n");
 
@@ -40,17 +42,19 @@
 		** the saved registers).
 		*/
 		restore_registers();
-		MR_copy_regs_to_saved_regs(MAX_REAL_REG + NUM_SPECIAL_REG);
+		MR_copy_regs_to_saved_regs(MAX_REAL_REG + NUM_SPECIAL_REG,
+			saved_regs);
 
 		MR_hp = MR_ENGINE(debug_heap_zone->min);
 		MR_virtual_hp = MR_ENGINE(debug_heap_zone->min);
 
 		fflush(NULL);
-		MR_trace_write_variable((Word) roots->type_info, *roots->root);
+		MR_write_variable((Word) roots->type_info, *roots->root);
 		fflush(NULL);
 		fprintf(stderr, "\n");
 
-		MR_copy_saved_regs_to_regs(MAX_REAL_REG + NUM_SPECIAL_REG);
+		MR_copy_saved_regs_to_regs(MAX_REAL_REG + NUM_SPECIAL_REG,
+			saved_regs);
 		save_registers();
 		roots = roots->next;
 	}
@@ -61,6 +65,7 @@
 MR_agc_dump_stack_frames(MR_Internal *label, MemoryZone *heap_zone,
 	Word *stack_pointer, Word *current_frame)
 {
+	Word saved_regs[MAX_FAKE_REG];
 	int i, var_count;
 	const MR_Stack_Layout_Vars *vars;
 	Word *type_params, type_info, value;
@@ -87,8 +92,8 @@
 		var_count = layout->MR_sll_var_count;
 		vars = &(layout->MR_sll_var_info);
 
-		type_params = MR_trace_materialize_typeinfos_base(vars,
-			top_frame, stack_pointer, current_frame);
+		type_params = MR_materialize_typeinfos_base(vars,
+			NULL, stack_pointer, current_frame);
 
 		for (i = 0; i < var_count; i++) {
 			MR_Stack_Layout_Var sl_var;
@@ -114,22 +119,22 @@
 			*/
 			restore_registers();
 			MR_copy_regs_to_saved_regs(MAX_REAL_REG +
-				NUM_SPECIAL_REG);
+				NUM_SPECIAL_REG, saved_regs);
 
 			MR_hp = MR_ENGINE(debug_heap_zone->min);
 			MR_virtual_hp = MR_ENGINE(debug_heap_zone->min);
 
-			if (MR_trace_get_type_and_value_base(&sl_var, 
-					top_frame, stack_pointer,
+			if (MR_get_type_and_value_base(&sl_var, 
+					NULL, stack_pointer,
 					current_frame, type_params,
 					&type_info, &value)) {
 				printf("\t");
-				MR_trace_write_variable(type_info, value);
+				MR_write_variable(type_info, value);
 				printf("\n");
 			}
 
 			MR_copy_saved_regs_to_regs(MAX_REAL_REG +
-				NUM_SPECIAL_REG);
+				NUM_SPECIAL_REG, saved_regs);
 			save_registers();
 #endif	/* MR_DEBUG_AGC_PRINT_VARS */
 
@@ -154,7 +159,7 @@
DELETE EASY-TO-MISUSE MACROS
 			}
 			                                
 			success_ip = (Code *) 
-				based_detstackvar(stack_pointer, number);
+				MR_based_stackvar(stack_pointer, number);
 			stack_pointer = stack_pointer - 
 				entry_layout->MR_sle_stack_slots;
 			label = MR_lookup_internal_by_addr(success_ip);
@@ -191,7 +196,7 @@
 			break;
 
 		case MR_LVAL_TYPE_STACKVAR:
-			value = based_detstackvar(stack_pointer, locn_num);
+			value = MR_based_stackvar(stack_pointer, locn_num);
 			have_value = TRUE;
 			fprintf(stderr, "stackvar%d", locn_num);
 			break;
Index: runtime/mercury_conf_param.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf_param.h,v
retrieving revision 1.10
diff -u -u -r1.10 mercury_conf_param.h
--- mercury_conf_param.h	1998/09/15 09:55:22	1.10
+++ mercury_conf_param.h	1998/09/18 07:56:45
@@ -187,6 +187,14 @@
ADD TRACE DEPTH HISTOGRAMS
 ** Enables profiling of memory usage.
 */
 
+/*
+** Experimental options:
+**
+** MR_TRACE_HISTOGRAM
+** Enable this if you want to count the number of execution tracing events
+** at various call depths.
+*/
+
 /*---------------------------------------------------------------------------*/
 /*
 ** Settings of configuration parameters which can be passed on
Index: runtime/mercury_init.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_init.h,v
retrieving revision 1.7
diff -u -u -r1.7 mercury_init.h
--- mercury_init.h	1998/09/29 05:10:56	1.7
+++ mercury_init.h	1998/09/29 06:39:02
@@ -92,40 +92,59 @@
FIX BUG: MAKE THE DEBUGGER PRINT TO STDOUT, NOT THE CURRENT STREAM
 /*
 ** mercury_main() takes the address of the following predicates/functions,
 ** which are defined elsewhere.
+**
+** These declarations duplicate some of the contents of the automatically
+** generated header files for some of the library modules, and therefore
+** represent a potential double maintenance problem. At the moment we
+** accept this because it avoids having the runtime rely on the library.
+** However, the dependence on browser/debugger_interface.m is unnecessary,
+** since the only code that relies on the ML_DI_* variables below is
+** in the trace directory, which is allowed to rely on the browser
+** directory.
 */
-Declare_entry(mercury__main_2_0);		/* in the user's program */
-extern	void	mercury_init_io(void);		/* in the Mercury library */
-extern	void	ML_io_init_state(void);		/* in the Mercury library */
-extern	void	ML_io_finalize_state(void);	/* in the Mercury library */
-
-
-/* in library/debugger_interface.m */
-void	ML_DI_output_current_vars(Word, Word, Word);
-		/* normally ML_DI_output_current_vars (output_current_vars/4) */
-void	ML_DI_output_current_nth_var(Word, Word);
-		/* normally ML_DI_output_current_nth_var (output_current_nth_var/3) */
-void	ML_DI_output_current_live_var_names(Word, Word, Word);
-		/* normally ML_DI_output_current_live_var_names 
-					   (output_current_live_var_names/5) */
-void	ML_DI_output_current_slots(Integer, Integer, Integer, Word, String,
-		String, Integer, Integer, Integer, String, Word);
-		/* normally ML_DI_output_current_slots (output_current_slots/13) */
-bool	ML_DI_found_match(Integer, Integer, Integer, Word, String, String,
-		Integer, Integer, Integer, Word, String, Word);
-		/* normally ML_DI_found_match (found_match/12) */
-Integer	ML_DI_get_var_number(Word);
-void	ML_DI_read_request_from_socket(Word, Word *, Integer *);
 
+/* in the user's program */
+Declare_entry(mercury__main_2_0);
+
+/* in library/io.h */
+extern	void	mercury_init_io(void);
+extern	void	ML_io_init_state(void);
+extern	void	ML_io_finalize_state(void);
+extern	void	ML_io_stderr_stream(Word *);
+extern	void	ML_io_stdout_stream(Word *);
+extern	void	ML_io_stdin_stream(Word *);
+extern	void	ML_io_print_to_cur_stream(Word, Word);
+extern	void	ML_io_print_to_stream(Word, Word, Word);
+
+/* in browser/debugger_interface.h */
+extern	void	ML_DI_output_current_vars(Word, Word, Word);
+		/* output_current_vars/4 */
+extern	void	ML_DI_output_current_nth_var(Word, Word);
+		/* output_current_nth_var/3 */
+extern	void	ML_DI_output_current_live_var_names(Word, Word, Word);
+		/* output_current_live_var_names/5 */
+extern	void	ML_DI_output_current_slots(Integer, Integer, Integer, Word,
+		String, String, Integer, Integer, Integer, String, Word);
+		/* output_current_slots/13 */
+extern	bool	ML_DI_found_match(Integer, Integer, Integer, Word, String,
+		String, Integer, Integer, Integer, Word, String, Word);
+		/* found_match/12 */
+extern	Integer	ML_DI_get_var_number(Word);
+extern	void	ML_DI_read_request_from_socket(Word, Word *, Integer *);
+
 /* in library/std_util.m  */
-String	ML_type_name(Word);
+extern	String	ML_type_name(Word);

SUPPORT RETRY
USE FIXED STACK SLOTS FOR TRACE INFO
 
 /* in runtime/mercury_trace_base.c */
-void	MR_trace_fake(const MR_Stack_Layout_Label *, MR_trace_port,
-		Word, Word, const char *, int);
+extern	Code	*MR_trace_fake(const MR_Stack_Layout_Label *, MR_Trace_Port,
+			Unsigned, Unsigned, const char *, int);
 
 /* in trace/mercury_trace.c */
-void	MR_trace_real(const MR_Stack_Layout_Label *, MR_trace_port,
-		Word, Word, const char *, int);
+extern	Code	*MR_trace_real(const MR_Stack_Layout_Label *, MR_Trace_Port,
+			Unsigned, Unsigned, const char *, int);
+
+/* in library/std_util.h  */
+extern	String	ML_type_name(Word);
 
 #endif /* not MERCURY_INIT_H */
--- mercury_trace_util.c.was	Tue Sep 22 12:08:31 1998
+++ mercury_layout_util.c	Tue Sep 22 16:51:58 1998
@@ -13,31 +13,24 @@
RECAST MERCURY_TRACE_UTIL AS MERCURY_LAYOUT_UTIL
 
 #include "mercury_imp.h"
 #include "mercury_stack_layout.h"
-#include "mercury_trace_util.h"
-
-Word	MR_saved_regs[MAX_FAKE_REG];
+#include "mercury_layout_util.h"
 
 void
-MR_copy_regs_to_saved_regs(int max_mr_num)
+MR_copy_regs_to_saved_regs(int max_mr_num, Word *saved_regs)
 {
 	/*
-	** In the process of browsing, we call Mercury code,
+	** In the process of browsing within the debugger, we call Mercury,
 	** which may clobber the contents of the virtual machine registers,
 	** both control and general purpose, and both real and virtual
 	** registers. We must therefore save and restore these.
-	** We store them in the MR_saved_regs array.
+	** We store them in the saved_regs array.
 	**
 	** The call to MR_trace will clobber the transient registers
 	** on architectures that have them. The compiler generated code
 	** will therefore call save_transient_registers to save the transient
 	** registers in the fake_reg array. We here restore them to the
 	** real registers, save them with the other registers back in
-	** fake_reg, and then copy all fake_reg entries to MR_saved_regs.
-	**
-	** If any code invoked by MR_trace is itself traced,
-	** MR_saved_regs will be overwritten, leading to a crash later on.
-	** This is one reason (but not the only one) why we turn off
-	** tracing when we call back Mercury code from this file.
+	** fake_reg, and then copy all fake_reg entries to saved_regs.
 	*/
 
 	int i;
@@ -46,12 +39,12 @@
 	save_registers();
 
 	for (i = 0; i <= max_mr_num; i++) {
-		MR_saved_regs[i] = MR_fake_reg[i];
+		saved_regs[i] = MR_fake_reg[i];
 	}
 }
 
 void
-MR_copy_saved_regs_to_regs(int max_mr_num)
+MR_copy_saved_regs_to_regs(int max_mr_num, Word *saved_regs)
 {
 	/*
 	** We execute the converse procedure to MR_copy_regs_to_saved_regs.
@@ -63,7 +56,7 @@
 	int i;
 
 	for (i = 0; i <= max_mr_num; i++) {
-		MR_fake_reg[i] = MR_saved_regs[i];
+		MR_fake_reg[i] = saved_regs[i];
 	}
 
 	restore_registers();
@@ -71,15 +64,16 @@
 }
 
 Word *
-MR_trace_materialize_typeinfos(const MR_Stack_Layout_Vars *vars)
+MR_materialize_typeinfos(const MR_Stack_Layout_Vars *vars,
+	Word *saved_regs)
 {
-	return MR_trace_materialize_typeinfos_base(vars, TRUE,
-		MR_saved_sp(MR_saved_regs), MR_saved_curfr(MR_saved_regs));
+	return MR_materialize_typeinfos_base(vars, saved_regs,
+		MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs));
 }
 
 Word *
-MR_trace_materialize_typeinfos_base(const MR_Stack_Layout_Vars *vars,
-	bool saved_regs_valid, Word *base_sp, Word *base_curfr)
+MR_materialize_typeinfos_base(const MR_Stack_Layout_Vars *vars,
+	Word *saved_regs, Word *base_sp, Word *base_curfr)
 {
 	Word	*type_params;
 	bool	succeeded;
@@ -96,12 +90,12 @@
 		*/
 		for (i = 1; i <= count; i++) {
 			if (vars->MR_slvs_tvars[i] != 0) {
-				type_params[i] = MR_trace_lookup_live_lval_base(
+				type_params[i] = MR_lookup_live_lval_base(
 					vars->MR_slvs_tvars[i],
-					saved_regs_valid, base_sp, base_curfr,
+					saved_regs, base_sp, base_curfr,
 					&succeeded);
-				if (!succeeded) {
-					fatal_error("missing type param in MR_trace_materialize_typeinfos_base");
+				if (! succeeded) {
+					fatal_error("missing type param in MR_materialize_typeinfos_base");
 				}
 			}
 		}
@@ -113,7 +107,7 @@
 }
 
 Word
-MR_trace_make_var_list(const MR_Stack_Layout_Label *layout)
+MR_make_var_list(const MR_Stack_Layout_Label *layout, Word *saved_regs)
 {
 	int 				var_count;
 	const MR_Stack_Layout_Vars 	*vars;
@@ -151,8 +145,8 @@
 		** at the moment due to the lack of a true browser.
 		*/
 
-		if (!MR_trace_get_type_and_value_filtered(var, name, 
-							  &type_info, &value))
+		if (! MR_get_type_and_value_filtered(var, saved_regs,
+			name, &type_info, &value))
 		{
 			continue;
 		}
@@ -162,7 +156,7 @@
 		** and cons it onto the list.
 		** Note that the calls to save/restore transient registers
 		** can't be hoisted out of the loop, because
-		** MR_trace_get_type_and_value() calls MR_create_type_info()
+		** MR_get_type_and_value() calls MR_create_type_info()
 		** which may allocate memory using incr_saved_hp.
 		*/
 
@@ -178,19 +172,29 @@
 	return univ_list;
 }
 
+int
+MR_get_register_number(MR_Live_Lval locn)
+{
+	if (MR_LIVE_LVAL_TYPE(locn) == MR_LVAL_TYPE_R) {
+		return MR_LIVE_LVAL_NUMBER(locn);
+	} else {
+		return -1;
+	}
+}
+
 /* if you want to debug this code, you may want to set this var to TRUE */
-static	bool	MR_trace_print_locn = FALSE;
+static	bool	MR_print_locn = FALSE;
 
 Word
-MR_trace_lookup_live_lval(MR_Live_Lval locn, bool *succeeded)
+MR_lookup_live_lval(MR_Live_Lval locn, Word *saved_regs, bool *succeeded)
 {
-	return MR_trace_lookup_live_lval_base(locn, TRUE,
-		MR_saved_sp(MR_saved_regs), MR_saved_curfr(MR_saved_regs),
+	return MR_lookup_live_lval_base(locn, saved_regs,
+		MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs),
 		succeeded);
 }
 
 Word
-MR_trace_lookup_live_lval_base(MR_Live_Lval locn, bool saved_regs_valid,
+MR_lookup_live_lval_base(MR_Live_Lval locn, Word *saved_regs,
 	Word *base_sp, Word *base_curfr, bool *succeeded)
 {
 	int	locn_num;
@@ -202,75 +206,75 @@
 	locn_num = (int) MR_LIVE_LVAL_NUMBER(locn);
 	switch (MR_LIVE_LVAL_TYPE(locn)) {
 		case MR_LVAL_TYPE_R:
-			if (MR_trace_print_locn) {
+			if (MR_print_locn) {
 				printf("r%d", locn_num);
 			}
-			if (saved_regs_valid) {
-				value = saved_reg(MR_saved_regs, locn_num);
+			if (saved_regs != NULL) {
+				value = saved_reg(saved_regs, locn_num);
 				*succeeded = TRUE;
 			}
 			break;
 
 		case MR_LVAL_TYPE_F:
-			if (MR_trace_print_locn) {
+			if (MR_print_locn) {
 				printf("f%d", locn_num);
 			}
 			break;
 
 		case MR_LVAL_TYPE_STACKVAR:
DELETE EASY-TO-MISUSE MACROS
-			if (MR_trace_print_locn) {
+			if (MR_print_locn) {
 				printf("stackvar%d", locn_num);
 			}
-			value = based_detstackvar(base_sp, locn_num);
+			value = MR_based_stackvar(base_sp, locn_num);
 			*succeeded = TRUE;
 			break;
 
 		case MR_LVAL_TYPE_FRAMEVAR:
-			if (MR_trace_print_locn) {
+			if (MR_print_locn) {
 				printf("framevar%d", locn_num);
 			}
-			value = based_framevar(base_curfr, locn_num);
+			value = MR_based_framevar(base_curfr, locn_num);
 			*succeeded = TRUE;
 			break;
 
RECAST MERCURY_TRACE_UTIL AS MERCURY_LAYOUT_UTIL
 		case MR_LVAL_TYPE_SUCCIP:
-			if (MR_trace_print_locn) {
+			if (MR_print_locn) {
 				printf("succip");
 			}
 			break;
 
 		case MR_LVAL_TYPE_MAXFR:
-			if (MR_trace_print_locn) {
+			if (MR_print_locn) {
 				printf("maxfr");
 			}
 			break;
 
 		case MR_LVAL_TYPE_CURFR:
-			if (MR_trace_print_locn) {
+			if (MR_print_locn) {
 				printf("curfr");
 			}
 			break;
 
 		case MR_LVAL_TYPE_HP:
-			if (MR_trace_print_locn) {
+			if (MR_print_locn) {
 				printf("hp");
 			}
 			break;
 
 		case MR_LVAL_TYPE_SP:
-			if (MR_trace_print_locn) {
+			if (MR_print_locn) {
 				printf("sp");
 			}
 			break;
 
 		case MR_LVAL_TYPE_UNKNOWN:
-			if (MR_trace_print_locn) {
+			if (MR_print_locn) {
 				printf("unknown");
 			}
 			break;
 
 		default:
-			if (MR_trace_print_locn) {
+			if (MR_print_locn) {
 				printf("DEFAULT");
 			}
 			break;
@@ -280,17 +284,17 @@
 }
 
 bool
-MR_trace_get_type_and_value(const MR_Stack_Layout_Var *var,
-	Word *type_params, Word *type_info, Word *value)
+MR_get_type_and_value(const MR_Stack_Layout_Var *var,
+	Word *saved_regs, Word *type_params, Word *type_info, Word *value)
 {
-	return MR_trace_get_type_and_value_base(var, TRUE,
-		MR_saved_sp(MR_saved_regs), MR_saved_curfr(MR_saved_regs),
+	return MR_get_type_and_value_base(var, saved_regs,
+		MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs),
 		type_params, type_info, value);
 }
 
 bool
-MR_trace_get_type_and_value_base(const MR_Stack_Layout_Var *var,
-	bool saved_regs_valid, Word *base_sp, Word *base_curfr,
+MR_get_type_and_value_base(const MR_Stack_Layout_Var *var,
+	Word *saved_regs, Word *base_sp, Word *base_curfr,
 	Word *type_params, Word *type_info, Word *value)
 {
 	bool	succeeded;
@@ -303,23 +307,23 @@
 
 	pseudo_type_info = MR_LIVE_TYPE_GET_VAR_TYPE(var->MR_slv_live_type);
 	*type_info = (Word) MR_create_type_info(type_params, pseudo_type_info);
-	*value = MR_trace_lookup_live_lval_base(var->MR_slv_locn,
-		saved_regs_valid, base_sp, base_curfr, &succeeded);
+	*value = MR_lookup_live_lval_base(var->MR_slv_locn,
+		saved_regs, base_sp, base_curfr, &succeeded);
 	return succeeded;
 }
 
 bool
-MR_trace_get_type(const MR_Stack_Layout_Var *var,
+MR_get_type(const MR_Stack_Layout_Var *var, Word *saved_regs,
 	Word *type_params, Word *type_info)
 {
-	return MR_trace_get_type_base(var, TRUE,
-		MR_saved_sp(MR_saved_regs), MR_saved_curfr(MR_saved_regs),
+	return MR_get_type_base(var, saved_regs,
+		MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs),
 		type_params, type_info);
 }
 
 bool
-MR_trace_get_type_base(const MR_Stack_Layout_Var *var,
-	bool saved_regs_valid, Word *base_sp, Word *base_curfr,
+MR_get_type_base(const MR_Stack_Layout_Var *var,
+	Word *saved_regs, Word *base_sp, Word *base_curfr,
 	Word *type_params, Word *type_info)
 {
 	bool	succeeded;
@@ -336,35 +340,6 @@
FIX BUG: MAKE THE DEBUGGER PRINT TO STDOUT, NOT THE CURRENT STREAM
 	return TRUE;
 }
 
-void
-MR_trace_write_variable(Word type_info, Word value)
-{
-
-	/*
-	** XXX It would be nice if we could call an exported C function
-	** version of the browser predicate, and thus avoid going
-	** through call_engine, but for some unknown reason, that seemed
-	** to cause the Mercury code in the browser to clobber part of
-	** the C stack.
-	**
-	** Probably that was due to a bug which has since been fixed, so
-	** we should change the code below back again...
-	**
-	** call_engine() expects the transient registers to be in
-	** fake_reg, others in their normal homes.  That is the case on
-	** entry to this function.  But r1 or r2 may be transient, so we
-	** need to save/restore transient regs around the assignments to
-	** them.
-	*/
-
-	restore_transient_registers();
-	r1 = type_info;
-	r2 = value;
-	save_transient_registers();
-	call_engine(MR_library_trace_browser);
-}
-
-
 /*
 ** get_type_and_value() and get_type() will succeed to retrieve "variables"
 ** that we do not want to send to the user; "variables" beginning with
@@ -377,23 +352,32 @@
RECAST MERCURY_TRACE_UTIL AS MERCURY_LAYOUT_UTIL
 */
 
 bool
-MR_trace_get_type_and_value_filtered(const MR_Stack_Layout_Var *var, 
-				     const char *name, 
-				     Word *type_info, Word *value)
+MR_get_type_and_value_filtered(const MR_Stack_Layout_Var *var, 
+	Word *saved_regs, const char *name, Word *type_info, Word *value)
 {
 	return ((strncmp(name, "TypeInfo", 8) != 0)
 	       && (strncmp(name, "ModuleInfo", 10) != 0)
 	       && (strncmp(name, "HLDS", 4) != 0)
-	       && MR_trace_get_type_and_value(var, NULL, type_info, value));
+	       && MR_get_type_and_value(var, saved_regs, NULL,
+			type_info, value));
 }
 
 
 bool
-MR_trace_get_type_filtered(const MR_Stack_Layout_Var *var, 
-			   const char *name, Word *type_info)
+MR_get_type_filtered(const MR_Stack_Layout_Var *var, Word *saved_regs,
+	const char *name, Word *type_info)
 {
 	return ((strncmp(name, "TypeInfo", 8) != 0)
 	       && (strncmp(name, "ModuleInfo", 10) != 0)
 	       && (strncmp(name, "HLDS", 4) != 0)
-	       && MR_trace_get_type(var, NULL, type_info));
+	       && MR_get_type(var, saved_regs, NULL, type_info));
+}
FIX BUG: MAKE THE DEBUGGER PRINT TO STDOUT, NOT THE CURRENT STREAM
+
+void
+MR_write_variable(Word type_info, Word value)
+{
+	Word	stdout_stream;
+
+	(*MR_io_stdout_stream)(&stdout_stream);
+	(*MR_io_print_to_stream)(type_info, stdout_stream, value);
 }
--- mercury_trace_util.h.was	Tue Sep 22 12:08:31 1998
+++ mercury_layout_util.h	Tue Sep 22 11:59:38 1998
@@ -4,45 +4,124 @@
RECAST MERCURY_TRACE_UTIL AS MERCURY_LAYOUT_UTIL
 ** Public License - see the file COPYING.LIB in the Mercury distribution.
 */
 
-#ifndef	MERCURY_TRACE_UTIL_H
-#define	MERCURY_TRACE_UTIL_H
+#ifndef	MERCURY_LAYOUT_UTIL_H
+#define	MERCURY_LAYOUT_UTIL_H
 
-extern	Word    MR_saved_regs[MAX_FAKE_REG];
-extern	void	MR_copy_regs_to_saved_regs(int max_mr_num);
-extern	void	MR_copy_saved_regs_to_regs(int max_mr_num);
-
-extern	Word	*MR_trace_materialize_typeinfos(const MR_Stack_Layout_Vars
-			*vars);
-extern	Word	*MR_trace_materialize_typeinfos_base(const MR_Stack_Layout_Vars
-			*vars, bool saved_regs_valid,
+/*
+** These two functions copy the register state to and from the provided
+** saved_regs array, which should have room for MAX_FAKE_REG Words.
+*/
+
+extern	void	MR_copy_regs_to_saved_regs(int max_mr_num, Word *saved_regs);
+extern	void	MR_copy_saved_regs_to_regs(int max_mr_num, Word *saved_regs);
+
+/*
+** A MR_Stack_Layout_Vars describes the variables that are live at a given
+** program point. Some of the types of these variables may contain type
+** variables. Since the values of those type variables are not known until
+** runtime, the MR_Stack_Layout_Vars cannot include full typeinfos for the
+** variables. Instead, it contains pseudo-typeinfos, in which some parts
+** of some typeinfo structures may contain an indication "this data is
+** not available at compile time, but at runtime it will be in this location".
+**
+** MR_materialize_typeinfos takes as input a MR_Stack_Layout_Vars
+** structure. It returns a vector of typeinfos which has one entry for each
+** pseudo-typeinfo in the MR_Stack_Layout_Vars structure, with this typeinfo
+** being the pseudo-typeinfo with the runtime-only information substituted in.
+** Since type variable numbers start at one, the element of this array at
+** index zero will be unused. This means that the array will itself look
+** like a typeinfo.
+** 
+** The vector returned by MR_materialize_typeinfos is from malloc;
+** it should be freed after last use.
+**
+** MR_materialize_typeinfos looks up locations in the current
+** environment, as indicated by the set of saved registers (including MR_sp
+** and MR_curfr). MR_materialize_typeinfos_base does the same job but
+** assumes the environment is given by the given values of MR_sp and MR_curfr,
+** and does not assume that the registers have valid contents unless saved_regs
+** is non-null.
+*/ 
+
+extern	Word	*MR_materialize_typeinfos(
+			const MR_Stack_Layout_Vars *vars, Word *saved_regs);
+extern	Word	*MR_materialize_typeinfos_base(
+			const MR_Stack_Layout_Vars *vars, Word *saved_regs,
 			Word *base_sp, Word *base_curfr);
 
-extern	Word	MR_trace_make_var_list(const MR_Stack_Layout_Label *layout);
-extern	Word	MR_trace_lookup_live_lval(MR_Live_Lval locn, bool *succeeded);
-extern	Word	MR_trace_lookup_live_lval_base(MR_Live_Lval locn,
-			bool saved_regs_valid, Word *base_sp, Word *base_curfr,
+extern	Word	MR_make_var_list(const MR_Stack_Layout_Label *layout,
+			Word *saved_regs);
+
+/*
+** If the given encoded location refers to a register, return its number.
+** If it does not, return -1.
+*/
+
+extern	int	MR_get_register_number(MR_Live_Lval locn);
+
+/*
+** Given an encoded location, return the value at that location if possible.
+** *succeeded will say whether the attempt was successful.
+**
+** MR_lookup_live_lval looks up locations in the current environment,
+** as indicated by the set of saved registers (including MR_sp and MR_curfr).
+** MR_lookup_live_lval_base does the same job but assumes the environment
+** is given by the given values of MR_sp and MR_curfr, and does not assume
+** that the registers have valid contents unless saved_regs is non-null.
+*/ 
+
+extern	Word	MR_lookup_live_lval(MR_Live_Lval locn,
+			Word *saved_regs, bool *succeeded);
+extern	Word	MR_lookup_live_lval_base(MR_Live_Lval locn,
+			Word *saved_regs, Word *base_sp, Word *base_curfr,
 			bool *succeeded);
-extern	bool	MR_trace_get_type_and_value(const MR_Stack_Layout_Var *var,
-			Word *type_params, Word *type_info, Word *value);
-extern	bool	MR_trace_get_type_and_value_base(const MR_Stack_Layout_Var *var,
-			bool saved_regs_valid, Word *base_sp, Word *base_curfr,
+
+/*
+** Given information about the location of a variable (var) and a vector giving
+** the typeinfos corresponding to the type variables that may occur in
+** the type of that variable (type_params), try to return the value of the
+** variable in *value and the typeinfo describing its type in *type_info.
+** *succeeded will say whether the attempt was successful.
+**
+** The type_params array should have the same format as the array returned
+** by MR_materialize_typeinfos.
+**
+** MR_get_type_and_value looks up locations in the current environment,
+** as indicated by the set of saved registers (including MR_sp and MR_curfr).
+** MR_get_type_and_value_base does the same job but assumes the
+** environment is given by the given values of MR_sp and MR_curfr, and does
+** not assume that the registers have valid contents unless saved_regs is
+** non-null.
+**
+** MR_get_type and MR_get_type_base are similar but do not
+** return the value, whereas the functions with _filtered deliberately
+** do not suceed if the variable's name indicates that the value is likely
+** to be too big. This is a temporary measure only, until we get a better
+** term printer.
+*/
+
+extern	bool	MR_get_type_and_value(const MR_Stack_Layout_Var *var,
+			Word *saved_regs, Word *type_params, Word *type_info,
+			Word *value);
+extern	bool	MR_get_type_and_value_base(const MR_Stack_Layout_Var *var,
+			Word *saved_regs, Word *base_sp, Word *base_curfr,
 			Word *type_params, Word *type_info, Word *value);
-extern	bool	MR_trace_get_type(const MR_Stack_Layout_Var *var,
-			Word *type_params, Word *type_info);
-extern	bool	MR_trace_get_type_base(const MR_Stack_Layout_Var *var,
-			bool saved_regs_valid, Word *base_sp, Word *base_curfr,
+extern	bool	MR_get_type(const MR_Stack_Layout_Var *var,
+			Word *saved_regs, Word *type_params, Word *type_info);
+extern	bool	MR_get_type_base(const MR_Stack_Layout_Var *var,
+			Word *saved_regs, Word *base_sp, Word *base_curfr,
 			Word *type_params, Word *type_info);
-extern	bool	MR_trace_get_type_and_value_filtered(
-			const MR_Stack_Layout_Var *var, const char *name,
-			Word *type_info, Word *value);
-extern	bool	MR_trace_get_type_filtered(const MR_Stack_Layout_Var *var, 
-			const char *name, Word *type_info);
-
+extern	bool	MR_get_type_and_value_filtered(
+			const MR_Stack_Layout_Var *var, Word *saved_regs,
+			const char *name, Word *type_info, Word *value);
+extern	bool	MR_get_type_filtered(const MR_Stack_Layout_Var *var, 
+			Word *saved_regs, const char *name, Word *type_info);
 
 /*
-** MR_trace_write_variable:
+** MR_write_variable:
 **	Write a variable to stdout.
 */
-extern	void	MR_trace_write_variable(Word type_info, Word value);
 
-#endif	/* MERCURY_TRACE_UTIL_H */
+extern	void	MR_write_variable(Word type_info, Word value);
+
+#endif	/* MERCURY_LAYOUT_UTIL_H */

Index: runtime/mercury_stack_layout.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_layout.h,v
retrieving revision 1.8
diff -u -u -r1.8 mercury_stack_layout.h
--- mercury_stack_layout.h	1998/07/09 04:37:57	1.8
+++ mercury_stack_layout.h	1998/09/29 07:28:06
@@ -9,7 +9,7 @@
 
 /*
 ** mercury_stack_layout.h -
-**	Definitions for the stack layout data structures. 
+**	Definitions for the stack layout data structures.
 **
 ** NOTE: The constants and data-structures used here need to be kept in
 ** sync with the ones generated in the compiler. If you change anything here,
@@ -70,7 +70,7 @@
 ** 	- stack slots, registers, and special lvals such as succip, hp,
 ** 	  etc.
 **
-** MR_Live_Lval is encoded using an 8 bit low tag, the rest of the word is a 
+** MR_Live_Lval is encoded using an 8 bit low tag, the rest of the word is a
 ** data field describing which stack slot number or register number.
 **
 **  Lval		Tag	Rest
@@ -93,7 +93,7 @@
 
 typedef Word MR_Live_Lval;
 
-typedef enum { 
+typedef enum {
 	MR_LVAL_TYPE_R,
 	MR_LVAL_TYPE_F,
 	MR_LVAL_TYPE_STACKVAR,
@@ -103,7 +103,7 @@
 	MR_LVAL_TYPE_CURFR,
 	MR_LVAL_TYPE_HP,
 	MR_LVAL_TYPE_SP,
-	MR_LVAL_TYPE_UNKNOWN 
+	MR_LVAL_TYPE_UNKNOWN
 } MR_Lval_Type;
 
 #define MR_LIVE_LVAL_TAGBITS	8
@@ -126,7 +126,7 @@
 **
 ** The data is encoded such that low values (less than
 ** TYPELAYOUT_MAX_VARINT) represent succip, hp, etc.  Higher values
-** represent data variables, and are pointers to a 2 word cell, 
+** represent data variables, and are pointers to a 2 word cell,
 ** containing a pseudo type_info and an instantiation represention.
 **
 ** This data is generated in compiler/stack_layout.m, which must be kept
@@ -135,16 +135,16 @@
 
 typedef Word MR_Live_Type;
 
-typedef enum { 
+typedef enum {
 	MR_LIVE_TYPE_SUCCIP,
 	MR_LIVE_TYPE_HP,
 	MR_LIVE_TYPE_CURFR,
 	MR_LIVE_TYPE_MAXFR,
 	MR_LIVE_TYPE_REDOIP,
-	MR_LIVE_TYPE_UNWANTED 
+	MR_LIVE_TYPE_UNWANTED
 } MR_Lval_NonVar;
 
-typedef struct { 
+typedef struct {
 	Word	*pseudo_type_info;
 	Word	inst;	/* not yet used; currently always -1 */
 } MR_Var_Shape_Info;
@@ -189,12 +189,18 @@
SUPPORT RETRY
 	MR_Live_Lval		*MR_slvs_tvars;
 } MR_Stack_Layout_Vars;
 
-#define	MR_name_if_present(vars, i)					\
-				((vars->MR_slvs_names != NULL		\
-				&& vars->MR_slvs_names[(i)] != NULL)	\
-				? vars->MR_slvs_names[(i)]		\
+#define	MR_name_if_present(vars, i)					    \
+				((vars->MR_slvs_names != NULL		    \
+				&& vars->MR_slvs_names[(i)] != NULL)	    \
+				? strchr(vars->MR_slvs_names[(i)], ':') + 1 \
 				: "")
 
+#define	MR_numbered_name_if_present(vars, i)				    \
+				((vars->MR_slvs_names != NULL	 	    \
+				&& vars->MR_slvs_names[(i)] != NULL)	    \
+				? vars->MR_slvs_names[(i)]		    \
+				: "")
+
 /*-------------------------------------------------------------------------*/
 /*
 ** Definitions for MR_Stack_Layout_Entry
@@ -222,6 +228,10 @@
USE FIXED STACK SLOTS FOR TRACE INFO
 ** if MR_ENTRY_LAYOUT_HAS_PROC_ID(entry) evaluates to true.
 ** Group (3) is present and meaningful
 ** if MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry) evaluates to true.
+**
+** Group (2) fields have a different interpretation if the procedure is
+** compiler-generated. You can test for this via the macro
+** MR_ENTRY_LAYOUT_COMPILER_GENERATED.
 */
 
 typedef	struct MR_Stack_Layout_Entry_Struct {
@@ -242,6 +252,7 @@
 	/* exec trace group */
 	struct MR_Stack_Layout_Label_Struct
 				*MR_sle_call_label;
+	int			MR_sle_maybe_from_full;
 } MR_Stack_Layout_Entry;
 
 #define	MR_ENTRY_LAYOUT_HAS_PROC_ID(entry)			\
@@ -251,6 +262,9 @@
 		(MR_ENTRY_LAYOUT_HAS_PROC_ID(entry)		\
 		&& entry->MR_sle_call_label != NULL)
 
+#define	MR_ENTRY_LAYOUT_COMPILER_GENERATED(entry)		\
+		((int) entry->MR_sle_pred_or_func > MR_FUNCTION)
+
 /*
 ** Define a stack layout for a label that you know very little about.
 ** It is just a generic entry label, no useful information, except
@@ -275,6 +289,44 @@
 #else
   #define MR_MAKE_STACK_LAYOUT_ENTRY(l)        
 #endif	/* MR_USE_STACK_LAYOUTS */
+
+/*
+** In procedures compiled with execution tracing, three items are stored
+** in stack slots with fixed numbers. They are:
+**
+**	the event number of the call event,
+**	the call number, and
+**	the call depth.
+**
+** The following macros will access them. They can be used whenever
+** MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry) is true; which set you should use
+** depends on the determinism of the procedure.
+**
+** These macros have to be kept in sync with compiler/trace.m.
+*/
+
+#define MR_event_num_framevar(base_curfr)    MR_based_framevar(base_curfr, 1)
+#define MR_call_num_framevar(base_curfr)     MR_based_framevar(base_curfr, 2)
+#define MR_call_depth_framevar(base_curfr)   MR_based_framevar(base_curfr, 3)
+
+#define MR_event_num_stackvar(base_sp)	     MR_based_stackvar(base_sp, 1)
+#define MR_call_num_stackvar(base_sp)	     MR_based_stackvar(base_sp, 2)
+#define MR_call_depth_stackvar(base_sp)	     MR_based_stackvar(base_sp, 3)
+
+/*
+** In model_non procedures compiled with an execution trace options that
+** require REDO events, one other item is stored in a fixed stack slot.
+** This is
+**
+**	the address of the layout structure for the redo event
+**
+** The following macro will access it. This macro should be used only from
+** within the code that calls MR_trace for the REDO event.
+**
+** This macros have to be kept in sync with compiler/trace.m.
+*/
+
+#define MR_redo_layout_framevar(base_curfr)  MR_based_framevar(base_curfr, 4)
 
 /*-------------------------------------------------------------------------*/
 /*
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.17
diff -u -u -r1.17 mercury_stack_trace.c
--- mercury_stack_trace.c	1998/09/21 06:30:47	1.17
+++ mercury_stack_trace.c	1998/09/21 06:40:15
@@ -171,7 +171,8 @@
 			return STEP_ERROR_AFTER;
 		}
 
-		success = (Code *) field(0, *stack_trace_sp_ptr, -number);
+		success = (Code *) MR_based_stackvar(*stack_trace_sp_ptr,
+					number);
 		*stack_trace_sp_ptr = *stack_trace_sp_ptr -
 			entry_layout->MR_sle_stack_slots;
 	} else {
@@ -289,15 +290,42 @@
 	fprintf(fp, "%9d ", start_level);
 
 	if (count > 1) {
-		fprintf(fp, " %3d*", count);
+		fprintf(fp, " %3d* ", count);
 	} else {
-		fprintf(fp, "%5s", "");
+		fprintf(fp, "%5s ", "");
 	}
 
-	fprintf(fp, " %s:%s/%ld-%ld (%s)\n",
+	MR_print_proc_id(fp, entry_layout, NULL);
+}
+
+void
+MR_print_proc_id_for_debugger(const MR_Stack_Layout_Entry *entry_layout)
+{
+	MR_print_proc_id(stdout, entry_layout, NULL);
+}
+
+void
+MR_print_proc_id(FILE *fp, const MR_Stack_Layout_Entry *entry_layout,
+	const char *extra)
+{
+	/*
+	** The following should be a full identification of the procedure
+	** provided (a) there was no intermodule optimization and (b) we are
+	** not interested in the details of compiler-generated procedures.
+	*/
+
+	fprintf(fp, "%s %s:%s/%ld-%ld (%s)",
+		entry_layout->MR_sle_pred_or_func == MR_PREDICATE ?
+			"pred" : "func",
 		entry_layout->MR_sle_def_module,
 		entry_layout->MR_sle_name,
 		(long) entry_layout->MR_sle_arity,
 		(long) entry_layout->MR_sle_mode,
 		detism_names[entry_layout->MR_sle_detism]);
+
+	if (extra != NULL) {
+		fprintf(fp, " %s\n", extra);
+	} else {
+		fprintf(fp, "\n");
+	}
 }
Index: runtime/mercury_stack_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.h,v
retrieving revision 1.9
diff -u -u -r1.9 mercury_stack_trace.h
--- mercury_stack_trace.h	1998/07/22 07:53:09	1.9
+++ mercury_stack_trace.h	1998/07/23 06:39:41
@@ -37,9 +37,8 @@
 ** 	using `:- external'.
 */
 
-extern	void		MR_dump_stack(Code *success_pointer,
-				Word *det_stack_pointer,
-				Word *current_frame);
+extern	void	MR_dump_stack(Code *success_pointer, Word *det_stack_pointer,
+			Word *current_frame);
 
 /*
 ** MR_dump_stack_from_layout:
@@ -62,8 +61,7 @@
 **	The value of maxfr should be in *base_maxfr.
 */
 
-extern	void		MR_dump_nondet_stack_from_layout(FILE *fp,
-				Word *base_maxfr);
+extern	void	MR_dump_nondet_stack_from_layout(FILE *fp, Word *base_maxfr);
 
 /*
 ** MR_find_nth_ancestor:
@@ -81,36 +79,11 @@
 */
 
 extern	const MR_Stack_Layout_Label *MR_find_nth_ancestor(
-				const MR_Stack_Layout_Label *label_layout,
-				int ancestor_level, Word **stack_trace_sp,
-				Word **stack_trace_curfr, const char **problem);
+			const MR_Stack_Layout_Label *label_layout,
+			int ancestor_level, Word **stack_trace_sp,
+			Word **stack_trace_curfr, const char **problem);
 
 /*
-** MR_stack_trace_bottom should be set to the address of global_success,
-** the label main/2 goes to on success. Stack dumps terminate when they
-** reach a stack frame whose saved succip slot contains this address.
-*/
-
-Code	*MR_stack_trace_bottom;
-
-/*
-** MR_nondet_stack_trace_bottom should be set to the address of the buffer
-** nondet stack frame created before calling main. Nondet stack dumps terminate
-** when they reach a stack frame whose redoip contains this address. Note that
-** the redoip and redofr slots of this frame may be hijacked.
-*/
-
-Word	*MR_nondet_stack_trace_bottom;
-
-
-typedef        enum {
-	STEP_ERROR_BEFORE,      /* the current entry_layout has no valid info */
-	STEP_ERROR_AFTER,       /* the current entry_layout has valid info,
-				   but the next one does not */
-	STEP_OK                 /* both have valid info */
-} MR_Stack_Walk_Step_Result;
-
-/*
 ** MR_stack_walk_step:
 **	This function takes the entry_layout for the current stack
 **	frame (which is the topmost stack frame from the two stack
@@ -126,10 +99,47 @@
 **	encountered, problem_ptr will be set to a string representation
 **	of the error.
 */
+
+typedef enum {
+	STEP_ERROR_BEFORE,      /* the current entry_layout has no valid info */
+	STEP_ERROR_AFTER,       /* the current entry_layout has valid info,
+				   but the next one does not */
+	STEP_OK                 /* both have valid info */
+} MR_Stack_Walk_Step_Result;
+
 extern  MR_Stack_Walk_Step_Result
 MR_stack_walk_step(const MR_Stack_Layout_Entry *entry_layout,
 		const MR_Stack_Layout_Label **return_label_layout,
 		Word **stack_trace_sp_ptr, Word **stack_trace_curfr_ptr,
 		const char **problem_ptr);
+
+/*
+** MR_stack_trace_bottom should be set to the address of global_success,
+** the label main/2 goes to on success. Stack dumps terminate when they
+** reach a stack frame whose saved succip slot contains this address.
+*/
+
+Code	*MR_stack_trace_bottom;
+
+/*
+** MR_nondet_stack_trace_bottom should be set to the address of the buffer
+** nondet stack frame created before calling main. Nondet stack dumps terminate
+** when they reach a stack frame whose redoip contains this address. Note that
+** the redoip and redofr slots of this frame may be hijacked.
+*/
+
+Word	*MR_nondet_stack_trace_bottom;
+
+/*
+** MR_print_proc_id prints an identification of the given procedure,
+** consisting of "pred" or "func", module name, pred or func name, arity,
+** mode number and determinism, followed by an optional extra string,
+** and a newline.
+*/
+
+extern	void	MR_print_proc_id_for_debugger(
+			const MR_Stack_Layout_Entry *entry);
+extern	void	MR_print_proc_id(FILE *fp, const MR_Stack_Layout_Entry *entry,
+			const char *extra);
 
 #endif /* MERCURY_STACK_TRACE_H */
Index: runtime/mercury_stacks.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stacks.h,v
retrieving revision 1.9
diff -u -u -r1.9 mercury_stacks.h
--- mercury_stacks.h	1998/08/02 06:37:00	1.9
+++ mercury_stacks.h	1998/09/10 09:06:02
@@ -21,9 +21,6 @@
 #define	MR_stackvar(n)			MR_based_stackvar(MR_sp, n)
 
 #define	detstackvar(n)			MR_based_stackvar(MR_sp, n)
-#define	based_detstackvar(base_sp, n)	MR_based_stackvar(base_sp, n)
-#define	saved_detstackvar(save_area, n)	\
-			MR_based_stackvar(MR_saved_sp(save_area), n)
 
 #define	incr_sp_push_msg(n, msg)				\
 			(					\
@@ -127,10 +124,6 @@
 
 #define	MR_framevar(n)		MR_based_framevar(MR_curfr,n)
 #define	framevar(n)		MR_framevar(n+1)
-#define	based_framevar(base_curfr, n)	\
-			MR_based_framevar(base_curfr, n+1)
-#define	saved_framevar(save_area, n)	\
-			MR_based_framevar(MR_saved_curfr(save_area), n+1)
 
 /* DEFINITIONS FOR MANIPULATING THE NONDET STACK */
 
Index: runtime/mercury_trace_base.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_base.c,v
retrieving revision 1.2
diff -u -u -r1.2 mercury_trace_base.c
--- mercury_trace_base.c	1998/09/29 05:11:07	1.2
+++ mercury_trace_base.c	1998/09/29 07:16:01
@@ -1,4 +1,8 @@
ADD REDO EVENTS
 /*
+INIT mercury_sys_init_trace
+ENDINIT
+*/
+/*
 ** Copyright (C) 1997-1998 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.
@@ -27,7 +31,7 @@
MISC RUNTIME CHANGES
 ** This variable is set in mercury_wrapper.c and never modified afterwards.
 */
 
-MR_trace_type	MR_trace_handler = MR_TRACE_INTERNAL;
+MR_Trace_Type	MR_trace_handler = MR_TRACE_INTERNAL;
 
 /*
 ** Compiler generated tracing code will check whether MR_trace_enabled is true,
@@ -86,28 +90,57 @@
ADD TRACE DEPTH HISTOGRAMS
 
 Bool		MR_trace_from_full = 1;
 
-void
-MR_trace(const MR_Stack_Layout_Label *layout, MR_trace_port port,
-	Word seqno, Word depth, const char * path, int max_mr_num,
-	bool trace_this_event)
+int		*MR_trace_histogram_all = NULL;
+int		*MR_trace_histogram_exp = NULL;
+int		MR_trace_histogram_max  = 0;
+int		MR_trace_histogram_hwm  = 0;
SUPPORT RETRY
USE FIXED STACK SLOTS FOR TRACE INFO
MISC RUNTIME CHANGES
+
+Code *
+MR_trace(const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
+	const char * path, int max_mr_num)
 {
-	if (MR_trace_enabled && trace_this_event) {
-		(*MR_trace_func_ptr)(layout, port, seqno, depth,
-			path, max_mr_num);
+	bool		maybe_from_full;
+	Unsigned	seqno;
+	Unsigned	depth;
+
+	if (! MR_trace_enabled) {
+		return NULL;
 	}
+
+	maybe_from_full = layout->MR_sll_entry->MR_sle_maybe_from_full;
+	if (MR_DETISM_DET_STACK(layout->MR_sll_entry->MR_sle_detism)) {
+		if (maybe_from_full > 0 && ! MR_stackvar(maybe_from_full)) {
+			return NULL;
+		}
+
+		seqno = (Unsigned) MR_call_num_stackvar(MR_sp);
+		depth = (Unsigned) MR_call_depth_stackvar(MR_sp);
+	} else {
+		if (maybe_from_full > 0 && ! MR_framevar(maybe_from_full)) {
+			return NULL;
+		}
+
+		seqno = (Unsigned) MR_call_num_framevar(MR_curfr);
+		depth = (Unsigned) MR_call_depth_framevar(MR_curfr);
+	}
+
+	return (*MR_trace_func_ptr)(layout, port, seqno, depth,
+			path, max_mr_num);
 }
 
-void
-MR_trace_fake(const MR_Stack_Layout_Label *layout, MR_trace_port port,
+Code *
+MR_trace_fake(const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
 	Word seqno, Word depth, const char * path, int max_mr_num)
 {
 	fatal_error("This executable is not set up for debugging.\n"
 		"Rebuild the <main>_init.c file, "
 		"and give the -t flag to c2init when you do so.\n"
 		"If you are using mmake, you can do this by including "
-		"-t in C2INIT_FLAGS.\n");
-	/* XXX refer to the debugging chapter in the user guide */
-	/* when it is written */
+		"-t in C2INIT_FLAGS.\n"
+		"For further details, please see the Debugging chapter"
+		"of the Mercury User's Guide.\n");
+	/*NOTREACHED*/
+	return NULL;
 }
 
 void
@@ -155,6 +188,22 @@
diff -N mercury_trace.h
 
 		fprintf(fp, "Last trace event was event #%ld.\n",
 			(long) MR_trace_event_number);
+
+#ifdef	MR_TRACE_HISTOGRAM
+		{
+			FILE	*hfp;
+
+			hfp = fopen(".mercury_histogram", "w");
+			if (hfp != NULL) {
+				fprintf(fp, "All-include event histogram put"
+					" into file .mercury_histogram\n");
+				MR_trace_print_histogram(hfp, "All-inclusive",
+					MR_trace_histogram_all,
+					MR_trace_histogram_hwm);
+				fclose(hfp);
+			}
+		}
+#endif	/* MR_TRACE_HISTOGRAM */
 	}
 }
 
@@ -173,4 +222,49 @@
 			(long) MR_trace_event_number);
 		write(fd, buf, strlen(buf));
 	}
+}
+
+void
+MR_trace_print_histogram(FILE *fp, const char *which, int *histogram, int max)
+{
+	int	i;
+
+	fprintf(fp, "%s histogram\n", which);
+	for (i = 1; i <= max; i++) {
+		fprintf(fp, "depth %4d: %10d", i, histogram[i]);
+		if (i + 1 <= max && histogram[i] != 0) {
+			fprintf(fp, ", branching factor %7.2f\n",
+				(float) histogram[i+1] / (float) histogram[i]);
+		} else {
+			fprintf(fp, "\n");
+		}
+	}
+}
ADD REDO EVENTS
+
+Define_extern_entry(MR_do_trace_redo_fail);
+
+BEGIN_MODULE(MR_trace_labels_module)
+	init_label(MR_do_trace_redo_fail);
+BEGIN_CODE
+
+Define_entry(MR_do_trace_redo_fail);
+#if 0
+	/* For use in case this ever needs to be debugged again. */
+	printf("MR_curfr = %p\n", MR_curfr);
+	printf("MR_redofr_slot(MR_curfr) = %p\n", MR_redofr_slot(MR_curfr));
+	printf("&MR_redo_layout_framevar(MR_redofr_slot(MR_curfr) = %p\n",
+		&MR_redo_layout_framevar(MR_redofr_slot(MR_curfr)));
+	printf("MR_redo_layout_framevar(MR_redofr_slot(MR_curfr) = %p\n",
+		MR_redo_layout_framevar(MR_redofr_slot(MR_curfr)));
+#endif
+	MR_trace((const MR_Stack_Layout_Label *)
+		MR_redo_layout_framevar(MR_redofr_slot(MR_curfr)),
+		MR_PORT_REDO, "", 0);
+	fail();
+
+END_MODULE
+
+void mercury_sys_init_trace(void); /* suppress gcc warning */
+void mercury_sys_init_trace(void) {
+	MR_trace_labels_module();
 }
Index: runtime/mercury_trace_base.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_base.h,v
retrieving revision 1.2
diff -u -u -r1.2 mercury_trace_base.h
--- mercury_trace_base.h	1998/09/29 05:11:08	1.2
+++ mercury_trace_base.h	1998/09/29 10:15:51
@@ -7,8 +7,9 @@
 /*
 ** mercury_trace_base.h defines the interface between the main part
 ** of the runtime system (mainly mercury_wrapper.c) and the part of the
-** tracing subsystem that has to be present even if no module in the program
-** is compiled with execution tracing.
+** tracing subsystem that has to be present even if tracing is not enabled.
+** The part of the tracing system that required only when tracing is enabled
+** is in the trace directory.
 */
 
 #ifndef MERCURY_TRACE_BASE_H
@@ -18,12 +19,13 @@
ADD REDO EVENTS
 
 /*
 ** This enum should EXACTLY match the definition of the `trace_port_type' type
-** in library/debugger_interface.
+** in browser/debugger_interface.
 */
 
 typedef	enum {
 	MR_PORT_CALL,
 	MR_PORT_EXIT,
+	MR_PORT_REDO,
 	MR_PORT_FAIL,
 	MR_PORT_THEN,
 	MR_PORT_ELSE,
@@ -31,21 +33,28 @@
MISC RUNTIME CHANGES
 	MR_PORT_SWITCH,
 	MR_PORT_PRAGMA_FIRST,
 	MR_PORT_PRAGMA_LATER
-} MR_trace_port;
+} MR_Trace_Port;
 
+#define MR_trace_incr_seq()		((Word) ++MR_trace_call_seqno)
+#define MR_trace_incr_depth()		((Word) ++MR_trace_call_depth)
+#define MR_trace_reset_depth(d)		(MR_trace_call_depth = (Unsigned) (d))
+
SUPPORT RETRY
USE FIXED STACK SLOTS FOR TRACE INFO
 /*
 ** MR_trace is called from Mercury modules compiled with tracing.
-** It performs an indirect call through MR_trace_func_ptr, which
-** will point either to MR_trace_real, which is defined in the trace
-** library, or to MR_trace_fake, defined here, which just prints an
-** error message and aborts.
+** If the event is supposed to be traced, it performs an indirect call
+** through MR_trace_func_ptr, which will point either to MR_trace_real,
+** which is defined in the trace library, or to MR_trace_fake, defined here,
+** which just prints an error message and aborts.
+**
+** The return value, if not NULL, says where execution should continue
+** after the event. (NULL means it should continue as usual.)
 */
 
-extern	void	MR_trace(const MR_Stack_Layout_Label *, MR_trace_port,
-			Word, Word, const char *, int, bool);
+extern	Code	*MR_trace(const MR_Stack_Layout_Label *, MR_Trace_Port,
+			const char *, int);
 
-extern	void	MR_trace_fake(const MR_Stack_Layout_Label *, MR_trace_port,
-			Word, Word, const char *, int);
+extern	Code	*MR_trace_fake(const MR_Stack_Layout_Label *, MR_Trace_Port,
+			Unsigned, Unsigned, const char *, int);
 
 /*
 ** MR_trace_init() is called from mercury_runtime_init()
@@ -72,25 +81,23 @@
MISC RUNTIME CHANGES
 extern	void	MR_trace_end(void);
 extern	void	MR_trace_final(void);
 
-#define	MR_trace_incr_seq()	(++MR_trace_call_seqno)
-#define	MR_trace_incr_depth()	(++MR_trace_call_depth)
-#define	MR_trace_reset_depth(d)	do { MR_trace_call_depth = (d); } while (0)
-
 /*
 ** The globals that define the interface between the tracing subsystem
 ** and compiled code, and which must be initialized in the permanent part
 ** of the runtime.
+**
+** XXX They should probably be in MercuryEngine.
 */
 
-extern	Word		MR_trace_call_seqno;
-extern	Word		MR_trace_call_depth;
+extern	Unsigned	MR_trace_call_seqno;
+extern	Unsigned	MR_trace_call_depth;
 
 typedef enum {
 	MR_TRACE_INTERNAL,
 	MR_TRACE_EXTERNAL
-} MR_trace_type;
+} MR_Trace_Type;
 
-extern	MR_trace_type	MR_trace_handler;
+extern	MR_Trace_Type	MR_trace_handler;
 extern	bool		MR_trace_enabled;
 
 extern	Unsigned	MR_trace_event_number;
@@ -103,5 +110,33 @@
ADD TRACE DEPTH HISTOGRAMS
 
 extern	void	MR_trace_report(FILE *fp);
 extern	void	MR_trace_report_raw(int fd);
+
+/*
+** If MR_TRACE_HISTOGRAM is defined, MR_trace maintains two arrays of integers,
+** MR_trace_histogram_all and MR_trace_histogram_exp, in which the element
+** with subscript d is incremented when a trace event occurs at depth d.
+** The intention is that the MR_trace_histogram_all records all events
+** and is never reset, which means that it records information about a whole
+** execution of the program. MR_trace_histogram_exp on the other hand can be
+** zeroed by a command from the debugger at e.g a call port, and examined at
+** e.g. an exit port, which means that it can record information about the
+** execution of a call.
+**
+** Both arrays are allocated via malloc, and resized on demand. They are
+** always the same size, and this size is stored in MR_trace_histogram_max.
+** MR_trace_histogram_hwm stores the high water mark, i.e. the biggest
+** depth number that has been encountered so far in the execution of the
+** program.
+*/
+
+#define	MR_INIT_HISTOGRAM_SIZE	128
+
+extern	int	*MR_trace_histogram_all;
+extern	int	*MR_trace_histogram_exp;
+extern	int	MR_trace_histogram_max;
+extern	int	MR_trace_histogram_hwm;
+
+extern	void	MR_trace_print_histogram(FILE *fp, const char *which,
+			int *histogram, int max);
 
 #endif /* MERCURY_TRACE_BASE_H */
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.26
diff -u -u -r1.26 mercury_wrapper.c
--- mercury_wrapper.c	1998/09/29 05:11:14	1.26
+++ mercury_wrapper.c	1998/09/29 06:39:24
@@ -138,8 +138,13 @@
FIX BUG: MAKE THE DEBUGGER PRINT TO STDOUT, NOT THE CURRENT STREAM
 		/* normally ML_io_init_state (io__init_state/2)*/
 void	(*MR_library_finalizer)(void);
 		/* normally ML_io_finalize_state (io__finalize_state/2) */
-Code	*MR_library_trace_browser;
-		/* normally mercury__io__print_3_0 (io__print/3) */
+
+void	(*MR_io_stderr_stream)(Word *);
+void	(*MR_io_stdout_stream)(Word *);
+void	(*MR_io_stdin_stream)(Word *);
+void	(*MR_io_print_to_cur_stream)(Word, Word);
+void	(*MR_io_print_to_stream)(Word, Word, Word);
+
 void	(*MR_DI_output_current_ptr)(Integer, Integer, Integer, Word, String,
 		String, Integer, Integer, Integer, Word, String, Word, Word);
 		/* normally ML_DI_output_current (output_current/13) */
@@ -147,9 +152,18 @@
 		Integer, Integer, Integer, Word, String, Word);
 		/* normally ML_DI_found_match (output_current/12) */
 void	(*MR_DI_read_request_from_socket)(Word, Word *, Integer *);
+
+/*
+** This variable has been replaced by MR_io_print_to_*_stream,
+** but the installed mkinit executable may still generate references to it.
+** We must therefore keep it until all obsolete mkinit executables have
+** been retired.
+*/
+
+Code	*MR_library_trace_browser;
SUPPORT RETRY
USE FIXED STACK SLOTS FOR TRACE INFO
 
-void	(*MR_trace_func_ptr)(const MR_Stack_Layout_Label *, MR_trace_port,
-		Word, Word, const char *, int);
+Code	*(*MR_trace_func_ptr)(const MR_Stack_Layout_Label *, MR_Trace_Port,
+		Unsigned, Unsigned, const char *, int);
 
 #ifdef USE_GCC_NONLOCAL_GOTOS
 
Index: runtime/mercury_wrapper.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.h,v
retrieving revision 1.13
diff -u -u -r1.13 mercury_wrapper.h
--- mercury_wrapper.h	1998/09/29 05:11:16	1.13
+++ mercury_wrapper.h	1998/09/29 06:39:44
@@ -42,12 +42,17 @@
FIX BUG: MAKE THE DEBUGGER PRINT TO STDOUT, NOT THE CURRENT STREAM
 ** The address_of_foo pointers are set to the address of
 ** the corresponding foo.
 */
-extern	Code *		program_entry_point; /* normally mercury__main_2_0; */
+extern	Code 		*program_entry_point; /* normally mercury__main_2_0; */
 
 extern	void		(*MR_library_initializer)(void);
 extern	void		(*MR_library_finalizer)(void);
-extern	Code		*MR_library_trace_browser;
 
+extern	void		(*MR_io_stderr_stream)(Word *);
+extern	void		(*MR_io_stdout_stream)(Word *);
+extern	void		(*MR_io_stdin_stream)(Word *);
+extern	void		(*MR_io_print_to_cur_stream)(Word, Word);
+extern	void		(*MR_io_print_to_stream)(Word, Word, Word);
+
 extern	void		(*address_of_mercury_init_io)(void);
 extern	void		(*address_of_init_modules)(void);
 
@@ -57,44 +62,50 @@
 
 /*
 ** Similarly, these are for the debugger interface; they're defined in
-** library/debugger_interface.m.
+** browser/debugger_interface.m.
 */
-void	(*MR_DI_output_current_vars)(Word, Word, Word);
-		/* normally ML_DI_output_current_vars (output_current_vars/3) */
-void	(*MR_DI_output_current_nth_var)(Word, Word);
-		/* normally ML_DI_output_current_nth_var 
-						 (output_current_nth_var/2) */
-void	(*MR_DI_output_current_live_var_names)(Word, Word, Word);
-		/* normally ML_DI_output_current_live_var_names
-					   (output_current_live_var_names/5) */
-void	(*MR_DI_output_current_slots)(Integer, Integer, Integer, Word, String,
-		String, Integer, Integer, Integer, String, Word);
-		/* normally ML_DI_output_current_slots (output_current_slots/13) */
-bool	(*MR_DI_found_match)(Integer, Integer, Integer, Word, String, String,
-		Integer, Integer, Integer, Word, String, Word);
-		/* normally ML_DI_found_match (found_match/12) */
-int	(*MR_DI_get_var_number)(Word);
-		/* normally ML_DI_get_var_number (get_var_number/1) */
-void	(*MR_DI_read_request_from_socket)(Word, Word *, Integer *);
-		/* normally ML_DI_read_request_from_socket
-		   (read_request_from_socket/5) */
+extern	void	(*MR_DI_output_current_vars)(Word, Word, Word);
+		/* output_current_vars/3 */
+extern	void	(*MR_DI_output_current_nth_var)(Word, Word);
+		/* output_current_nth_var/2 */
+extern	void	(*MR_DI_output_current_live_var_names)(Word, Word, Word);
+		/* output_current_live_var_names/5 */
+extern	void	(*MR_DI_output_current_slots)(Integer, Integer, Integer, Word,
+		String, String, Integer, Integer, Integer, String, Word);
+		/* output_current_slots/13 */
+extern	bool	(*MR_DI_found_match)(Integer, Integer, Integer, Word, String,
+		String, Integer, Integer, Integer, Word, String, Word);
+		/* found_match/12 */
+extern	int	(*MR_DI_get_var_number)(Word);
+		/* get_var_number/1 */
+extern	void	(*MR_DI_read_request_from_socket)(Word, Word *, Integer *);
+		/* read_request_from_socket/5 */
 
 /*
-** ML_type_name() is defined in library/std_util.m and use in
-** runtime/mercury_trace_external.c
+** ML_type_name() is defined in library/std_util.m and used in
+** trace/mercury_trace_external.c.
 */
 
-String	(*MR_type_name)(Word);
+extern	String	(*MR_type_name)(Word);
 		/* normally ML_type_name (type_name/1) */ 
+
+/*
+** This variable has been replaced by MR_io_print_to_*_stream,
+** but the installed mkinit executable may still generate references to it.
+** We must therefore keep it until all obsolete mkinit executables have
+** been retired.
+*/
+
+extern	Code	*MR_library_trace_browser;
SUPPORT RETRY
USE FIXED STACK SLOTS FOR TRACE INFO
 
-void    (*MR_trace_func_ptr)(const MR_Stack_Layout_Label *, MR_trace_port,
-                Word, Word, const char *, int);
+extern	Code    *(*MR_trace_func_ptr)(const MR_Stack_Layout_Label *,
+			MR_Trace_Port, Unsigned, Unsigned, const char *, int);
 
 extern	void		do_init_modules(void);
 
-extern	const char *	progname;
+extern	const char	*progname;
 extern	int		mercury_argc;
-extern	char **		mercury_argv;
+extern	char		**mercury_argv;
 extern	int		mercury_exit_status;
 
 /* sizes of the data areas, *including* the red zone size */
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 scripts
Index: scripts/final_grade_options.sh-subr
===================================================================
RCS file: final_grade_options.sh-subr
diff -N final_grade_options.sh-subr
--- /dev/null	Wed May 28 10:49:58 1997
+++ final_grade_options.sh-subr	Mon Sep 28 17:17:56 1998
@@ -0,0 +1,25 @@
+#---------------------------------------------------------------------------#
+# Copyright (C) 1998 The University of Melbourne.
+# This file may only be copied under the terms of the GNU General
+# Public License - see the file COPYING in the Mercury distribution.
+#---------------------------------------------------------------------------#
+#
+# final_grade_options.sh-subr:
+#	An `sh' subroutine for handling implications between grade-related
+#	options. Used by the `ml' and `mgnuc' scripts.
+#
+#	The code here should be inserted after a script's option-parsing
+#	loop.
+#
+#---------------------------------------------------------------------------#
+
+#
+# .debug grade implies --use-trail
+#	(see comment in compiler/handle_options.m for rationale)
+#
+case $stack_trace,$require_tracing in
+	true,true)
+		use_trail=true ;;
+esac
+
+#---------------------------------------------------------------------------#
--- /mnt/munkora/home/staff/zs/mer/ws1/scripts/mdb	Mon Sep 28 17:02:40 1998
+++ scripts/mdb.in	Wed Sep 16 14:46:30 1998
DOCUMENT NEW DEBUG COMMAND SET
@@ -36,4 +36,6 @@
 
 MERCURY_OPTIONS="$MERCURY_OPTIONS -Di"
 export MERCURY_OPTIONS
+DEFAULT_MERCURY_DEBUGGER_INIT=@DEFAULT_MERCURY_DEBUGGER_INIT_DIR@/mdbrc
+export DEFAULT_MERCURY_DEBUGGER_INIT
 exec "$@"
Index: scripts/mgnuc.in
===================================================================
RCS file: /home/mercury1/repository/mercury/scripts/mgnuc.in,v
retrieving revision 1.53
diff -u -u -r1.53 mgnuc.in
--- mgnuc.in	1998/08/07 00:50:40	1.53
+++ mgnuc.in	1998/09/28 07:19:25
FACTOR OUT SHELL CODE HANDLING GRADE IMPLICATIONS
@@ -186,14 +186,8 @@
     shift
 done
 
-#
-# .debug grade implies --use-trail
-#	(see comment in compiler/handle_options.m for rationale)
-#
-case $stack_trace,$require_tracing in
-	true,true)
-		use_trail=true ;;
-esac
+# include the file `final_grade_options.sh-subr'
+ at FINAL_GRADE_OPTIONS@
 
 #
 # convert mgnuc options into gcc options
Index: scripts/ml.in
===================================================================
RCS file: /home/mercury1/repository/mercury/scripts/ml.in,v
retrieving revision 1.47
diff -u -u -r1.47 ml.in
--- ml.in	1998/09/29 05:11:33	1.47
+++ ml.in	1998/09/29 06:53:47
FACTOR OUT SHELL CODE HANDLING GRADE IMPLICATIONS
@@ -206,6 +206,9 @@
     shift
 done
 
+# include the file `final_grade_options.sh-subr'
+ at FINAL_GRADE_OPTIONS@
+
 # If you haven't set mercury_libs, set it to the default value
 # (shared on most systems). Note that if you have set all_libs,
 # it will also have set mercury_libs.
@@ -255,15 +258,6 @@
 			MAYBE_STATIC_OPT=-static
 			;;
 	esac
-esac
-
-#
-# .debug grade implies --use-trail
-#	(see comment in compiler/handle_options.m for rationale)
-#
-case $stack_trace,$require_tracing in
-	true,true)
-		use_trail=true ;;
 esac
 
 #
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
Index: tests/debugger/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/Mmakefile,v
retrieving revision 1.10
diff -u -u -r1.10 Mmakefile
--- Mmakefile	1998/09/29 05:11:38	1.10
+++ Mmakefile	1998/10/01 04:08:17
UPDATE TEST CASES
@@ -1,8 +1,8 @@
 #-----------------------------------------------------------------------------#
 
-main_target: check
+main_target:	check
 
-include ../Mmake.common
+include		../Mmake.common
 
 RM_C=:
 
@@ -15,11 +15,14 @@
 DEBUGGER_PROGS=	\
 	debugger_regs	\
 	interpreter	\
-#	queens
+	queens
 
-MCFLAGS = --trace all
+MCFLAGS = --trace deep
 C2INITFLAGS = -t
 
+# EXTRA_CFLAGS = -g -v
+# EXTRA_MLFLAGS = -g -v
+
 # Base grades `jump' and `fast' cannot be used with
 # stack layouts (which are required for tracing).
 
@@ -60,6 +63,11 @@
SIMPLIFY THE MAINTAINANCE OF CONSISTENCY BETWEEN DEBUGGER CODE AND DOCUMENTATION
 queens_lib.out: queens_lib queens_lib.inp
 	mdb ./queens_lib < queens_lib.inp > queens_lib.out
 
+mdb_command_test.out: queens mdb_command_test
+	-mdb ./queens < mdb_command_test \
+		| egrep "internal error in the trace help system" \
+		> mdb_command_test.out
+
 #-----------------------------------------------------------------------------#
 
 DEPS=		$(ALLPROGS:%=$(deps_subdir)%.dep)
@@ -75,7 +83,7 @@
 
 depend:		$(DEPENDS)
 
-check:		$(OUTS) $(RESS)
+check:		$(OUTS) $(RESS) mdb_command_test.res
 
 check_lib:	$(LIBOUTS) $(LIBRESS)
 
Index: tests/debugger/*.{inp,exp}
<omitted>
cvs diff: Diffing tests/general
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
Index: tools/bootcheck
===================================================================
RCS file: /home/mercury1/repository/mercury/tools/bootcheck,v
retrieving revision 1.64
diff -u -u -r1.64 bootcheck
--- bootcheck	1998/09/29 05:11:44	1.64
+++ bootcheck	1998/10/01 04:11:07
@@ -885,8 +885,18 @@
DOCUMENT NEW DEBUG COMMAND SET

 		export PATH
 	fi
 
+	# We need to give tests/debugger access to the mdbrc and mdb_doc
+	# files in the doc directory, without hardcoding their pathnames.
+	# We must also compensate for doc/mdbrc having hardcoded within it
+	# the *installed* pathname of mdb_doc and not its current pathname.
+	cat $root/doc/mdb_doc > $root/doc/test_mdbrc
+	sed -e '/^source/d' $root/doc/mdbrc >> $root/doc/test_mdbrc
+	MERCURY_DEBUGGER_INIT=$root/doc/test_mdbrc
+	export MERCURY_DEBUGGER_INIT
+
SIMPLIFY THE MAINTAINANCE OF CONSISTENCY BETWEEN DEBUGGER CODE AND DOCUMENTATION
 	if test -d ../tests
 	then
+		cp $root/doc/mdb_command_test.inp ../tests/debugger
 		if test "$testdir" = ""
 		then
 			cd ../tests
@@ -899,6 +909,7 @@
 		cd $root
 	elif test -d tests
 	then
+		cp $root/doc/mdb_command_test.inp tests/debugger
 		if test "$testdir" = ""
 		then
 			cd tests
cvs diff: Diffing trace
Index: trace/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/Mmakefile,v
retrieving revision 1.1
diff -u -u -r1.1 Mmakefile
--- Mmakefile	1998/09/29 05:11:49	1.1
+++ Mmakefile	1998/09/29 07:41:54
IMPLEMENT NEW DEBUGGER COMMAND SET
@@ -25,15 +25,24 @@
 
 # keep this list in alphabetical order, please
 HDRS		=	\
+			mercury_macros.h		\
 			mercury_trace.h			\
+			mercury_trace_alias.h		\
 			mercury_trace_external.h 	\
-			mercury_trace_internal.h
+			mercury_trace_help.h		\
+			mercury_trace_internal.h	\
+			mercury_trace_spy.h		\
+			mercury_trace_tables.h
 
 # keep this list in alphabetical order, please
 CFILES		= 	\
 			mercury_trace.c			\
+			mercury_trace_alias.c		\
 			mercury_trace_external.c 	\
-			mercury_trace_internal.c
+			mercury_trace_help.c		\
+			mercury_trace_internal.c	\
+			mercury_trace_spy.c		\
+			mercury_trace_tables.c
 
 OBJS		= $(CFILES:.c=.o)
 PIC_OBJS	= $(CFILES:.c=.$(EXT_FOR_PIC_OBJECTS))
Index: trace/mercury_macros.h
===================================================================
RCS file: mercury_macros.h
diff -N mercury_macros.h
--- /dev/null	Wed May 28 10:49:58 1997
+++ mercury_macros.h	Tue Sep 22 12:30:04 1998
IMPLEMENT NEW DEBUGGER COMMAND SET
@@ -0,0 +1,171 @@
+/*
+** Copyright (C) 1998 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.
+*/
+
+/*
+** mercury_macros.h defines macros that are useful in more than one
+** module of the Mercury runtime system.
+*/
+
+#ifndef MERCURY_MACROS_H
+#define MERCURY_MACROS_H
+
+/*
+** The MR_ensure_room_for_next macro works with a group of three variables
+** that follow the pattern
+**
+**	Item	widgets = NULL;
+**	int	widget_max = 0;
+**	int	widget_next = 0;
+**
+** where widgets is a pointer to a malloc'd array of items, widget_max
+** gives the number of elements in the array, and widget_next is the
+** index of the first free slot in the widgets array. Widget_max is
+** zero if and only if widgets is NULL.
+**
+** MR_ensure_room_for_next(widget, Item, INIT_SIZE) checks whether
+** there is enough room in the widgets array to add a new item.
+** If not, doubles the size of the existing widgets array, or
+** allocates an array of INIT_SIZE items if the widgets array
+** has not been initialized before.
+*/
+
+#define	MR_ensure_room_for_next(base, type, init)	  		    \
+	do {								    \
+		if (base##_next >= base##_max) {			    \
+			if (base##_max == 0) {				    \
+				base##_max = init;			    \
+				base##s = checked_malloc(		    \
+						base##_max * sizeof(type)); \
+			} else {					    \
+				base##_max *= 2;			    \
+				base##s = checked_realloc(base##s, 	    \
+						base##_max * sizeof(type)); \
+			}						    \
+		}							    \
+	} while(0)
+
+/*
+** MR_ensure_big_enough makes the same assumptions as MR_ensure_room_for_next,
+** and operates almost the same way. The exception is that it does not assume
+** that the array grows one item at a time; instead it ensures that the array
+** is big enough to contain the element at index `slot'. Since with this regime
+** there is no notion of the "next" slot, this macro does not access, nor does
+** it require the existence of, base##_next.
+*/
+
+#define	MR_ensure_big_enough(slot, base, type, init)	  		    \
+	do {								    \
+		if (slot >= base##_max) {				    \
+			if (base##_max == 0) {				    \
+				base##_max = max(init, slot + 1);	    \
+				base##s = checked_malloc(		    \
+						base##_max * sizeof(type)); \
+			} else {					    \
+				base##_max = max(base##_max * 2, slot + 1); \
+				base##s = checked_realloc(base##s, 	    \
+						base##_max * sizeof(type)); \
+			}						    \
+		}							    \
+	} while(0)
+
+/*
+** MR_ensure_big_enough2 works like MR_ensure_big_enough, except that
+** it resizes two arrays at once. These two arrays are named base##s1 and
+** base##s2, and since they are always the same size, they share the
+** base##_max variable.
+*/
+
+#define	MR_ensure_big_enough2(slot, base, s1, s2, type, init)  		    \
+	do {								    \
+		if (slot >= base##_max) {				    \
+			if (base##_max == 0) {				    \
+				base##_max = max(init, slot + 1);	    \
+				base##s1 = checked_malloc(		    \
+						base##_max * sizeof(type)); \
+				base##s2 = checked_malloc(		    \
+						base##_max * sizeof(type)); \
+			} else {					    \
+				base##_max = max(base##_max * 2, slot + 1); \
+				base##s1 = checked_realloc(base##s1, 	    \
+						base##_max * sizeof(type)); \
+				base##s2 = checked_realloc(base##s2, 	    \
+						base##_max * sizeof(type)); \
+			}						    \
+		}							    \
+	} while(0)
+
+/*
+** MR_bsearch(int next, int& element, bool& found, COMPARE)
+**
+** Given a sorted array, this macro performs a binary search.
+** If the search is successful, MR_bsearch sets the `found' parameter
+** to TRUE and the `element' parameter to the index of the desired item.
+** If the search is unsuccessful, MR_bsearch sets `found' to FALSE;
+** `element' will be clobbered.
+**
+** The number of the elements in the array is given by the `next' parameter.
+** The `COMPARE' parameter should be an expression which compares
+** the value at the index specified by the current value of `element'
+** with the desired value, and returns <0, 0, or >0 according to whether
+** it is less than, equal to, or greater than the desired value.
+**
+** The name of the array to be searched is not explicitly a parameter;
+** its identity is encoded in the boolean expression of the `COMPARE'
+** parameter.
+*/
+
+#define MR_bsearch(next, element, found, COMPARE)			\
+	do {								\
+		int	lo;						\
+		int	hi;						\
+		int	diff;						\
+									\
+		lo = 0;							\
+		hi = (next) - 1;					\
+		(found) = FALSE;					\
+		while (lo <= hi) {					\
+			(element) = (lo + hi) / 2;			\
+			diff = (COMPARE);				\
+			if (diff == 0) {				\
+				(found) = TRUE;				\
+				break;					\
+			} else if (diff < 0) {				\
+				lo = (element) + 1;			\
+			} else {					\
+				hi = (element) - 1;			\
+			}						\
+		}							\
+	} while(0)
+
+/*
+** MR_prepare_insert_into_sorted(array[], int& next, int& element, COMPARE)
+**
+** Given a sorted array `items', this prepares for the insertion of a new
+** item into the array at the proper point. It find the index at which
+** the new item should be inserted, and moves all items at and above that
+** index one position to the right to make room for the new item.
+**
+** The `next' parameter holds the number of elements in the array;
+** it is incremented by this macro. The macro returns the index of the slot
+** at which the new item should be inserted in the `element' parameter.
+** The `COMPARE' parameter should be an expression which compares
+** the item at the index specified by the current value of `element' with
+** the item being inserted, and returns <0, 0, or >0 according to whether
+** it is less than, equal to, or greater than the item being inserted.
+*/
+
+#define MR_prepare_insert_into_sorted(items, next, element, COMPARE)	\
+	do {								\
+		(element) = (next) - 1;					\
+		while ((element) >= 0 && COMPARE > 0) {			\
+			items[element + 1] = items[element];		\
+			(element) -= 1;					\
+		}							\
+		(element) += 1;						\
+		(next) += 1;						\
+	} while(0)
+
+#endif /* MERCURY_MACROS_H */
Index: trace/mercury_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace.c,v
retrieving revision 1.1
diff -u -u -r1.1 mercury_trace.c
--- mercury_trace.c	1998/09/29 05:11:50	1.1
+++ mercury_trace.c	1998/09/29 07:07:55
@@ -10,8 +10,6 @@
 ** The trace events can be processed either by our internal debugger,
 ** or by an external trace-analysis style debugger. These are in
 ** mercury_trace_internal.c and mercury_trace_external.c respectively.
-** Utility functions usable by both the internal and external debuggers
-** are in mercury_trace_util.c.
 **
 ** The C functions in all these modules which use any of the Mercury registers
 ** expect the transient registers to be in fake_reg, and the others to be in
@@ -20,113 +18,217 @@
 
 #include "mercury_imp.h"
 #include "mercury_trace.h"
-#include "mercury_trace_util.h"
 #include "mercury_trace_internal.h"
 #include "mercury_trace_external.h"
+#include "mercury_trace_spy.h"
+#include "mercury_layout_util.h"
+#include "mercury_memory.h"
 #include "mercury_engine.h"
 #include "mercury_wrapper.h"
 #include "mercury_misc.h"
+#include "mercury_macros.h"
 #include <stdio.h>
 #include <unistd.h>		/* for the write system call */
IMPLEMENT NEW DEBUGGER COMMAND SET
 
-static	MR_trace_cmd_info	MR_trace_ctrl = { MR_CMD_GOTO, 0, 0, FALSE };
+static	MR_Trace_Cmd_Info	MR_trace_ctrl = { MR_CMD_GOTO, 0, 0,
+					MR_PRINT_LEVEL_SOME, FALSE };
SUPPORT RETRY
USE FIXED STACK SLOTS FOR TRACE INFO
 
-static	void	MR_trace_event(MR_trace_cmd_info *cmd,
+static	Code	*MR_trace_event(MR_Trace_Cmd_Info *cmd, bool interactive,
 			const MR_Stack_Layout_Label *layout,
-			MR_trace_port port, Unsigned seqno, Unsigned depth,
+			MR_Trace_Port port, Unsigned seqno, Unsigned depth,
 			const char *path, int max_r_num);
 
-static	void	MR_trace_event_report(const MR_Stack_Layout_Label *layout,
-			MR_trace_port port, Unsigned seqno, Unsigned depth,
-			const char *path, int max_r_num);
ADD TRACE DEPTH HISTOGRAMS
+/*
+** Reserve room for event counts for this many depths initially.
+*/
 
+#define	INIT_HISTOGRAM	128
+
SUPPORT RETRY
USE FIXED STACK SLOTS FOR TRACE INFO
 /*
-** This function is called from compiled code whenever an event to be traced
+** MR_trace() is called from compiled code whenever an event to be traced
 ** occurs.
 */
 
-void
-MR_trace_real(const MR_Stack_Layout_Label *layout, MR_trace_port port,
+Code *
+MR_trace_real(const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
 	Unsigned seqno, Unsigned depth, const char *path, int max_r_num)
 {
+	MR_Spy_Action	action;
+	bool		match;
+
 	MR_trace_event_number++;
ADD TRACE DEPTH HISTOGRAMS
 
+#ifdef	MR_TRACE_HISTOGRAM
+
+	/*
+	** The depths do not necessarily increase one-by-one, since
+	** a procedure from a fully traced module can be called from
+	** deep within interface traced code.
+	*/
+
+	MR_ensure_big_enough2(depth, MR_trace_histogram, _all, _exp,
+		int, INIT_HISTOGRAM);
+
+	if (depth > MR_trace_histogram_hwm) {
+		MR_trace_histogram_hwm = depth;
+	}
+
+	MR_trace_histogram_all[depth]++;
+	MR_trace_histogram_exp[depth]++;
+
+#endif	/* MR_TRACE_HISTOGRAM */
+
IMPLEMENT NEW DEBUGGER COMMAND SET
 	switch (MR_trace_ctrl.MR_trace_cmd) {
 		case MR_CMD_FINISH:
-			if (MR_trace_ctrl.MR_trace_stop_seqno == seqno
-			&& MR_port_is_final(port)) {
-				MR_trace_event(&MR_trace_ctrl, layout,
-					port, seqno, depth, path, max_r_num);
-
-			} else if (MR_trace_ctrl.MR_trace_print_intermediate) {
-				MR_trace_event_report(layout,
-					port, seqno, depth, path, max_r_num);
+			if (MR_trace_ctrl.MR_trace_stop_depth == depth
+					&& MR_port_is_final(port))
+			{
+				return MR_trace_event(&MR_trace_ctrl, TRUE,
+						layout, port, seqno, depth,
+						path, max_r_num);
+			} else {
+				goto check_stop_print;
 			}
 
-			break;
-
 		case MR_CMD_GOTO:
 			if (MR_trace_event_number >=
-				MR_trace_ctrl.MR_trace_stop_event
-			|| MR_event_matches_spy_point(layout)) {
-				MR_trace_event(&MR_trace_ctrl, layout,
-					port, seqno, depth, path, max_r_num);
-			} else if (MR_trace_ctrl.MR_trace_print_intermediate) {
-				MR_trace_event_report(layout,
-					port, seqno, depth, path, max_r_num);
+					MR_trace_ctrl.MR_trace_stop_event)
+			{
+				return MR_trace_event(&MR_trace_ctrl, TRUE,
+						layout, port, seqno, depth,
+						path, max_r_num);
+			} else {
+				goto check_stop_print;
 			}
 
-			break;
-
 		case MR_CMD_RESUME_FORWARD:
-			if (MR_port_is_final(port)) {
-				MR_trace_event(&MR_trace_ctrl, layout,
-					port, seqno, depth, path, max_r_num);
-			} else if (MR_trace_ctrl.MR_trace_print_intermediate) {
-				MR_trace_event_report(layout,
-					port, seqno, depth, path, max_r_num);
+			if (! (port == MR_PORT_REDO || port == MR_PORT_FAIL)) {
+				return MR_trace_event(&MR_trace_ctrl, TRUE,
+						layout, port, seqno, depth,
+						path, max_r_num);
+			} else {
+				goto check_stop_print;
 			}
 
-			break;
+		case MR_CMD_RETURN:
+			if (port != MR_PORT_EXIT) {
+				return MR_trace_event(&MR_trace_ctrl, TRUE,
+						layout, port, seqno, depth,
+						path, max_r_num);
+			} else {
+				goto check_stop_print;
+			}
 
-		case MR_CMD_TO_END:
-			if (MR_event_matches_spy_point(layout)) {
-				MR_trace_event(&MR_trace_ctrl, layout,
-					port, seqno, depth, path, max_r_num);
-			} else if (MR_trace_ctrl.MR_trace_print_intermediate) {
-				MR_trace_event_report(layout,
-					port, seqno, depth, path, max_r_num);
+		case MR_CMD_MIN_DEPTH:
+			if (MR_trace_ctrl.MR_trace_stop_depth <= depth) {
+				return MR_trace_event(&MR_trace_ctrl, TRUE,
+						layout, port, seqno, depth,
+						path, max_r_num);
+			} else {
+				goto check_stop_print;
 			}
 
-			break;
+		case MR_CMD_MAX_DEPTH:
+			if (MR_trace_ctrl.MR_trace_stop_depth >= depth) {
+				return MR_trace_event(&MR_trace_ctrl, TRUE,
+						layout, port, seqno, depth,
+						path, max_r_num);
+			} else {
+				goto check_stop_print;
+			}
+
+		case MR_CMD_TO_END:
+			goto check_stop_print;
 
 		default:
-			fatal_error("invalid cmd in MR_trace");
-			break;
+			fatal_error("invalid command in MR_trace");
 	}
+
+check_stop_print:
+
+	if (MR_trace_ctrl.MR_trace_must_check) {
+		/*
+		** The value of MR_trace_ctrl.MR_trace_must_check was
+		** precomputed when the command was set up; it was set to TRUE
+		** iff either MR_trace_ctrl.MR_trace_strict is FALSE (allowing
+		** us to stop at breakpoints whose action is MR_SPY_STOP) or
+		** MR_trace_ctrl.MR_trace_print_level is something other than
+		** MR_PRINT_LEVEL_NONE (allowing us to print at least some
+		** events). The precomputation avoids several jumps in the
+		** very frequent case that MR_trace_must_check is false.
+		*/
+
+		match = MR_event_matches_spy_point(layout, port, &action);
+		if (! match) {
+			if (MR_trace_ctrl.MR_trace_print_level ==
+					MR_PRINT_LEVEL_ALL)
+			{
+				return MR_trace_event(&MR_trace_ctrl, FALSE,
+						layout, port, seqno, depth,
+						path, max_r_num);
+			}
+
+			return NULL;
+		}
+
+		if ((! MR_trace_ctrl.MR_trace_strict)
+				&& action == MR_SPY_STOP)
+		{
+			return MR_trace_event(&MR_trace_ctrl, TRUE,
+					layout, port, seqno, depth,
+					path, max_r_num);
+		}
+
+		if (MR_trace_ctrl.MR_trace_print_level != MR_PRINT_LEVEL_NONE) {
+			/*
+			** It doesn't matter whether action is MR_SPY_STOP or
+			** MR_SPY_PRINT; even if it is MR_SPY_STOP, we want
+			** to print it if printing is allowed and we did not
+			** stop.
+			*/
+
+			return MR_trace_event(&MR_trace_ctrl, FALSE,
+					layout, port, seqno, depth,
+					path, max_r_num);
+		}
+	}
+
+	return NULL;
 }
SUPPORT RETRY
USE FIXED STACK SLOTS FOR TRACE INFO
RECAST MERCURY_TRACE_UTIL AS MERCURY_LAYOUT_UTIL
 
-static void
-MR_trace_event(MR_trace_cmd_info *cmd,
-	const MR_Stack_Layout_Label *layout, MR_trace_port port,
+static Code *
+MR_trace_event(MR_Trace_Cmd_Info *cmd, bool interactive,
+	const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
 	Unsigned seqno, Unsigned depth, const char *path, int max_r_num)
 {
 	int	max_mr_num;
+	Code	*jumpaddr;
+	Word	saved_regs[MAX_FAKE_REG];
 
 	if (max_r_num + MR_NUM_SPECIAL_REG > MR_MAX_SPECIAL_REG_MR) {
 		max_mr_num = max_r_num + MR_NUM_SPECIAL_REG;
 	} else {
 		max_mr_num = MR_MAX_SPECIAL_REG_MR;
 	}
+
+	MR_copy_regs_to_saved_regs(max_mr_num, saved_regs);
 
-	MR_copy_regs_to_saved_regs(max_mr_num);
 #ifdef MR_USE_EXTERNAL_DEBUGGER
 	if (MR_trace_handler == MR_TRACE_EXTERNAL) {
-		MR_trace_event_external(cmd, layout, port, seqno, depth, path);
+		if (!interactive) {
+			fatal_error("reporting event for external debugger");
+		}
+
+		MR_trace_event_external(cmd, layout, saved_regs,
+			port, seqno, depth, path);
+		jumpaddr = NULL;
 	} else {
-		MR_trace_event_internal(cmd, layout, port, seqno, depth, path);
+		jumpaddr = MR_trace_event_internal(cmd, interactive,
+				layout, saved_regs, port, seqno,
+				depth, path, &max_mr_num);
 	}
 #else
 	/*
@@ -134,28 +236,20 @@
 	** This is enforced by mercury_wrapper.c.
 	*/
 
-	MR_trace_event_internal(cmd, layout, port, seqno, depth, path);
+	jumpaddr = MR_trace_event_internal(cmd, interactive,
+			layout, saved_regs, port, seqno,
+			depth, path, &max_mr_num);
 #endif
-	MR_copy_saved_regs_to_regs(max_mr_num);
-}
 
-static void
-MR_trace_event_report(const MR_Stack_Layout_Label *layout, MR_trace_port port,
-	Unsigned seqno, Unsigned depth, const char *path, int max_r_num)
-{
-#ifdef MR_USE_EXTERNAL_DEBUGGER
-	if (MR_trace_handler == MR_TRACE_EXTERNAL) {
-		fatal_error("trying to report an event to external debugger");
-	} else {
-		MR_trace_event_internal_report(layout,
-			port, seqno, depth, path);
-	}
-#else
 	/*
-	** We should get here only if MR_trace_handler == MR_TRACE_INTERNAL.
-	** This is enforced by mercury_wrapper.c.
+	** Whenever the debugger changes the flow of control, e.g. by
+	** executing a retry command, it also sets up the saved registers
+	** to the state that is appropriate for the label at which execution
+	** will resume. There may be more registers live at that point than
+	** at the point at which MR_trace was called. Therefore max_mr_num
+	** should also be set appropriately when executing a retry command.
 	*/
 
-	MR_trace_event_internal_report(layout, port, seqno, depth, path);
-#endif
+	MR_copy_saved_regs_to_regs(max_mr_num, saved_regs);
+	return jumpaddr;
 }
Index: trace/mercury_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace.h,v
retrieving revision 1.1
diff -u -u -r1.1 mercury_trace.h
--- mercury_trace.h	1998/09/29 05:11:51	1.1
+++ mercury_trace.h	1998/09/29 06:58:57
@@ -5,46 +5,22 @@
IMPLEMENT NEW DEBUGGER COMMAND SET
 */
 
 /*
-** mercury_trace.h has two functions.
+** mercury_trace.h defines the interface by which the internal and external
+** debuggers can control how the tracing subsystem treats events.
 **
-** (a)	It defines the interface between the tracing subsystem of the runtime
-**	and compiled code.
-**
-** (b)	It defines the interface by which the internal and external debuggers
-**	can control how the tracing subsystem treats events.
-**
 ** The macros, functions and variables of this module are intended to be
 ** referred to only from code generated by the Mercury compiler, and from
 ** hand-written code in the Mercury runtime or the Mercury standard library,
 ** and even then only if at least some part of the program was compiled
 ** with some form of execution tracing.
 **
-** The parts of the tracing system that need to be present even when no
-** part of the program is compiled with execution tracing are in the module
-** mercury_trace_base.
+** The parts of the tracing system that need to be present even when tracing
+** is not enabled are in the module runtime/mercury_trace_base.
 */
 
 #ifndef MERCURY_TRACE_H
 #define MERCURY_TRACE_H
 
-#include "mercury_trace_base.h"
-
-/* The interface between the tracing subsystem and compiled code. */
-
-#define	MR_trace_incr_seq()	(++MR_trace_call_seqno)
-#define	MR_trace_incr_depth()	(++MR_trace_call_depth)
-#define	MR_trace_reset_depth(d)	do { MR_trace_call_depth = (d); } while (0)
-
-extern	void	MR_trace_real(
-	const MR_Stack_Layout_Label *,	/* layout info for the event */
-	MR_trace_port,
-	Word,			/* call sequence number */
-	Word,			/* call depth */
-	const char *,		/* path to event goal within procedure */
-	int);			/* highest numbered rN register in use */
-
-/* The interface between the debuggers and the tracing subsystem. */
-
 /*
 ** MR_trace_cmd says what mode the tracer is in, i.e. how events should be
 ** treated.
@@ -54,11 +30,20 @@
 **
 ** If MR_trace_cmd == MR_CMD_FINISH, the event handler will stop at the next
 ** event that specifies the procedure invocation whose call number is in
-** MR_trace_stop_seqno and whose port is final.
+** MR_trace_stop_seqno and whose port is EXIT or FAIL.
 **
 ** If MR_trace_cmd == MR_CMD_RESUME_FORWARD, the event handler will stop at
-** the next event of any call whose port is *not* final.
+** the next event of any call whose port is *not* REDO or FAIL.
+**
+** If MR_trace_cmd == MR_CMD_RETURN, the event handler will stop at
+** the next event of any call whose port is *not* EXIT.
 **
+** If MR_trace_cmd == MR_CMD_MIN_DEPTH, the event handler will stop at
+** the next event of any call whose depth is at least MR_trace_stop_depth.
+**
+** If MR_trace_cmd == MR_CMD_MAX_DEPTH, the event handler will stop at
+** the next event of any call whose depth is at most MR_trace_stop_depth.
+**
 ** If MR_trace_cmd == MR_CMD_TO_END, the event handler will not stop
 ** until the end of the program.
 **
@@ -66,20 +51,42 @@
 ** summary line for the event if MR_trace_print_intermediate is true.
 */
 
+typedef enum {
+	MR_CMD_GOTO,
+	MR_CMD_FINISH,
+	MR_CMD_RESUME_FORWARD,
+	MR_CMD_RETURN,
+	MR_CMD_MIN_DEPTH,
+	MR_CMD_MAX_DEPTH,
+	MR_CMD_TO_END
+} MR_Trace_Cmd_Type;
+
 typedef enum {
-	MR_CMD_GOTO,		/* stop at an event with a given number    */
-	MR_CMD_FINISH,		/* stop when exiting/failing out of a proc */
-	MR_CMD_RESUME_FORWARD,	/* stop at the next non-final port         */
-	MR_CMD_TO_END		/* do not stop until the end of execution  */
-} MR_trace_cmd_type;
+	MR_PRINT_LEVEL_NONE,	/* no events at all                        */
+	MR_PRINT_LEVEL_SOME,	/* events matching an active spy point     */
+	MR_PRINT_LEVEL_ALL	/* all events                              */
+} MR_Trace_Print_Level;
 
 typedef struct {
-	MR_trace_cmd_type	MR_trace_cmd;	
-	Unsigned		MR_trace_stop_seqno;
-	Unsigned		MR_trace_stop_event;
-	bool			MR_trace_print_intermediate;
-} MR_trace_cmd_info;
+	MR_Trace_Cmd_Type	MR_trace_cmd;	
+	Unsigned		MR_trace_stop_depth;	/* if MR_CMD_FINISH */
+	Unsigned		MR_trace_stop_event;	/* if MR_CMD_GOTO   */
+	MR_Trace_Print_Level	MR_trace_print_level;
+	bool			MR_trace_strict;
+
+				/*
+				** The next field is an optimization;
+				** it must be set to !MR_trace_strict ||
+				** MR_trace_print_level != MR_PRINT_LEVEL_NONE
+				*/
+	bool			MR_trace_must_check;
+} MR_Trace_Cmd_Info;
+
+#define	MR_port_is_final(port)		((port) == MR_PORT_EXIT || \
+					(port) == MR_PORT_FAIL)
+
+#define	MR_port_is_interface(port)	((port) < MR_PORT_FAIL)
 
-#define	MR_port_is_final(port)	(port == MR_PORT_EXIT || port == MR_PORT_FAIL)
+#define	MR_port_is_entry(port)		((port) == MR_PORT_CALL)
 
 #endif /* MERCURY_TRACE_H */
Index: trace/mercury_trace_alias.c
===================================================================
RCS file: mercury_trace_alias.c
diff -N mercury_trace_alias.c
--- /dev/null	Wed May 28 10:49:58 1997
+++ mercury_trace_alias.c	Mon Sep 21 20:03:43 1998
IMPLEMENT NEW DEBUGGER COMMAND SET
@@ -0,0 +1,148 @@
+/*
+** Copyright (C) 1998 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.
+*/
+
+/*
+** mercury_trace_alias.h
+**
+** Author: zs.
+*/
+
+#include "mercury_imp.h"
+#include "mercury_trace_alias.h"
+#include "mercury_macros.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 the alias table. */
+#define	INIT_ALIAS_COUNT	32
+
+static	void		MR_trace_print_alias_num(FILE *fp, int slot);
+
+void
+MR_trace_add_alias(char *name, char **words, int word_count)
+{
+	bool	found;
+	int	slot;
+	int	i;
+	int	count;
+
+	MR_bsearch(MR_alias_record_next, slot, found,
+		strcmp(MR_alias_records[slot].MR_alias_name, name));
+	if (found) {
+		count = MR_alias_records[slot].MR_alias_word_count;
+		for (i = 0; i < count; i++) {
+			free(MR_alias_records[slot].MR_alias_words[i]);
+		}
+
+		free(MR_alias_records[slot].MR_alias_name);
+		free(MR_alias_records[slot].MR_alias_words);
+	} else {
+		MR_ensure_room_for_next(MR_alias_record, MR_Alias,
+			INIT_ALIAS_COUNT);
+		MR_prepare_insert_into_sorted(MR_alias_records,
+			MR_alias_record_next, slot,
+			strcmp(MR_alias_records[slot].MR_alias_name,
+				name));
+	}
+
+	MR_alias_records[slot].MR_alias_name = MR_copy_string(name);
+	MR_alias_records[slot].MR_alias_word_count = word_count;
+	MR_alias_records[slot].MR_alias_words = checked_malloc(word_count
+							* sizeof(char *));
+	for (i = 0; i < word_count; i++) {
+		MR_alias_records[slot].MR_alias_words[i]
+			= MR_copy_string(words[i]);
+	}
+}
+
+bool
+MR_trace_remove_alias(const char *name)
+{
+	bool	found;
+	int	slot;
+	int	i;
+	int	count;
+
+	MR_bsearch(MR_alias_record_next, slot, found,
+		strcmp(MR_alias_records[slot].MR_alias_name, name));
+	if (! found) {
+		return FALSE;
+	} else {
+		count = MR_alias_records[slot].MR_alias_word_count;
+		for (i = 0; i < count; i++) {
+			free(MR_alias_records[slot].MR_alias_words[i]);
+		}
+
+		free(MR_alias_records[slot].MR_alias_name);
+		free(MR_alias_records[slot].MR_alias_words);
+
+		for (i = slot; i < MR_alias_record_next - 1; i++) {
+			MR_alias_records[slot] = MR_alias_records[slot+1];
+		}
+
+		MR_alias_record_next--;
+
+		return TRUE;
+	}
+}
+
+bool
+MR_trace_lookup_alias(const char *name,
+	char ***words_ptr, int *word_count_ptr)
+{
+	bool	found;
+	int	slot;
+
+	MR_bsearch(MR_alias_record_next, slot, found,
+		strcmp(MR_alias_records[slot].MR_alias_name, name));
+	if (found) {
+		*word_count_ptr = MR_alias_records[slot].MR_alias_word_count;
+		*words_ptr = MR_alias_records[slot].MR_alias_words;
+		return TRUE;
+	} else {
+		return FALSE;
+	}
+}
+
+void
+MR_trace_print_alias(FILE *fp, const char *name)
+{
+	bool	found;
+	int	slot;
+
+	MR_bsearch(MR_alias_record_next, slot, found,
+		strcmp(MR_alias_records[slot].MR_alias_name, name));
+	if (found) {
+		MR_trace_print_alias_num(fp, slot);
+	} else {
+		fprintf(fp, "There is no such alias.\n");
+	}
+}
+
+void
+MR_trace_print_all_aliases(FILE *fp)
+{
+	int	slot;
+
+	for (slot = 0; slot < MR_alias_record_next; slot++) {
+		MR_trace_print_alias_num(fp, slot);
+	}
+}
+
+static void
+MR_trace_print_alias_num(FILE *fp, int slot)
+{
+	int	i;
+
+	fprintf(fp, "%-6s =>   ", MR_alias_records[slot].MR_alias_name);
+	for (i = 0; i < MR_alias_records[slot].MR_alias_word_count; i++) {
+		fprintf(fp, " %s", MR_alias_records[slot].MR_alias_words[i]);
+	}
+
+	fprintf(fp, "\n");
+}
Index: trace/mercury_trace_alias.h
===================================================================
RCS file: mercury_trace_alias.h
diff -N mercury_trace_alias.h
--- /dev/null	Wed May 28 10:49:58 1997
+++ mercury_trace_alias.h	Tue Sep 22 12:30:04 1998
IMPLEMENT NEW DEBUGGER COMMAND SET
@@ -0,0 +1,67 @@
+/*
+** Copyright (C) 1998 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.
+*/
+
+/*
+** mercury_trace_alias.h
+**
+** Defines the interface of the alias system for the internal debugger.
+*/
+
+#ifndef	MERCURY_TRACE_ALIAS_H
+#define MERCURY_TRACE_ALIAS_H
+
+#include <stdio.h>
+
+typedef struct {
+	char		*MR_alias_name;
+	char		**MR_alias_words;
+	int		MR_alias_word_count;
+} MR_Alias;
+
+/*
+** Add an alias with the given name and expansion to the list.
+** The name, the words in the expansion and the array of pointers to the
+** expansion will all be copied, so their storage can be released
+** when MR_trace_add_alias returns.
+**
+** Overwrites any previous alias with the same name.
+*/
+
+extern	void		MR_trace_add_alias(char *name, char **words,
+				int word_count);
+
+/*
+** Remove the given alias from the list. Returns FALSE if there is no
+** such alias, and TRUE if there was such an alias and the removal was
+** successful.
+*/
+
+extern	bool		MR_trace_remove_alias(const char *name);
+
+/*
+** Looks up whether the given alias exists. If yes, returns TRUE, and
+** sets *words_ptr to point to a vector of words forming the alias expansion,
+** and *word_count_ptr to the number of words in the expansion. If no,
+** returns FALSE.
+*/
+
+extern	bool		MR_trace_lookup_alias(const char *name,
+				char ***words_ptr, int *word_count_ptr);
+
+/*
+** Print the alias of the given name, if it exists, and an error message
+** if it does not.
+*/
+
+extern	void		MR_trace_print_alias(FILE *fp, const char *name);
+
+/*
+** Print all the aliases to the given file.
+*/
+
+extern	void		MR_trace_print_all_aliases(FILE *fp);
+
+#endif	/* MERCURY_TRACE_ALIAS_H */



More information about the developers mailing list