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

Zoltan Somogyi zs at cs.mu.OZ.AU
Wed Sep 16 18:21:33 AEST 1998


cvs diff: Diffing runtime
Index: runtime/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/Mmakefile,v
retrieving revision 1.38
diff -u -u -r1.38 Mmakefile
--- Mmakefile	1998/09/15 07:19:11	1.38
+++ Mmakefile	1998/09/15 08:28:22
@@ -14,7 +14,7 @@
 #-----------------------------------------------------------------------------#
 
 CFLAGS		= -I$(MERCURY_DIR)/runtime -I$(MERCURY_DIR)/boehm_gc -g \
-		  $(DLL_CFLAGS) $(EXTRA_CFLAGS)
+		  $(DLL_CFLAGS) $(EXTRA_CFLAGS) -O0
 MGNUC		= MERCURY_C_INCL_DIR=. $(SCRIPTS_DIR)/mgnuc
 MGNUCFLAGS	= --no-ansi $(EXTRA_MGNUCFLAGS) $(CFLAGS)
 MOD2C		= $(SCRIPTS_DIR)/mod2c
@@ -46,6 +46,7 @@
 			mercury_init.h		\
 			mercury_label.h		\
 			mercury_library_types.h	\
+			mercury_macros.h	\
 			mercury_memory.h	\
 			mercury_memory_zones.h	\
 			mercury_memory_handlers.h	\
@@ -70,9 +71,13 @@
 			mercury_thread.h	\
 			mercury_timing.h	\
 			mercury_trace.h		\
+			mercury_trace_alias.h	\
 			mercury_trace_base.h	\
 			mercury_trace_external.h \
+			mercury_trace_help.h	\
 			mercury_trace_internal.h \
+			mercury_trace_spy.h	\
+			mercury_trace_tables.h	\
 			mercury_trace_util.h	\
 			mercury_trail.h		\
 			mercury_types.h		\
@@ -128,9 +133,13 @@
 			mercury_thread.c	\
 			mercury_timing.c	\
 			mercury_trace.c		\
+			mercury_trace_alias.c	\
 			mercury_trace_base.c	\
 			mercury_trace_external.c \
+			mercury_trace_help.c	\
 			mercury_trace_internal.c \
+			mercury_trace_spy.c	\
+			mercury_trace_tables.c	\
 			mercury_trace_util.c	\
 			mercury_trail.c 	\
 			mercury_type_info.c	\
Index: runtime/mercury_agc_debug.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_agc_debug.c,v
retrieving revision 1.2
diff -u -u -r1.2 mercury_agc_debug.c
--- mercury_agc_debug.c	1998/08/10 06:40:12	1.2
+++ mercury_agc_debug.c	1998/08/10 07:04:37
@@ -154,7 +154,7 @@
 			}
 			                                
 			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 +191,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.9
diff -u -u -r1.9 mercury_conf_param.h
--- mercury_conf_param.h	1998/07/25 13:15:37	1.9
+++ mercury_conf_param.h	1998/09/08 06:48:24
@@ -187,6 +187,14 @@
 ** 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_engine.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_engine.c,v
retrieving revision 1.14
diff -u -u -r1.14 mercury_engine.c
--- mercury_engine.c	1998/08/24 08:24:38	1.14
+++ mercury_engine.c	1998/08/24 09:05:49
@@ -170,10 +170,10 @@
 **	That will copy the real registers we use to the fake_reg array.
 **
 **	Beware, however, that if you are planning to return to C code
-**	that did not #include "mercury_regs.h" (directly or via e.g. "mercury_imp.h"),
-**	and you have fiddled with the Mercury registers or invoked
-**	call_engine() or anything like that, then you will need to
-**	save the real registers that C is using before modifying the
+**	that did not #include "mercury_regs.h" (directly or via e.g.
+**	"mercury_imp.h"), and you have fiddled with the Mercury registers
+**	or invoked call_engine() or anything like that, then you will need
+**	to save the real registers that C is using before modifying the
 **	Mercury registers and then restore them afterwards.
 **
 **	The called routine may invoke C functions; currently this
@@ -532,18 +532,12 @@
 Define_extern_entry(do_last_succeed);
 Define_extern_entry(do_not_reached);
 
-MR_MAKE_STACK_LAYOUT_ENTRY(do_redo)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_fail)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_succeed)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_last_succeed)
-MR_MAKE_STACK_LAYOUT_ENTRY(do_not_reached)
-
 BEGIN_MODULE(special_labels_module)
-	init_entry(do_redo);
-	init_entry(do_fail);
-	init_entry(do_succeed);
-	init_entry(do_last_succeed);
-	init_entry(do_not_reached);
+	init_label(do_redo);
+	init_label(do_fail);
+	init_label(do_succeed);
+	init_label(do_last_succeed);
+	init_label(do_not_reached);
 BEGIN_CODE
 
 Define_entry(do_redo);
Index: runtime/mercury_goto.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_goto.h,v
retrieving revision 1.14
diff -u -u -r1.14 mercury_goto.h
--- mercury_goto.h	1998/09/04 11:26:10	1.14
+++ mercury_goto.h	1998/09/09 07:53:51
@@ -19,11 +19,14 @@
 #define entry(label) paste(_entry_,label)
 #define skip(label) paste(skip_,label)
 
-#if defined(MR_USE_STACK_LAYOUTS)
-  #define MR_ENTRY_LAYOUT(label)	(const MR_Stack_Layout_Entry *) (Word) \
+#define MR_ALWAYS_ENTRY_LAYOUT(label)	(const MR_Stack_Layout_Entry *) (Word) \
 	&(paste(mercury_data__layout__,label))
-  #define MR_INTERNAL_LAYOUT(label)	(const MR_Stack_Layout_Label *) (Word) \
+#define MR_ALWAYS_INTERNAL_LAYOUT(label)(const MR_Stack_Layout_Label *) (Word) \
 	&(paste(mercury_data__layout__,label))
+
+#if defined(MR_USE_STACK_LAYOUTS)
+  #define MR_ENTRY_LAYOUT(label)	MR_ALWAYS_ENTRY_LAYOUT(label)
+  #define MR_INTERNAL_LAYOUT(label)	MR_ALWAYS_INTERNAL_LAYOUT(label)
 #else
   #define MR_ENTRY_LAYOUT(label)	(const MR_Stack_Layout_Entry *) NULL
   #define MR_INTERNAL_LAYOUT(label)	(const MR_Stack_Layout_Label *) NULL
@@ -39,34 +42,43 @@
 ** The versions of the macros below with the _sl suffix assume that the label
 ** that they are applied to has a stack layout record; the versions without
 ** do not. This governs whether they try to pass the address of this record
-** to insert_entry().
+** to MR_insert_*_label().
 */
 
 #if defined(MR_INSERT_LABELS)
   #define make_label(n, a, l)		MR_insert_internal_label(n, a, NULL)
   #define make_label_sl(n, a, l)	\
-  		MR_insert_internal_label(n, a, MR_INTERNAL_LAYOUT(l))
+		MR_insert_internal_label(n, a, MR_INTERNAL_LAYOUT(l))
+  #define make_label_asl(n, a, l)	\
+		MR_insert_internal_label(n, a, MR_ALWAYS_INTERNAL_LAYOUT(l))
 #else
   #define make_label(n, a, l)		/* nothing */
   #define make_label_sl(n, a, l)	/* nothing */
+  #define make_label_asl(n, a, l)	/* nothing */
 #endif
 
 #if defined(MR_INSERT_LABELS) || defined(PROFILE_CALLS)
   #define make_local(n, a, l)		MR_insert_internal_label(n, a, NULL)
   #define make_local_sl(n, a, l)	\
-  		MR_insert_internal_label(n, a, MR_INTERNAL_LAYOUT(l))
+		MR_insert_internal_label(n, a, MR_INTERNAL_LAYOUT(l))
+  #define make_local_asl(n, a, l)	\
+		MR_insert_internal_label(n, a, MR_ALWAYS_INTERNAL_LAYOUT(l))
 #else 
   #define make_local(n, a, l)		/* nothing */
   #define make_local_sl(n, a, l)	/* nothing */
+  #define make_local_asl(n, a, l)	/* nothing */
 #endif
 
 #if defined(MR_INSERT_LABELS) || defined(PROFILE_CALLS)
   #define make_entry(n, a, l)		MR_insert_entry_label(n, a, NULL)
   #define make_entry_sl(n, a, l)	\
   		MR_insert_entry_label(n, a, MR_ENTRY_LAYOUT(l))
+  #define make_entry_asl(n, a, l)	\
+  		MR_insert_entry_label(n, a, MR_ALWAYS_ENTRY_LAYOUT(l))
 #else
   #define make_entry(n, a, l)		/* nothing */
   #define make_entry_sl(n, a, l)	/* nothing */
+  #define make_entry_asl(n, a, l)	/* nothing */
 #endif
 
 #ifdef SPLIT_C_FILES
@@ -483,12 +495,25 @@
     ** prevent an over-zealous gcc from optimizing away `label'
     ** and the code that followed. 
     */
-    #define init_entry(label)	\
-	PRETEND_ADDRESS_IS_USED(&&label); \
+    #define init_entry(label)				\
+	PRETEND_ADDRESS_IS_USED(&&label);		\
 	make_entry(stringify(label), label, label)
-    #define init_entry_sl(label)	\
-	PRETEND_ADDRESS_IS_USED(&&label); \
+    #define init_entry_sl(label)			\
+	PRETEND_ADDRESS_IS_USED(&&label);		\
 	make_entry_sl(stringify(label), label, label)
+    #define init_entry_asl(label)			\
+	PRETEND_ADDRESS_IS_USED(&&label);		\
+	make_entry_asl(stringify(label), label, label)
+    #define MR_always_init_entry(label)			\
+	PRETEND_ADDRESS_IS_USED(&&label);		\
+	MR_insert_entry_label(stringify(label), label, NULL)
+    #define MR_always_init_entry_sl(label)		\
+	PRETEND_ADDRESS_IS_USED(&&label);		\
+	MR_insert_entry_label(stringify(label), label, MR_ENTRY_LAYOUT(label))
+    #define MR_always_init_entry_asl(label)		\
+	PRETEND_ADDRESS_IS_USED(&&label); 		\
+	MR_insert_entry_label(stringify(label), label,	\
+		MR_ALWAYS_ENTRY_LAYOUT(label))
 
     #define ENTRY(label) 	(&label)
     #define STATIC(label) 	(&label)
@@ -513,12 +538,26 @@
 	entry(label): \
 	label:	\
 	{
-    #define init_entry(label)	\
-	make_entry(stringify(label), &&label, label);	\
+    #define init_entry(label)					\
+	make_entry(stringify(label), &&label, label);		\
 	entry(label) = &&label
-    #define init_entry_sl(label)	\
+    #define init_entry_sl(label)				\
 	make_entry_sl(stringify(label), &&label, label);	\
 	entry(label) = &&label
+    #define init_entry_asl(label)				\
+	make_entry_asl(stringify(label), &&label, label);	\
+	entry(label) = &&label
+    #define MR_always_init_entry(label)				\
+	MR_insert_entry_label(stringify(label), &&label, NULL);	\
+	entry(label) = &&label
+    #define MR_always_init_entry_sl(label)			\
+	MR_insert_entry_label(stringify(label), &&label, 	\
+		MR_ENTRY_LAYOUT(label));			\
+	entry(label) = &&label
+    #define MR_always_init_entry_asl(label)			\
+	MR_insert_entry_label(stringify(label), &&label,	\
+		MR_ALWAYS_ENTRY_LAYOUT(label)));		\
+	entry(label) = &&label
     #define ENTRY(label) 	(entry(label))
     #define STATIC(label) 	(entry(label))
 
@@ -536,16 +575,45 @@
 	{
   #define init_local(label)	make_local(stringify(label), &&label, label)
   #define init_local_sl(label)	make_local_sl(stringify(label), &&label, label)
+  #define init_local_asl(label)	make_local_asl(stringify(label), &&label, label)
+  #define MR_always_init_local(label)		\
+	MR_insert_internal_label(stringify(label), &&label, NULL)
+  #define MR_always_init_local_sl(label)	\
+	MR_insert_internal_label(stringify(label), &&label, \
+		MR_INTERNAL_LAYOUT(label))
+  #define MR_always_init_local_asl(label)	\
+	MR_insert_internal_label(stringify(label), &&label, \
+		MR_ALWAYS_INTERNAL_LAYOUT(label))
   #define Define_label(label)	Define_local(label)
   #define Declare_label(label)	/* no declaration required */
   #ifdef MR_INSERT_LABELS
-   #define init_label(label)	\
+   #define init_label(label)		\
 	make_label(stringify(label), &&entry(label), label)
-   #define init_label_sl(label)	\
+   #define init_label_sl(label)		\
 	make_label_sl(stringify(label), &&entry(label), label)
+   #define init_label_asl(label)	\
+	make_label_asl(stringify(label), &&entry(label), label)
+   #define MR_always_init_label(label)	\
+	MR_insert_internal_label(stringify(label), &&entry(label), NULL)
+   #define MR_always_init_label_sl(label)	\
+	MR_insert_internal_label(stringify(label), &&entry(label), \
+		 MR_INTERNAL_LAYOUT(label))
+   #define MR_always_init_label_asl(label)	\
+	MR_insert_internal_label(stringify(label), &&entry(label), \
+		 MR_ALWAYS_INTERNAL_LAYOUT(label))
   #else
    #define init_label(label)	make_label(stringify(label), &&label, label)
    #define init_label_sl(label)	make_label_sl(stringify(label), &&label, label)
+   #define init_label_asl(label)		\
+	make_label_asl(stringify(label), &&label, label)
+   #define MR_always_init_label(label)	\
+	MR_insert_internal_label(stringify(label), &&label, NULL)
+   #define MR_always_init_label_sl(label)	\
+	MR_insert_internal_label(stringify(label), &&label, \
+		 MR_INTERNAL_LAYOUT(label))
+   #define MR_always_init_label_asl(label)	\
+	MR_insert_internal_label(stringify(label), &&label, \
+		 MR_ALWAYS_INTERNAL_LAYOUT(label))
   #endif
 
   #define LOCAL(label)		(&&entry(label))
@@ -586,6 +654,16 @@
 	static Code* label(void) {
   #define init_entry(label)	make_entry(stringify(label), label, label)
   #define init_entry_sl(label)	make_entry_sl(stringify(label), label, label)
+  #define init_entry_asl(label)	make_entry_asl(stringify(label), label, label)
+  #define MR_always_init_entry(label)			\
+	MR_insert_entry_label(stringify(label), label, NULL)
+		 MR_ALWAYS_INTERNAL_LAYOUT(label))
+  #define MR_always_init_entry_sl(label)		\
+	MR_insert_entry_label(stringify(label), label,	\
+		 MR_INTERNAL_LAYOUT(label))
+  #define MR_always_init_entry_asl(label)		\
+	MR_insert_entry_label(stringify(label), label,	\
+		 MR_ALWAYS_INTERNAL_LAYOUT(label))
 
   #define Declare_local(label)	static Code *label(void)
   #define Define_local(label)		\
@@ -594,6 +672,15 @@
 	static Code* label(void) {
   #define init_local(label)	make_local(stringify(label), label, label)
   #define init_local_sl(label)	make_local_sl(stringify(label), label, label)
+  #define init_local_asl(label)	make_local_asl(stringify(label), label, label)
+  #define MR_always_init_local(label)				\
+	MR_insert_internal_label(stringify(label), label, NULL)
+  #define MR_always_init_local_sl(label)			\
+	MR_insert_internal_label(stringify(label), label,	\
+		 MR_INTERNAL_LAYOUT(label))
+  #define MR_always_init_local_asl(label)		 	\
+	MR_insert_internal_label(stringify(label), label,	\
+		 MR_ALWAYS_INTERNAL_LAYOUT(label))
 
   #define Declare_label(label)	static Code *label(void)
   #define Define_label(label)		\
@@ -602,6 +689,15 @@
 	static Code* label(void) {
   #define init_label(label)	make_label(stringify(label), label, label)
   #define init_label_sl(label)	make_label_sl(stringify(label), label, label)
+  #define init_label_asl(label)	make_label_asl(stringify(label), label, label)
+  #define MR_always_init_label(label)				\
+	MR_insert_internal_label(stringify(label), label, NULL)
+  #define MR_always_init_label_sl(label)			\
+	MR_insert_internal_label(stringify(label), label,	\
+		 MR_INTERNAL_LAYOUT(label))
+  #define MR_always_init_label_asl(label)			\
+	MR_insert_internal_label(stringify(label), label,	\
+		 MR_ALWAYS_INTERNAL_LAYOUT(label))
 
   #define ENTRY(label) 		((Code *) (label))
   #define STATIC(label) 	((Code *) (label))
Index: runtime/mercury_label.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_label.c,v
retrieving revision 1.10
diff -u -u -r1.10 mercury_label.c
--- mercury_label.c	1998/09/15 07:19:23	1.10
+++ mercury_label.c	1998/09/15 08:29:42
@@ -248,5 +248,6 @@
 void
 MR_process_all_internal_labels(void f(const void *))
 {
+	MR_do_init_label_tables();
 	MR_process_all_entries(internal_addr_table, f);
 }
Index: runtime/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	Wed Jul 29 13:28:20 1998
@@ -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 indexs 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: runtime/mercury_memory.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory.c,v
retrieving revision 1.13
diff -u -u -r1.13 mercury_memory.c
--- mercury_memory.c	1998/08/24 08:24:45	1.13
+++ mercury_memory.c	1998/08/24 09:05:52
@@ -244,16 +244,16 @@
 {
 #ifdef CONSERVATIVE_GC
 	GC_FREE(ptr);
-
 #else
 	free(ptr);
 #endif
 }
+
+/*
+** Note: checked_malloc()ed structures never contain pointers into GCed memory,
+** so we don't need to GC_malloc() them. (cf. newmem())
+*/
 
-		/* Note: checked_malloc()ed structures */
-		/* never contain pointers into GCed    */
-		/* memory, so we don't need to         */
-		/* GC_malloc() them. (cf. newmem())    */
 void *
 checked_malloc(size_t n)
 {
@@ -267,7 +267,6 @@
 	return p;
 }
 
-
 void *
 checked_realloc(void *old, size_t n)
 {
@@ -281,3 +280,14 @@
 	return p;
 }
 
+char *
+MR_copy_string(const char *s)
+{
+	int	len;
+	char	*copy;
+
+	len = strlen(s);
+	copy = checked_malloc(len + 1);
+	strcpy(copy, s);
+	return copy;
+}
Index: runtime/mercury_memory.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory.h,v
retrieving revision 1.7
diff -u -u -r1.7 mercury_memory.h
--- mercury_memory.h	1998/07/22 07:52:54	1.7
+++ mercury_memory.h	1998/07/23 06:38:11
@@ -51,6 +51,7 @@
 ** For these functions, see the comments in mercury_memory.c and 
 ** mercury_engine.c 
 */
+
 extern	void	init_memory(void);
 extern	void	init_heap(void);
 extern	void	debug_memory(void);
@@ -82,7 +83,6 @@
 
 void deallocate_memory(void *);
 
-
 /*
 ** checked_malloc() and checked_realloc() are like the standard C
 ** malloc() and realloc() functions, except that the return values
@@ -94,16 +94,22 @@
 */
 
 #include <stddef.h>	/* for size_t */
-void *checked_malloc(size_t n);
-void *checked_realloc(void *old, size_t n);
+void	*checked_malloc(size_t n);
+void	*checked_realloc(void *old, size_t n);
+
+/*
+** MR_copy_string makes a copy of the given string with checked_malloc.
+*/
+
+char	*MR_copy_string(const char *s);
 
 /*
 ** `unit' is the size of the minimum unit of memory we allocate (in bytes).
 ** `page_size' is the size of a single page of memory.
 */
 
-extern size_t          unit;
-extern size_t          page_size;
+extern	size_t          unit;
+extern	size_t          page_size;
 
 /*
 ** Users need to call MR_add_root() for any global variable which
Index: runtime/mercury_misc.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_misc.c,v
retrieving revision 1.12
diff -u -u -r1.12 mercury_misc.c
--- mercury_misc.c	1998/08/24 08:24:48	1.12
+++ mercury_misc.c	1998/08/25 04:24:56
@@ -500,12 +500,25 @@
 	exit(EXIT_FAILURE);
 }
 
-	/* See header file for documentation on why we need this function */
+/*
+** See header file for documentation on why we need these two functions.
+*/
+
 void
 MR_memcpy(char *dest, const char *src, size_t nbytes)
 {
 	while (nbytes-- > 0)
 		*dest++ = *src++;
+}
+
+void
+MR_memcpy_fromhigh(char *dest, const char *src, size_t nbytes)
+{
+	dest += nbytes;
+	src += nbytes;
+
+	while (nbytes-- > 0)
+		*--dest = *--src;
 }
 
 /*
Index: runtime/mercury_misc.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_misc.h,v
retrieving revision 1.9
diff -u -u -r1.9 mercury_misc.h
--- mercury_misc.h	1998/08/19 07:45:24	1.9
+++ mercury_misc.h	1998/08/24 09:05:54
@@ -9,7 +9,7 @@
 **			MR_warning(),
 **			fatal_error(),
 **			checked_malloc(),
-**			MR_memcpy
+**			MR_memcpy/MR_memrevcpy
 */
 
 #ifndef	MERCURY_MISC_H
@@ -68,9 +68,16 @@
 ** standard memcpy and generates inline code for them. Unfortunately this
 ** causes it to abort because it tries to use a register that we're already
 ** reserved.
+**
 ** XXX We should fix this eventually by using -fno-builtin since pragma
 ** c_code may call the builtin functions.
+**
+** MR_memcpy does the copying from the low bytes first; MR_memcpy_fromhigh
+** does the copying from the high bytes first. If the src and dest arrays
+** overlap, you must be careful to call the right version.
 */
+
 extern	void	MR_memcpy(char *dest, const char *src, size_t nbytes);
+extern	void	MR_memcpy_fromhigh(char *dest, const char *src, size_t nbytes);
 
 #endif /* not MERCURY_MISC_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/15 08:19:38
@@ -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 @@
 	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 @@
 ** 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,31 +262,75 @@
 		(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
 ** the code address for the label.
-*/ 
+*/
+
+#define MR_DEFINE_STACK_LAYOUT_ENTRY(l) 				\
+	const struct mercury_data__layout__##l##_struct {		\
+		Code	*f1;						\
+		Integer	f2;						\
+		Integer	f3;						\
+		Integer	f4;						\
+		Integer	f5;						\
+	} mercury_data__layout__##l = {					\
+		STATIC(l),						\
+		(Integer) -1, 	/* Unknown determinism */		\
+		(Integer) -1,	/* Unknown number of stack slots */	\
+		(Integer) MR_LVAL_TYPE_UNKNOWN,	/* Unknown succip locn */\
+		(Integer) -1, 	/* Procid component is not present */	\
+	};
 
 #ifdef MR_USE_STACK_LAYOUTS
-  #define MR_MAKE_STACK_LAYOUT_ENTRY(l) 				\
-  const struct mercury_data__layout__##l##_struct {			\
-	Code	*f1;							\
-	Integer	f2;							\
-	Integer	f3;							\
-	Integer	f4;							\
-	Integer	f5;							\
-  } mercury_data__layout__##l = {					\
-	STATIC(l),							\
-	(Integer) -1, 	/* Unknown determinism */			\
-	(Integer) -1,	/* Unknown number of stack slots */		\
-        (Integer) MR_LVAL_TYPE_UNKNOWN,	/* Unknown succip location */	\
-	(Integer) -1, 	/* The procid component is not present */	\
-  };
+  #define MR_MAKE_STACK_LAYOUT_ENTRY(l)	\
+	MR_DEFINE_STACK_LAYOUT_ENTRY(l)
 #else
-  #define MR_MAKE_STACK_LAYOUT_ENTRY(l)        
+  #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)
+
 /*-------------------------------------------------------------------------*/
 /*
 ** Definitions for MR_Stack_Layout_Label
@@ -310,21 +365,24 @@
 **
 ** The only useful information in this structure is the code address
 ** and the reference to the entry for this label.
-*/ 
+*/
 
+#define MR_DEFINE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)		\
+	const struct mercury_data__layout__##l##_struct {		\
+		const Word *f1;						\
+		UNKNOWN_INTERNAL_LABEL_FIELD				\
+		Integer f3;						\
+	} mercury_data__layout__##l = {					\
+		(const Word *) &mercury_data__layout__##e,		\
+		UNKNOWN_INTERNAL_LABEL_NUMBER				\
+		(Integer) -1	/* No information about live values */	\
+	};
+
 #ifdef MR_USE_STACK_LAYOUTS
-  #define MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)		\
-  const struct mercury_data__layout__##l##_struct {			\
-	const Word *f1;							\
-	UNKNOWN_INTERNAL_LABEL_FIELD					\
-	Integer f3;							\
-  } mercury_data__layout__##l = {					\
-	(const Word *) &mercury_data__layout__##e,			\
-	UNKNOWN_INTERNAL_LABEL_NUMBER					\
-	(Integer) -1		/* No information about live values */	\
-  };
+  #define MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)	\
+	MR_DEFINE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)
 #else
-  #define MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)        
+  #define MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY(l, e)
 #endif	/* MR_USE_STACK_LAYOUTS */
 
 /*
@@ -333,29 +391,32 @@
 ** label_name_i3, x is 3. It is assumed the entry label for that
 ** corresponds to this label is the label name without the _iX suffix.
 **
-** (MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY, above, is a little
-** more general than MR_MAKE_STACK_LAYOUT_INTERNAL. This macro can
+** (MR_DEFINE_STACK_LAYOUT_INTERNAL_WITH_ENTRY, above, is a little
+** more general than MR_DEFINE_STACK_LAYOUT_INTERNAL. This macro can
 ** only describe relationships between labels that have the same
-** base -- MR_MAKE_STACK_LAYOUT_INTERNAL_WITH_ENTRY can create layouts
+** base -- MR_DEFINE_STACK_LAYOUT_INTERNAL_WITH_ENTRY can create layouts
 ** for internal labels no matter what the name of the entry layout is).
 **
 ** The only useful information in this structure is the code address
 ** and the reference to the entry for this label.
-*/ 
+*/
+
+#define MR_DEFINE_STACK_LAYOUT_INTERNAL(e, x)				\
+	const struct mercury_data__layout__##e##_i##x##_struct {	\
+		const Word *f1;						\
+		UNKNOWN_INTERNAL_LABEL_FIELD				\
+		Integer f3;						\
+	} mercury_data__layout__##e##_i##x = {				\
+		(const Word *) &mercury_data__layout__##e,		\
+		UNKNOWN_INTERNAL_LABEL_NUMBER				\
+		(Integer) -1	/* No information about live values */	\
+	};
 
 #ifdef MR_USE_STACK_LAYOUTS
-  #define MR_MAKE_STACK_LAYOUT_INTERNAL(e, x)				\
-  const struct mercury_data__layout__##e##_i##x##_struct {		\
-	const Word *f1;							\
-	UNKNOWN_INTERNAL_LABEL_FIELD					\
-	Integer f3;							\
-  } mercury_data__layout__##e##_i##x = {				\
-	(const Word *) &mercury_data__layout__##e,			\
-	UNKNOWN_INTERNAL_LABEL_NUMBER					\
-	(Integer) -1		/* No information about live values */	\
-  };
+  #define MR_MAKE_STACK_LAYOUT_INTERNAL(e, x)        \
+	MR_DEFINE_STACK_LAYOUT_INTERNAL(e, x)
 #else
-  #define MR_MAKE_STACK_LAYOUT_INTERNAL(l, x)        
+  #define MR_MAKE_STACK_LAYOUT_INTERNAL(e, x)
 #endif	/* MR_USE_STACK_LAYOUTS */
 
 #endif /* not MERCURY_STACK_LAYOUT_H */
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.16
diff -u -u -r1.16 mercury_stack_trace.c
--- mercury_stack_trace.c	1998/07/29 08:56:03	1.16
+++ mercury_stack_trace.c	1998/08/19 10:30:19
@@ -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 {
@@ -286,15 +287,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.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace.c,v
retrieving revision 1.17
diff -u -u -r1.17 mercury_trace.c
--- mercury_trace.c	1998/07/23 20:12:23	1.17
+++ mercury_trace.c	1998/08/12 09:21:11
@@ -1,4 +1,8 @@
 /*
+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.
@@ -20,104 +24,188 @@
 ** Main author: Zoltan Somogyi.
 */
 
+#define	MR_STACK_TRACE_THIS_MODULE
 #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_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 */
 
-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 };
 
-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);
+/*
+** Reserve room for event counts for this many depths initially.
+*/
+
+#define	INIT_HISTOGRAM	128
 
 /*
-** 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(const MR_Stack_Layout_Label *layout, MR_trace_port port,
-	Unsigned seqno, Unsigned depth, const char *path, int max_r_num,
-	bool trace_this)
+Code *
+MR_trace(const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
+	const char *path, int max_r_num)
 {
-	if (! (MR_trace_enabled && trace_this))
-		return;
+	MR_Spy_Action	action;
+	bool		match;
+	Unsigned	seqno;
+	Unsigned	depth;
+	bool		maybe_from_full;
+
+	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);
+	}
+
 	MR_trace_event_number++;
 
+#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 */
+
 	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);
+				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_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);
-			}
-
-			break;
+			goto check_stop_print;
 
 		default:
 			fatal_error("invalid cmd in MR_trace");
-			break;
 	}
+
+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;
 }
 
-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;
 
 	if (max_r_num + MR_NUM_SPECIAL_REG > MR_MAX_SPECIAL_REG_MR) {
 		max_mr_num = max_r_num + MR_NUM_SPECIAL_REG;
@@ -126,11 +214,18 @@
 	}
 
 	MR_copy_regs_to_saved_regs(max_mr_num);
+
 #ifdef MR_USE_EXTERNAL_DEBUGGER
 	if (MR_trace_handler == MR_TRACE_EXTERNAL) {
+		if (!interactive) {
+			fatal_error("reporting event for external debugger");
+		}
+
 		MR_trace_event_external(cmd, layout, 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, port, seqno, depth, path, &max_mr_num);
 	}
 #else
 	/*
@@ -138,28 +233,46 @@
 	** 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, 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_copy_saved_regs_to_regs(max_mr_num);
+	return jumpaddr;
+}
+
+Define_extern_entry(MR_do_trace_redo_fail);
 
-	MR_trace_event_internal_report(layout, port, seqno, depth, path);
+BEGIN_MODULE(MR_trace_labels_module)
+	init_label(MR_do_trace_redo_fail);
+BEGIN_CODE
+
+Define_entry(MR_do_trace_redo_fail);
+#if 0
+	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.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace.h,v
retrieving revision 1.10
diff -u -u -r1.10 mercury_trace.h
--- mercury_trace.h	1998/07/17 06:35:14	1.10
+++ mercury_trace.h	1998/08/12 09:11:53
@@ -31,9 +31,11 @@
 
 /* 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)
+#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)	do {					     \
+					MR_trace_call_depth = (Unsigned) (d);\
+				} while (0)
 
 /*
 ** This enum should EXACTLY match the definition of the `trace_port_type' type
@@ -42,6 +44,7 @@
 typedef	enum {
 	MR_PORT_CALL,
 	MR_PORT_EXIT,
+	MR_PORT_REDO,
 	MR_PORT_FAIL,
 	MR_PORT_THEN,
 	MR_PORT_ELSE,
@@ -49,16 +52,16 @@
 	MR_PORT_SWITCH,
 	MR_PORT_PRAGMA_FIRST,
 	MR_PORT_PRAGMA_LATER
-} MR_trace_port;
+} MR_Trace_Port;
 
-extern	void	MR_trace(
-	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 */
-	bool);			/* is this event supposed to be traced */
+extern	Code	*MR_trace(	/* if the return value is non-NULL, 	*/
+				/* it gives an address to jump to	*/
+		const MR_Stack_Layout_Label *,
+				/* layout info for the event		*/
+		MR_Trace_Port,
+		const char *,	/* path to event goal within procedure	*/
+		int		/* highest numbered rN register in use	*/
+	);
 
 /* The interface between the debuggers and the tracing subsystem. */
 
@@ -88,15 +91,34 @@
 	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_Trace_Cmd_Type;
 
+typedef enum {
+	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: runtime/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	Wed Sep  9 15:34:40 1998
@@ -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: runtime/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	Sun Jul 12 16:41:51 1998
@@ -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 */
Index: runtime/mercury_trace_base.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_base.c,v
retrieving revision 1.1
diff -u -u -r1.1 mercury_trace_base.c
--- mercury_trace_base.c	1998/07/03 05:34:46	1.1
+++ mercury_trace_base.c	1998/09/09 05:45:51
@@ -30,7 +30,7 @@
 ** 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,
@@ -89,6 +89,11 @@
 
 Bool		MR_trace_from_full = 1;
 
+int		*MR_trace_histogram_all = NULL;
+int		*MR_trace_histogram_exp = NULL;
+int		MR_trace_histogram_max  = 0;
+int		MR_trace_histogram_hwm  = 0;
+
 void
 MR_trace_init(void)
 {
@@ -134,6 +139,22 @@
 
 		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 */
 	}
 }
 
@@ -151,5 +172,22 @@
 		sprintf(buf, "Last trace event was event #%ld.\n",
 			(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");
+		}
 	}
 }
Index: runtime/mercury_trace_base.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_base.h,v
retrieving revision 1.1
diff -u -u -r1.1 mercury_trace_base.h
--- mercury_trace_base.h	1998/07/03 05:34:47	1.1
+++ mercury_trace_base.h	1998/09/09 05:46:11
@@ -11,8 +11,8 @@
 ** is compiled with execution tracing.
 */
 
-#ifndef MERCURY_TRACE_PERMANENT_H
-#define MERCURY_TRACE_PERMANENT_H
+#ifndef MERCURY_TRACE_BASE_H
+#define MERCURY_TRACE_BASE_H
 
 /*
 ** MR_trace_init() is called from mercury_runtime_init()
@@ -39,25 +39,23 @@
 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;
@@ -70,5 +68,33 @@
 
 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_PERMANENT_H */
+#endif /* MERCURY_TRACE_BASE_H */
Index: runtime/mercury_trace_external.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_external.c,v
retrieving revision 1.7
diff -u -u -r1.7 mercury_trace_external.c
--- mercury_trace_external.c	1998/07/31 15:14:14	1.7
+++ mercury_trace_external.c	1998/08/02 22:52:57
@@ -68,11 +68,11 @@
 			Integer *debugger_request_type_ptr);
 	
 static bool	MR_found_match(const MR_Stack_Layout_Label *layout,
-			MR_trace_port port, Unsigned seqno, Unsigned depth,
+			MR_Trace_Port port, Unsigned seqno, Unsigned depth,
 			/* XXX registers */
 			const char *path, Word search_data);
 static void	MR_output_current_slots(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);
 static void	MR_output_current_vars(Word var_list, Word string_list);
 static void	MR_output_current_nth_var(Word var);
@@ -321,7 +321,7 @@
 
 void
 MR_trace_event_external(MR_trace_cmd_info *cmd, 
-	const MR_Stack_Layout_Label *layout, MR_trace_port port,
+	const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
 	Unsigned seqno, Unsigned depth, const char *path)
 {
 	static bool searching = FALSE;
@@ -420,7 +420,7 @@
 
 static void
 MR_output_current_slots(const MR_Stack_Layout_Label *layout,
-	MR_trace_port port, Unsigned seqno, Unsigned depth, const char *path)
+	MR_Trace_Port port, Unsigned seqno, Unsigned depth, const char *path)
 {
 	MR_DI_output_current_slots(
 		MR_trace_event_number,
@@ -477,7 +477,7 @@
 
 static bool
 MR_found_match(const MR_Stack_Layout_Label *layout,
-	MR_trace_port port, Unsigned seqno, Unsigned depth,
+	MR_Trace_Port port, Unsigned seqno, Unsigned depth,
 	/* XXX live vars */
 	const char *path, Word search_data)
 {
Index: runtime/mercury_trace_external.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_external.h,v
retrieving revision 1.2
diff -u -u -r1.2 mercury_trace_external.h
--- mercury_trace_external.h	1998/07/23 20:12:26	1.2
+++ mercury_trace_external.h	1998/07/29 00:02:11
@@ -13,7 +13,7 @@
 extern	void	MR_trace_final_external(void);
 extern	void	MR_trace_event_external(MR_trace_cmd_info *cmd,
 			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);
 
 #endif	/* MR_USE_EXTERNAL_DEBUGGER */
Index: runtime/mercury_trace_internal.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_internal.h,v
retrieving revision 1.1
diff -u -u -r1.1 mercury_trace_internal.h
--- mercury_trace_internal.h	1998/05/16 07:28:28	1.1
+++ mercury_trace_internal.h	1998/07/07 11:09:22
@@ -7,16 +7,10 @@
 #ifndef	MERCURY_TRACE_INTERNAL_H
 #define	MERCURY_TRACE_INTERNAL_H
 
-extern	void	MR_trace_event_internal(MR_trace_cmd_info *cmd,
+extern	Code	*MR_trace_event_internal(MR_Trace_Cmd_Info *cmd,
+			bool interactive,
 			const MR_Stack_Layout_Label *layout,
-			MR_trace_port port, int seqno, int depth,
-			const char *path);
-
-extern	void	MR_trace_event_internal_report(
-			const MR_Stack_Layout_Label *layout,
-			MR_trace_port port, int seqno, int depth,
-			const char *path);
-
-extern	bool	MR_event_matches_spy_point(const MR_Stack_Layout_Label *layout);
+			MR_Trace_Port port, int seqno, int depth,
+			const char *path, int *max_mr_num);
 
 #endif	/* MERCURY_TRACE_INTERNAL_H */
Index: runtime/mercury_trace_spy.c
===================================================================
RCS file: mercury_trace_spy.c
diff -N mercury_trace_spy.c
--- /dev/null	Wed May 28 10:49:58 1997
+++ mercury_trace_spy.c	Fri Aug  7 16:42:53 1998
@@ -0,0 +1,181 @@
+/*
+** 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.
+*/
+
+/*
+** This file contains code to manage spy points for both
+** the internal and external debuggers.
+**
+** Main author: Zoltan Somogyi.
+*/
+
+#undef	USE_GCC_GLOBAL_REGISTERS
+#include "mercury_imp.h"
+#include "mercury_trace_base.h"
+#include "mercury_trace.h"
+#include "mercury_trace_spy.h"
+#include "mercury_macros.h"
+
+typedef struct {
+	const MR_Stack_Layout_Entry	*spy_proc;
+	MR_Spy_Point			*spy_points;
+} MR_Spied_Proc;
+
+static	MR_Spied_Proc	*MR_spied_procs;
+static	int		MR_spied_proc_next = 0;
+static	int		MR_spied_proc_max = 0;
+
+#define	INIT_SPY_TABLE_SIZE	10
+
+		/* Return the index of the entry in MR_spied_procs whose   */
+		/* spy_proc field is entry, or a negative number if absent */
+static	int	MR_search_spy_table_for_proc(const MR_Stack_Layout_Entry
+			*entry);
+
+static int
+MR_search_spy_table_for_proc(const MR_Stack_Layout_Entry *entry)
+{
+	int				lo;
+	int				hi;
+	int				mid;
+
+	lo = 0;
+	hi = MR_spied_proc_next - 1;
+	while (lo <= hi) {
+		mid = (lo + hi) / 2;
+		if (MR_spied_procs[mid].spy_proc == entry) {
+			return mid;
+		} else if (MR_spied_procs[mid].spy_proc < entry) {
+			lo = mid + 1;
+		} else {
+			hi = mid - 1;
+		}
+	}
+
+	return -1;
+}
+
+bool
+MR_event_matches_spy_point(const MR_Stack_Layout_Label *layout,
+	MR_Trace_Port port, MR_Spy_Action *action_ptr)
+{
+	int				slot;
+	bool				enabled;
+	MR_Spy_Point			*point;
+	MR_Spy_Action			action;
+
+	slot = MR_search_spy_table_for_proc(layout->MR_sll_entry);
+	if (slot < 0) {
+		return FALSE;
+	}
+
+	enabled = FALSE;
+	action = MR_SPY_PRINT;
+	for (point = MR_spied_procs[slot].spy_points; point != NULL;
+			point = point->spy_next) {
+		if (! point->spy_enabled) {
+			continue;
+		}
+
+		switch (point->spy_when) {
+
+			case MR_SPY_ALL:
+				enabled = TRUE;
+				action = max(action, point->spy_action);
+				break;
+
+			case MR_SPY_ENTRY:
+				if (MR_port_is_entry(port)) {
+					enabled = TRUE;
+					action = max(action, point->spy_action);
+				} else {
+					continue;
+				}
+
+				break;
+
+			case MR_SPY_INTERFACE:
+				if (MR_port_is_interface(port)) {
+					enabled = TRUE;
+					action = max(action, point->spy_action);
+				} else {
+					continue;
+				}
+
+				break;
+
+			case MR_SPY_SPECIFIC:
+				if (layout == point->spy_label) {
+					enabled = TRUE;
+					action = max(action, point->spy_action);
+				} else {
+					continue;
+				}
+
+				break;
+
+			default:
+				fatal_error("bad spy point when in "
+						"MR_event_matches_spy_point");
+		}
+	}
+
+	if (enabled) {
+		*action_ptr = action;
+		return TRUE;
+	} else {
+		return FALSE;
+	}
+}
+
+static bool MR_need_move(int i, const MR_Stack_Layout_Entry *entry);
+
+MR_Spy_Point *
+MR_add_spy_point(MR_Spy_When when, MR_Spy_Action action,
+	const MR_Stack_Layout_Entry *entry, const MR_Stack_Layout_Label *label,
+	const char *path)
+{
+	MR_Spy_Point	*point;
+	int		i;
+	int		slot;
+	bool		found;
+
+	slot = MR_search_spy_table_for_proc(entry);
+	if (slot < 0) {
+		MR_ensure_room_for_next(MR_spied_proc, MR_Spied_Proc,
+			INIT_SPY_TABLE_SIZE);
+		MR_prepare_insert_into_sorted(MR_spied_procs,
+			MR_spied_proc_next, slot, MR_need_move(i, entry));
+		MR_spied_procs[slot].spy_proc = entry;
+		MR_spied_procs[slot].spy_points = NULL;
+	}
+
+	/* Insert the spy point at the head of the list for the proc. */
+	point = checked_malloc(sizeof(MR_Spy_Point));
+	point->spy_when    = when;
+	point->spy_enabled = TRUE;
+	point->spy_action  = action;
+	point->spy_proc    = entry;
+	point->spy_label   = label;
+	point->spy_next    = MR_spied_procs[slot].spy_points;
+	MR_spied_procs[slot].spy_points = point;
+
+	return point;
+}
+
+/*
+** The only reason why MR_need_move is a function is that gcc version 2.7.2.3
+** on i686-pc-linux-gnu gets an internal error ("fixed or forbidden register
+** was spilled") if it isn't a function.
+*/
+
+static bool
+MR_need_move(int i, const MR_Stack_Layout_Entry *entry)
+{
+	if (MR_spied_procs[i].spy_proc > entry)
+		return TRUE;
+	else
+		return FALSE;
+}
Index: runtime/mercury_trace_spy.h
===================================================================
RCS file: mercury_trace_spy.h
diff -N mercury_trace_spy.h
--- /dev/null	Wed May 28 10:49:58 1997
+++ mercury_trace_spy.h	Sun Jul  5 14:02:53 1998
@@ -0,0 +1,56 @@
+/*
+** 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.
+*/
+
+/*
+** This file contains the declarations of the types and functions that
+** the internal and external debuggers can use to manipulate spy points.
+**
+** Main author: Zoltan Somogyi.
+*/
+
+#ifndef	MERCURY_TRACE_SPY_H
+#define	MERCURY_TRACE_SPY_H
+
+typedef enum {
+	MR_SPY_PRINT, MR_SPY_STOP
+} MR_Spy_Action;
+
+#define	MR_spy_action_string(a)		((a == MR_SPY_STOP) ? "stop" :      \
+					(a == MR_SPY_PRINT) ? "print" :     \
+					"weird spy action")
+
+typedef enum {
+	MR_SPY_ALL, MR_SPY_INTERFACE, MR_SPY_ENTRY, MR_SPY_SPECIFIC
+} MR_Spy_When;
+
+#define	MR_spy_when_string(w)		((w == MR_SPY_ALL) ? "all" :          \
+					(w == MR_SPY_INTERFACE) ? "interface":\
+					(w == MR_SPY_ENTRY) ? "entry" : \
+					(w == MR_SPY_SPECIFIC) ? "specific" : \
+					"weird spy when")
+
+typedef struct struct_mr_spy_point MR_Spy_Point;
+
+struct struct_mr_spy_point {
+	MR_Spy_When			spy_when;
+	bool				spy_enabled;
+	MR_Spy_Action			spy_action;
+	const MR_Stack_Layout_Entry	*spy_proc;
+	const MR_Stack_Layout_Label	*spy_label; /* if MR_SPY_SPECIFIC */
+	MR_Spy_Point			*spy_next;
+};
+
+extern	bool		MR_event_matches_spy_point(const MR_Stack_Layout_Label
+				*layout, MR_Trace_Port port,
+				MR_Spy_Action *action);
+
+extern	MR_Spy_Point	*MR_add_spy_point(MR_Spy_When when,
+				MR_Spy_Action action,
+				const MR_Stack_Layout_Entry *entry,
+				const MR_Stack_Layout_Label *label,
+				const char *path);
+
+#endif	/* not MERCURY_TRACE_SPY_H */
Index: runtime/mercury_trace_tables.c
===================================================================
RCS file: mercury_trace_tables.c
diff -N mercury_trace_tables.c
--- /dev/null	Wed May 28 10:49:58 1997
+++ mercury_trace_tables.c	Wed Sep 16 12:03:18 1998
@@ -0,0 +1,376 @@
+/*
+** 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.
+*/
+
+/*
+** This file manages a table listing the debuggable modules of the program,
+** and subsidiary tables listing the procedures of each of those modules.
+**
+** Main author: Zoltan Somogyi.
+*/
+
+#undef	USE_GCC_GLOBAL_REGISTERS
+#include "mercury_imp.h"
+#include "mercury_label.h"
+#include "mercury_macros.h"
+#include "mercury_trace_tables.h"
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+static	MR_Module_Info	*MR_module_infos;
+static	int		MR_module_info_next = 0;
+static	int		MR_module_info_max  = 0;
+static	int		MR_module_info_proc_count = 0;
+
+#define	INIT_MODULE_TABLE_SIZE	10
+
+static	void		MR_register_from_internal_label(const void *info);
+static	void		MR_ensure_proc_node_is_present(MR_Module_Info *module,
+				const MR_Stack_Layout_Entry *entry);
+static	MR_Module_Info	*MR_search_module_info(const char *name);
+static	MR_Module_Info	*MR_insert_module_info(const char *name);
+static	MR_Module_Info	*MR_ensure_module_info_is_present(const char *name);
+
+static	void		MR_process_matching_procedures_in_module(
+				MR_Module_Info *module, MR_Proc_Spec *spec,
+				void f(const MR_Stack_Layout_Entry *));
+
+void
+MR_register_all_modules_and_procs(FILE *fp, bool verbose)
+{
+	static	bool	done = FALSE;
+
+	if (! done) {
+		if (verbose) {
+			fprintf(fp, "Registering debuggable procedures... ");
+			fflush(fp);
+		}
+
+		do_init_modules();
+		MR_process_all_internal_labels(MR_register_from_internal_label);
+		done = TRUE;
+		if (verbose) {
+			fprintf(fp, "done.\n");
+			if (MR_module_info_next == 0) {
+				fprintf(fp, "There are no debuggable modules.");
+			} else if (MR_module_info_next == 1) {
+				fprintf(fp, "There is one debuggable module, "
+					"with %d procedures.\n",
+					MR_module_info_proc_count);
+			} else {
+				fprintf(fp, "There are %d debuggable modules, "
+					"with a total of %d procedures.\n",
+					MR_module_info_next,
+					MR_module_info_proc_count);
+			}
+		}
+	}
+}
+
+static void
+MR_register_from_internal_label(const void *info)
+{
+	const MR_Stack_Layout_Label	*label;
+	const MR_Stack_Layout_Entry	*entry;
+	MR_Module_Info			*module;
+
+	label = ((const MR_Internal *) info)->i_layout;
+
+	if (label == NULL) {
+		/* some labels have no layout structure */
+		return;
+	}
+
+	if (label->MR_sll_entry == NULL) {
+		/* some hand-crafted label structures have no entry */
+		return;
+	}
+
+	entry = label->MR_sll_entry;
+
+	if (MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry) &&
+			! MR_ENTRY_LAYOUT_COMPILER_GENERATED(entry))
+	{
+		module = MR_ensure_module_info_is_present(
+				entry->MR_sle_def_module);
+		MR_ensure_proc_node_is_present(module, entry);
+	}
+}
+
+static void
+MR_ensure_proc_node_is_present(MR_Module_Info *module,
+	const MR_Stack_Layout_Entry *entry)
+{
+	MR_Proc_Node	*cur;
+
+	for (cur = module->MR_module_procs; cur != NULL;
+			cur = cur->MR_proc_next) {
+		if (entry == cur->MR_proc_layout) {
+			return;
+		}
+	}
+
+	cur = checked_malloc(sizeof(MR_Proc_Node));
+	cur->MR_proc_layout = entry;
+	cur->MR_proc_next   = module->MR_module_procs;
+	module->MR_module_procs = cur;
+	MR_module_info_proc_count++;
+}
+
+static MR_Module_Info *
+MR_search_module_info(const char *name)
+{
+	int	slot;
+	bool	found;
+
+	MR_bsearch(MR_module_info_next, slot, found,
+		strcmp(MR_module_infos[slot].MR_module_name, name));
+	if (found) {
+		return &MR_module_infos[slot];
+	} else {
+		return NULL;
+	}
+}
+
+static MR_Module_Info *
+MR_insert_module_info(const char *name)
+{
+	int	slot;
+
+	MR_ensure_room_for_next(MR_module_info, MR_Module_Info,
+		INIT_MODULE_TABLE_SIZE);
+	MR_prepare_insert_into_sorted(MR_module_infos, MR_module_info_next,
+		slot, strcmp(MR_module_infos[slot].MR_module_name, name));
+
+	MR_module_infos[slot].MR_module_name = name;
+	MR_module_infos[slot].MR_module_procs = NULL;
+	return &MR_module_infos[slot];
+}
+
+static MR_Module_Info *
+MR_ensure_module_info_is_present(const char *name)
+{
+	MR_Module_Info	*module;
+
+	module = MR_search_module_info(name);
+	if (module != NULL) {
+		return module;
+	} else {
+		return MR_insert_module_info(name);
+	}
+}
+
+void
+MR_dump_module_tables(FILE *fp)
+{
+	const MR_Proc_Node	*cur;
+	int			i;
+
+	for (i = 0; i < MR_module_info_next; i++) {
+		fprintf(fp, "====================\n");
+		fprintf(fp, "module %s\n", MR_module_infos[i].MR_module_name);
+		fprintf(fp, "====================\n");
+		for (cur = MR_module_infos[i].MR_module_procs; cur != NULL;
+				cur = cur->MR_proc_next) {
+			MR_print_proc_id(fp, cur->MR_proc_layout, NULL);
+		}
+	}
+}
+
+void
+MR_dump_module_list(FILE *fp)
+{
+	int			i;
+
+	fprintf(fp, "List of debuggable modules\n\n");
+	for (i = 0; i < MR_module_info_next; i++) {
+		fprintf(fp, "%s\n", MR_module_infos[i].MR_module_name);
+	}
+}
+
+void
+MR_dump_module_procs(FILE *fp, const char *name)
+{
+	MR_Module_Info		*module;
+	const MR_Proc_Node	*cur;
+
+	module = MR_search_module_info(name);
+	if (module == NULL) {
+		fprintf(fp, "There is no debugging info about module %s\n",
+				name);
+	} else {
+		fprintf(fp, "List of procedures in module %s\n\n", name);
+		for (cur = module->MR_module_procs; cur != NULL;
+				cur = cur->MR_proc_next) {
+			MR_print_proc_id(fp, cur->MR_proc_layout, NULL);
+		}
+	}
+}
+
+bool
+MR_parse_proc_spec(char *str, MR_Proc_Spec *spec)
+{
+	char	*dash;
+	char	*slash;
+	char	*s;
+	int	n;
+	bool	found;
+
+	spec->MR_proc_module = NULL;
+	spec->MR_proc_name   = NULL;
+	spec->MR_proc_arity  = -1;
+	spec->MR_proc_mode   = -1;
+	spec->MR_proc_pf     = (MR_PredFunc) -1;
+
+	if (strneq(str, "pred*", 5)) {
+		spec->MR_proc_pf = MR_PREDICATE;
+		str += 5;
+	} else if (strneq(str, "func*", 5)) {
+		spec->MR_proc_pf = MR_FUNCTION;
+		str += 5;
+	}
+
+	if ((dash = strrchr(str, '-')) != NULL) {
+		found = FALSE;
+		n = 0;
+		for (s = dash + 1; *s != '\0'; s++) {
+			if (MR_isdigit(*s)) {
+				found = TRUE;
+				n = n * 10 + *s - '0';
+			} else {
+				/* a dash followed by a nondigit is an error */
+				return FALSE;
+			}
+		}
+
+		if (! found) {
+			/* a dash with no following digit is an error */
+			return FALSE;
+		}
+
+		spec->MR_proc_mode = n;
+		*dash = '\0';
+	}
+
+	if ((slash = strrchr(str, '/')) != NULL) {
+		found = FALSE;
+		n = 0;
+		for (s = slash + 1; *s != '\0'; s++) {
+			if (MR_isdigit(*s)) {
+				found = TRUE;
+				n = n * 10 + *s - '0';
+			} else {
+				/* a slash followed by a nondigit is an error */
+				return FALSE;
+			}
+		}
+
+		if (! found) {
+			/* a slash with no following digit is an error */
+			return FALSE;
+		}
+
+		spec->MR_proc_arity = n;
+		*slash = '\0';
+	}
+
+	for (s = str; *s != '\0'; s++) {
+		if (*s == ':' || (*s == '_' && *(s+1) == '_')) {
+			if (*s == ':') {
+				spec->MR_proc_name = s+1;
+			} else {
+				spec->MR_proc_name = s+2;
+			}
+
+			*s = '\0';
+			spec->MR_proc_module = str;
+
+			return TRUE;
+		}
+	}
+
+	spec->MR_proc_name = str;
+	return TRUE;
+}
+
+/* These two variables are for communication between */
+/* MR_register_match and MR_search_for_matching_procedure. */
+static	const MR_Stack_Layout_Entry	*matching_entry;
+static	bool	 			match_unique;
+
+static void
+MR_register_match(const MR_Stack_Layout_Entry *entry)
+{
+	if (matching_entry == NULL) {
+		matching_entry = entry;
+	} else {
+		match_unique = FALSE;
+	}
+}
+
+const MR_Stack_Layout_Entry *
+MR_search_for_matching_procedure(MR_Proc_Spec *spec, bool *unique)
+{
+	matching_entry = NULL;
+	match_unique = TRUE;
+	MR_process_matching_procedures(spec, MR_register_match);
+	*unique = match_unique;
+	return matching_entry;
+}
+
+void
+MR_process_matching_procedures(MR_Proc_Spec *spec,
+	void f(const MR_Stack_Layout_Entry *))
+{
+	if (spec->MR_proc_module != NULL) {
+		MR_Module_Info			*module;
+
+		module = MR_search_module_info(spec->MR_proc_module);
+		if (module != NULL) {
+			MR_process_matching_procedures_in_module(
+				module, spec, f);
+		}
+	} else {
+		int	i;
+
+		for (i = 0; i < MR_module_info_next; i++) {
+			MR_process_matching_procedures_in_module(
+				&MR_module_infos[i], spec, f);
+		}
+	}
+}
+
+#define	match_name(spec, cur)	(((spec)->MR_proc_name == NULL) ||	\
+				streq((spec)->MR_proc_name, cur->MR_sle_name))
+
+#define	match_arity(spec, cur)	(((spec)->MR_proc_arity < 0) ||		\
+				(spec)->MR_proc_arity == cur->MR_sle_arity)
+
+#define	match_mode(spec, cur)	(((spec)->MR_proc_mode < 0) ||		\
+				(spec)->MR_proc_mode == cur->MR_sle_mode)
+
+#define	match_pf(spec, cur)	(((int) (spec)->MR_proc_pf < 0) ||	\
+				(spec)->MR_proc_pf == cur->MR_sle_pred_or_func)
+
+static void
+MR_process_matching_procedures_in_module(MR_Module_Info *module,
+	MR_Proc_Spec *spec, void f(const MR_Stack_Layout_Entry *))
+{
+	MR_Proc_Node			*cur;
+	const MR_Stack_Layout_Entry	*cur_entry;
+
+	for (cur = module->MR_module_procs; cur != NULL;
+			cur = cur->MR_proc_next) {
+		cur_entry = cur->MR_proc_layout;
+		if (match_name(spec, cur_entry) &&
+				match_arity(spec, cur_entry) &&
+				match_mode(spec, cur_entry) &&
+				match_pf(spec, cur_entry))
+		{
+			f(cur_entry);
+		}
+	}
+}
Index: runtime/mercury_trace_tables.h
===================================================================
RCS file: mercury_trace_tables.h
diff -N mercury_trace_tables.h
--- /dev/null	Wed May 28 10:49:58 1997
+++ mercury_trace_tables.h	Wed Sep 16 12:03:55 1998
@@ -0,0 +1,120 @@
+/*
+** 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.
+*/
+
+/*
+** This file contains the declarations of the tables that contain
+** the identities of the debuggable modules and their procedures.
+**
+** Main author: Zoltan Somogyi.
+*/
+
+#ifndef	MERCURY_TRACE_TABLES_H
+#define	MERCURY_TRACE_TABLES_H
+
+#include	"mercury_stack_layout.h"
+#include	<stdio.h>
+
+/*
+** The module info table is an array with one element for each module
+** that has procedures with execution tracing information. This element
+** gives the module's name and points to a list of the procedure layouts
+** of the traceable procedures of the module.
+*/
+
+typedef struct struct_mr_proc_node	MR_Proc_Node;
+
+struct struct_mr_proc_node {
+	const MR_Stack_Layout_Entry	*MR_proc_layout;
+	MR_Proc_Node			*MR_proc_next;
+};
+
+typedef struct {
+	const char 			*MR_module_name;
+	MR_Proc_Node			*MR_module_procs;
+} MR_Module_Info;
+
+/*
+** MR_register_all_modules_and_procs gathers all available debugging info
+** about the modules and procedures of the program into the module info table.
+** If verbose is TRUE, print progress and summary messages.
+*/
+
+extern	void		MR_register_all_modules_and_procs(FILE *fp,
+				bool verbose);
+
+/*
+** These functions print (parts of) the module info table.
+**
+** MR_dump_module_tables lists all procedures in all modules.
+** Its output can be very big; it should be used only by developers,
+** for debugging the debugger.
+**
+** MR_dump_module_list lists the names of all the modules,
+** while MR_dump_module_procs lists the names of all the procs in the named
+** module. These are intended for ordinary, non-developer users.
+*/
+
+extern	void		MR_dump_module_tables(FILE *fp);
+extern	void		MR_dump_module_list(FILE *fp);
+extern	void		MR_dump_module_procs(FILE *fp, const char *name);
+
+/*
+** A procedure specification gives some or all of
+**
+**	the name of the module defining the procedure
+**	the name of the predicate or function
+**	the arity of the predicate or function
+**	the mode of the predicate or function
+**	whether the procedure belongs to a predicate or function
+**
+** A NULL pointer for the string fields, and a negative number for the other
+** fields signifies the absence of information about that field, which should
+** therefore be treated as a wildcard.
+*/
+
+typedef	struct {
+	const char			*MR_proc_module;
+	const char			*MR_proc_name;
+	int				MR_proc_arity;
+	int				MR_proc_mode;
+	MR_PredFunc			MR_proc_pf;
+} MR_Proc_Spec;
+
+/*
+** Given a string containing the specification of a procedure in the form
+**
+**	[`pred*'|`func*']module:name/arity-mode
+**
+** in which some of the five components (but not the name) may be missing,
+** parse it into the more usable form of a MR_Proc_Spec. The original string
+** may be overwritten in the process.
+**
+** Returns TRUE if the string was correctly formed, and FALSE otherwise.
+*/
+
+extern	bool	MR_parse_proc_spec(char *str, MR_Proc_Spec *spec);
+
+/*
+** Search the tables for a procedure that matches the given specification.
+** If no procedure matches, return NULL.
+** If one procedure matches, return its layout structure,
+** and set *unique to TRUE.
+** If more than one procedure matches, return the layout structure of one
+** and set *unique to FALSE.
+*/
+
+extern	const MR_Stack_Layout_Entry *MR_search_for_matching_procedure(
+					MR_Proc_Spec *spec, bool *unique);
+
+/*
+** Call f(entry) on the layout of every procedure that matches
+** the given specification.
+*/
+
+extern	void	MR_process_matching_procedures(MR_Proc_Spec *spec,
+			void f(const MR_Stack_Layout_Entry *));
+
+#endif	/* not MERCURY_TRACE_TABLES_H */
Index: runtime/mercury_trace_util.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_util.c,v
retrieving revision 1.8
diff -u -u -r1.8 mercury_trace_util.c
--- mercury_trace_util.c	1998/07/31 15:14:17	1.8
+++ mercury_trace_util.c	1998/09/16 02:12:24
@@ -14,6 +14,7 @@
 #include "mercury_imp.h"
 #include "mercury_stack_layout.h"
 #include "mercury_trace_util.h"
+#include "../library/io.h"
 
 Word	MR_saved_regs[MAX_FAKE_REG];
 
@@ -178,6 +179,16 @@
 	return univ_list;
 }
 
+int
+MR_trace_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;
 
@@ -221,7 +232,7 @@
 			if (MR_trace_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;
 
@@ -229,7 +240,7 @@
 			if (MR_trace_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;
 
@@ -339,6 +350,17 @@
 void
 MR_trace_write_variable(Word type_info, Word value)
 {
+	static	bool	done = FALSE;
+	static	Word	stdout_stream;
+
+	if (! done) {
+		ML_io_stdout_stream(&stdout_stream);
+		done = TRUE;
+	}
+
+#if 1
+	ML_io_print_to_stream(type_info, stdout_stream, value);
+#else
 
 	/*
 	** XXX It would be nice if we could call an exported C function
@@ -352,16 +374,18 @@
 	**
 	** 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
+	** entry to this function.  But r1, r2 or r3 may be transient, so we
 	** need to save/restore transient regs around the assignments to
 	** them.
 	*/
 
 	restore_transient_registers();
 	r1 = type_info;
-	r2 = value;
+	r2 = 
+	r3 = value;
 	save_transient_registers();
 	call_engine(MR_library_trace_browser);
+#endif
 }
 
 
Index: runtime/mercury_trace_util.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_util.h,v
retrieving revision 1.5
diff -u -u -r1.5 mercury_trace_util.h
--- mercury_trace_util.h	1998/07/31 15:14:19	1.5
+++ mercury_trace_util.h	1998/08/02 22:53:00
@@ -7,10 +7,43 @@
 #ifndef	MERCURY_TRACE_UTIL_H
 #define	MERCURY_TRACE_UTIL_H
 
-extern	Word    MR_saved_regs[MAX_FAKE_REG];
+/*
+** These two functions copy the register state to and from MR_saved_regs.
+** XXX MR_saved_regs should probably be in MercuryEngine.
+*/
+
 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_saved_regs[MAX_FAKE_REG];
+
+/*
+** 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_trace_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_trace_materialize_typeinfos is from malloc;
+** it should be freed after last use.
+**
+** MR_trace_materialize_typeinfos looks up locations in the current
+** environment. MR_trace_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 the
+** flag says so.
+*/ 
+
 extern	Word	*MR_trace_materialize_typeinfos(const MR_Stack_Layout_Vars
 			*vars);
 extern	Word	*MR_trace_materialize_typeinfos_base(const MR_Stack_Layout_Vars
@@ -18,10 +51,45 @@
 			Word *base_sp, Word *base_curfr);
 
 extern	Word	MR_trace_make_var_list(const MR_Stack_Layout_Label *layout);
+
+/*
+** If the given encoded location refers to a register, return its number.
+** If it does not, return -1.
+*/
+
+extern	int	MR_trace_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_trace_lookup_live_lval looks up locations in the current environment.
+** MR_trace_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 the flag says so.
+*/ 
+
 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,
 			bool *succeeded);
+
+/*
+** 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_trace_materialize_typeinfos.
+**
+** MR_trace_get_type_and_value looks up locations in the current environment.
+** MR_trace_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 the flag says so.
+*/
+
 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,
Index: runtime/mercury_wrapper.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.h,v
retrieving revision 1.12
diff -u -u -r1.12 mercury_wrapper.h
--- mercury_wrapper.h	1998/07/31 15:14:21	1.12
+++ mercury_wrapper.h	1998/08/02 22:53:03
@@ -5,8 +5,8 @@
 */
 
 /*
-** mercury_wrapper.h - defines the interface to wrapper.c.
-** See wrapper.c for documentation.
+** mercury_wrapper.h - defines the interface to mercury_wrapper.c.
+** See mercury_wrapper.c for documentation.
 */
 
 #ifndef	MERCURY_WRAPPER_H
@@ -40,7 +40,7 @@
 ** 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);
@@ -88,9 +88,9 @@
 
 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



More information about the developers mailing list