for review again: reorganize label table, reduce executable sizes

Zoltan Somogyi zs at cs.mu.OZ.AU
Thu Jul 2 10:32:16 AEST 1998


Estimated hours taken: 24

Reorganize the label table to better fit the needs of accurate gc
and the tracer, and reduce the size of executables.

With these changes, the size of hello world, compiled with static
Mercury libraries but dynamic C libraries, goes from 150+ Kb to
138+ Kb, much of which is beyond our control (e.g. Boehm gc).

runtime/mercury_label.[ch]:
	The old label table contained both entry labels and internal labels,
	even though they had different kinds of layouts associated with them
	(proc layouts and label layouts respectively). The two kinds of labels
	have different usage patterns. Internal labels are needed for stack
	walking, which requires random access by exact label address. Entry
	labels are needed for finding which procedure a program counter is in
	for accurate GC, which requires lower-bound inexact search.

	The module now has two separate data structures for the two
	different kinds of labels. Internal labels are in a hash table,
	as before. Entry labels are in an array (resized on demand),
	which is sorted for binary search. The entry label array and
	its associated functions are present only if they are needed.

runtime/mercury_goto.h:
	Call the new functions in mercury_label.c from the
	init_{local,label,entry}{,_sl} macros.

runtime/mercury_misc.[ch]
	Use the new functions in mercury_label. Fix some software rot,
	so that the code now compiles with MR_DEBUG_GOTOS. (It still does not
	compile with MR_LOWLEVEL_DEBUG, but the fix for that would conflict
	with Tom's planned change to zone handling, so that fix should be
	done after Tom is done.)

	Note that mercury_misc.c still defines newmem() and oldmem()
	although they are declared in mercury_std.h.

runtime/mercury_stack_trace.c:
	Use the new functions in mercury_label. As a result, we also need
	to make a few more pointers const.

runtime/mercury_table.[ch]:
	Add a new traversal predicate to support a new function in
	mercury_label.c. (That function is not used yet, but will be soon.)

runtime/mercury_trace.[ch]:
runtime/mercury_trace_base.[ch]:
	Split the old mercury_trace module into two. The functions and
	variables that will always be linked in (because they are referenced
	from modules such as mercury_wrapper which are always needed) are
	now in mercury_trace_base; the other functions and variables
	stay in mercury_trace. This way, mercury_trace.o will be linked in
	only if some module was compiled with execution tracing. Since
	mercury_trace.o drags in mercury_trace_internal.o which drags in
	everything needed for printing arbitrary terms (which is a lot),
	this can be a significant win.

runtime/Mmakefile:
	Include the new module in the library.

runtime/mercury_wrapper.c:
runtime/mercury_conf_param.h:
	Remove some obsolete MERCURY_OPTIONS options, which would be
	difficult to support with the new label table.

	Replace the long help message for malformed MERCURY_OPTIONS
	environment variables with a pointer to the user's guide.
	This saves about 1 Kb on every executable.

runtime/mercury_conf_param.h:
	Document MR_STACK_TRACE_THIS_MODULE.

util/mkinit.c:
	Add a new flag, -i. If this flag is given, include the initialization
	code regardless of grade. If it is not given, include the init code
	only if the grade requires it.

	The -i should be given if you want the executable to support stack
	tracing, or uplevel printing in execution tracing, at the cost of
	making the executable link in the init functions of all the modules
	in the library.

	Put the option handling code in alphabetical order.

	Fix the wrong default name of the entry point. (It only worked because
	c2init was always overriding the default.)

scripts/c2init.in:
	Pass through the -i flag to mkinit.

	Put the option handling code in alphabetical order.

compiler/mercury_compile.m:
	If the trace level specifies any kind of tracing, pass -i to c2init.

tests/debugger/Mmakefile:
	Add -i to the c2init flags.

tests/debugger/*
	Update the other half the test cases (those which assume a traced
	library) to conform to the changes in the debugger interface.
	The first half were updated earlier.

doc/user_guide.texi:
	In the environment variable section, modify the entry for
	MERCURY_OPTIONS to document all the options it makes sense
	for non-developers to use.

	Slight changes to two other parts of the guide to reduce duplication
	with the new material.

Zoltan.

cvs diff: Diffing .
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing bytecode
cvs diff: Diffing bytecode/test
cvs diff: Diffing compiler
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.101
diff -u -u -r1.101 mercury_compile.m
--- mercury_compile.m	1998/07/01 04:09:37	1.101
+++ mercury_compile.m	1998/07/01 04:41:41
@@ -2359,7 +2359,13 @@
 	    % create the initialization C file
 	    maybe_write_string(Verbose, "% Creating initialization file...\n"),
 	    join_module_list(Modules, ".m", ["> ", InitCFileName], MkInitCmd0),
-	    { string__append_list(["c2init " | MkInitCmd0], MkInitCmd) },
+	    globals__io_get_trace_level(TraceLevel),
+	    { trace_level_trace_interface(TraceLevel, yes) ->
+		CmdPrefix = "c2init -i "
+	    ;
+		CmdPrefix = "c2init "
+	    },
+	    { string__append_list([CmdPrefix | MkInitCmd0], MkInitCmd) },
 	    invoke_system_command(MkInitCmd, MkInitOK),
 	    maybe_report_stats(Stats),
 	    ( { MkInitOK = no } ->
cvs diff: Diffing compiler/notes
cvs diff: Diffing doc
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.127
diff -u -u -r1.127 user_guide.texi
--- user_guide.texi	1998/07/01 04:10:14	1.127
+++ user_guide.texi	1998/07/01 04:42:09
@@ -1185,30 +1185,24 @@
 @node Time profiling methods
 @section Time profiling methods
 
-By setting the environment variable MERCURY_OPTIONS,
-which is used for passing options to the Mercury runtime system,
-you can control how the Mercury profiler measures the time spent.
-The default (@samp{-Tp}) is to count time spent executing the process,
-including time spent by the system performing operations on behalf of
-the process, but not including time that the process was suspended
+You can control whether profiling measures
+real (elapsed) time, user time plus system time, or user time only,
+by including the options -Tr, -Tp, or -Tv respectively
+in the environment variable MERCURY_OPTIONS
+when you run the program to be profiled.
+ at c (See the environment variables section below.)
+
+The default is user time plus system time,
+which counts all time spent executing the process,
+including time spent by the operating system performing
+working on behalf of the process,
+but not including time that the process was suspended
 (e.g. due to time slicing, or while waiting for input).
-Using @samp{-Tv} counts only time spent executing the process.
-Using @samp{-Tr} counts all elapsed time, even including time that
-the process was suspended.
+When measuring real time, profiling counts
+even periods during which the process was suspended.
+When measuring user time only, profiling does not count
+time inside the operating system at all.
 
- at table @asis
- at item @samp{-Tr}
-Profile real (elapsed) time (using ITIMER_REAL).
- at item @samp{-Tv}
-Profile user time (using ITIMER_VIRTUAL).
- at item @samp{-Tp}
-Profile user time plus system time (using ITIMER_PROF).
-This is the default.
- at end table
-
-Currently, the @samp{-Tv} and @samp{-Tp} options don't work on Windows,
-so on Windows you must explicitly specify @samp{-Tr}.
-
 @node Creating the profile
 @section Creating the profile
 
@@ -2713,14 +2707,6 @@
 The default grade to use if no @samp{--grade} option is specified.
 
 @sp 1
- at item MERCURY_OPTIONS
-A list of options for the Mercury runtime that gets
-linked into every Mercury program.
-Options are available to set the size of the different memory
-areas, and to enable various debugging traces.
-Set @samp{MERCURY_OPTIONS} to @samp{-h} for help.
-
- at sp 1
 @item MERCURY_C_INCL_DIR
 Directory for the C header files for the Mercury runtime system (@file{*.h}).
 This environment variable is used
@@ -2809,6 +2795,82 @@
 @sp 1
 @item MERCURY_MKINIT
 Filename of the program to create the @file{*_init.c} file.
+
+ at sp 1
+ at item MERCURY_OPTIONS
+A list of options for the Mercury runtime that gets
+linked into every Mercury program.
+Their meanings are as follows.
+
+ at sp 1
+ at table @code
+
+ at c @item -a
+ at c @item -c
+
+ at item -C @var{size}
+Tells the runtime system
+to optimize the locations of the starts of the various data areas
+for a primary data cache of @var{size} kilobytes.
+The optimization consists of arranging the starts of the areas
+to differ as much as possible modulo this size.
+
+ at c @item -d @var{debugflag}
+
+ at sp 1
+ at item -D @var{debugger}
+Enables execution tracing of the program,
+via the internal debugger if @var{debugger} is @samp{i}
+and via the external debugger if @var{debugger} is @samp{e}.
+ at c The mdb script works by including -Di in MERCURY_OPTIONS.
+
+ at sp 1
+ at item -p
+Disables profiling in an executable built in a profiling grade.
+
+ at sp 1
+ at item -P @var{num}
+Tells the runtime system to use @var{num} threads
+if the program was build in a parallel grade.
+
+ at c @item -r
+
+ at sp 1
+ at item -s @var{area} @var{size}
+Tells the runtime system to set the size of one area of the runtime system,
+where @var{area} must be one of @samp{h} (standing for heap),
+ at samp{d} (standing for deterministic stack),
+ at samp{n} (standing for nondeterministic stack)
+and, in grades with trailing, @samp{t} (standing for trail),
+to @var{size} kilobytes.
+
+ at c @item -t
+
+ at sp 1
+ at item -T @var{time_method}
+If the executable is in a grade that includes time profiling,
+specifies what time is counted in the profile.
+ at var{time_method} must have one of the following values:
+
+ at sp 1
+ at table @code
+ at item @samp{r}
+Profile real (elapsed) time (using ITIMER_REAL).
+ at item @samp{p}
+Profile user time plus system time (using ITIMER_PROF).
+This is the default.
+ at item @samp{v}
+Profile user time (using ITIMER_VIRTUAL).
+ at end table
+
+ at sp 1
+Currently, the @samp{-Tp} and @samp{-Tv} options don't work on Windows,
+so on Windows you must explicitly specify @samp{-Tr}.
+
+ at c @item -x
+ at c @item -z @var{area} @var{size}
+
+ at end table
 
 @end table
 
cvs diff: Diffing extras
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/Togl-1.2
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing library
cvs diff: Diffing lp_solve
cvs diff: Diffing lp_solve/lp_examples
cvs diff: Diffing profiler
cvs diff: Diffing runtime
Index: runtime/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/Mmakefile,v
retrieving revision 1.30
diff -u -u -r1.30 Mmakefile
--- Mmakefile	1998/06/09 02:07:45	1.30
+++ Mmakefile	1998/06/30 06:36:10
@@ -14,7 +14,7 @@
 #-----------------------------------------------------------------------------#
 
 CFLAGS		= -I$(MERCURY_DIR)/runtime -I$(MERCURY_DIR)/boehm_gc -g \
-		  $(DLL_CFLAGS) $(EXTRA_CFLAGS) 
+		  $(DLL_CFLAGS) $(EXTRA_CFLAGS)
 MGNUC		= MERCURY_C_INCL_DIR=. $(SCRIPTS_DIR)/mgnuc
 MGNUCFLAGS	= --no-ansi $(EXTRA_MGNUCFLAGS) $(CFLAGS)
 MOD2C		= $(SCRIPTS_DIR)/mod2c
@@ -67,6 +67,7 @@
 			mercury_thread.h	\
 			mercury_timing.h	\
 			mercury_trace.h		\
+			mercury_trace_base.h	\
 			mercury_trace_external.h \
 			mercury_trace_internal.h \
 			mercury_trace_util.h	\
@@ -118,6 +119,7 @@
 			mercury_table_type_info.c\
 			mercury_timing.c	\
 			mercury_trace.c		\
+			mercury_trace_base.c	\
 			mercury_trace_external.c \
 			mercury_trace_internal.c \
 			mercury_trace_util.c	\
Index: runtime/mercury_conf_param.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf_param.h,v
retrieving revision 1.5
diff -u -u -r1.5 mercury_conf_param.h
--- mercury_conf_param.h	1998/06/08 08:26:58	1.5
+++ mercury_conf_param.h	1998/07/01 10:31:18
@@ -47,7 +47,7 @@
 ** COMPACT_ARGS
 ** NO_TYPE_LAYOUT
 ** BOXED_FLOAT
-** USE_TRAIL
+** MR_USE_TRAIL
 **	See the documentation for
 **		--gcc-global-registers
 **		--gcc-non-local-gotos
@@ -91,8 +91,16 @@
 ** Debugging options:
 **
 ** MR_STACK_TRACE
-**	Enable stuff needed so that error/1 (and co.) can print out
-**	stack traces.
+**	Require the inclusion of the layout information needed by error/1
+**	and the debugger to print stack traces. This effect is achieved by
+**	including MR_STACK_TRACE in the mangled grade (see mercury_grade.h).
+**
+** MR_STACK_TRACE_THIS_MODULE
+**	Include the layout information needed by error/1 and the debugger
+**	to print stack traces. Unlike MR_STACK_TRACE, this does not affect
+**	the mangled grade, so it can be specified on a module-by-module basis.
+**	(When a stack trace encounters a stack frame created by code from a
+**	module which does not have layout information, the trace stops.)
 **
 ** MR_REQUIRE_TRACING
 **	Require that all Mercury procedures linked in should be compiled
@@ -143,16 +151,6 @@
 **
 ** PROFILE_MEMORY
 ** Enables profiling of memory usage.
-*/
-
-/*
-** Miscellaneous options:
-**
-** MR_CHOOSE_ENTRY_POINT
-**	Enables support for the `-w' (entry point) command
-**	in the MERCURY_OPTIONS environment variable.
-**	(`-w' also happens to work if you set certain other
-**	options instead, include MR_LOWLEVEL_DEBUG.)
 */
 
 /*---------------------------------------------------------------------------*/
Index: runtime/mercury_goto.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_goto.h,v
retrieving revision 1.10
diff -u -u -r1.10 mercury_goto.h
--- mercury_goto.h	1998/06/08 08:27:01	1.10
+++ mercury_goto.h	1998/06/30 06:38:48
@@ -12,6 +12,7 @@
 #include "mercury_conf.h"
 #include "mercury_types.h"	/* for `Code *' */
 #include "mercury_debug.h"	/* for debuggoto() */
+#include "mercury_label.h"	/* for insert_{entry,internal}_label() */
 
 #define paste(a,b) a##b
 #define stringify(string) #string
@@ -19,13 +20,15 @@
 #define skip(label) paste(skip_,label)
 
 #if defined(MR_USE_STACK_LAYOUTS)
-  #define MR_STACK_LAYOUT(label)        (Word *) (Word) \
+  #define MR_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) \
+	&(paste(mercury_data__layout__,label))
 #else
-  #define MR_STACK_LAYOUT(label)	(Word *) NULL
+  #define MR_ENTRY_LAYOUT(label)	(const MR_Stack_Layout_Entry *) NULL
+  #define MR_INTERNAL_LAYOUT(label)	(const MR_Stack_Layout_Label *) NULL
 #endif
 
-
 /*
 ** Taking the address of a label can inhibit gcc's optimization,
 ** because it assumes that anything can jump there.
@@ -40,25 +43,27 @@
 */
 
 #if defined(MR_INSERT_LABELS)
-  #define make_label(n, a, l)		make_entry(n, a, l)
-  #define make_label_sl(n, a, l)	make_entry_sl(n, a, l)
+  #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))
 #else
   #define make_label(n, a, l)		/* nothing */
   #define make_label_sl(n, a, l)	/* nothing */
 #endif
 
 #if defined(MR_INSERT_LABELS) || defined(PROFILE_CALLS)
-  #define make_local(n, a, l)		make_entry(n, a, l)
-  #define make_local_sl(n, a, l)	make_entry_sl(n, a, l)
+  #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))
 #else 
   #define make_local(n, a, l)		/* nothing */
   #define make_local_sl(n, a, l)	/* nothing */
 #endif
 
-#if defined(MR_INSERT_LABELS) || defined(PROFILE_CALLS) \
-		|| defined(MR_CHOOSE_ENTRY_POINT)
-  #define make_entry(n, a, l)		insert_entry(n, a, NULL)
-  #define make_entry_sl(n, a, l)	insert_entry(n, a, MR_STACK_LAYOUT(l))
+#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))
 #else
   #define make_entry(n, a, l)		/* nothing */
   #define make_entry_sl(n, a, l)	/* nothing */
Index: runtime/mercury_label.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_label.c,v
retrieving revision 1.6
diff -u -u -r1.6 mercury_label.c
--- mercury_label.c	1998/03/16 12:23:30	1.6
+++ mercury_label.c	1998/07/01 04:09:29
@@ -23,44 +23,76 @@
 #include	"mercury_engine.h"	/* for `progdebug' */
 #include	"mercury_wrapper.h"	/* for do_init_modules() */
 
-static	const void	*entry_name(const void *entry);
-static	const void	*entry_addr(const void *entry);
-static	bool		equal_name(const void *name1, const void *name2);
+/*
+** We record information about entry labels in an array that
+** we sort by code address once all the entry labels have been inserted.
+** Space for the array is provided by malloc, and it is expanded when
+** needed.
+**
+** This array is needed only by accurate garbage collection and when
+** doing low-level debugging.
+*/
+
+#ifdef	MR_NEED_ENTRY_LABEL_ARRAY
+
+/* the number of entries in the initial array */
+#define	INIT_ENTRY_SIZE	(1 << 8)
+
+static	int		compare_entry_by_addr(const void *e1, const void *e2);
+
+static	MR_Entry	*entry_array;
+static	int		entry_array_size;	/* # of entries allocated */
+static	int		entry_array_next;	/* # of entries used      */
+static	bool		entry_array_sorted;
+
+#endif	/* MR_NEED_ENTRY_LABEL_ARRAY */
+
+/*
+** We record information about internal labels in a hash table
+** that is indexed by the code address of the label.
+**
+** This table is used by stack tracing and execution tracing.
+** Since execution tracing and hence stack tracing can be required
+** in any grade, we always include this table.
+*/
+
+#define	INTERNAL_SIZE	(1 << 16)	/* 64k */
+
+static	const void	*internal_addr(const void *internal);
 static	bool		equal_addr(const void *addr1, const void *addr2);
-static	int		hash_name(const void *name);
 static	int		hash_addr(const void *addr);
 
-int	entry_table_size = (1 << 16);	/* 64k */
+static	Table		internal_addr_table = {INTERNAL_SIZE, NULL,
+				internal_addr, hash_addr, equal_addr};
 
-Table	entry_name_table =
-	{0, NULL, entry_name, hash_name, equal_name};
-Table	entry_addr_table =
-	{0, NULL, entry_addr, hash_addr, equal_addr};
-
 void 
-do_init_entries(void)
+MR_do_init_label_tables(void)
 {
-	static bool done = FALSE;
+	static	bool	done = FALSE;
+
 	if (!done) {
-		entry_name_table.ta_size = entry_table_size;
-		entry_addr_table.ta_size = entry_table_size;
-		init_table(entry_name_table);
-		init_table(entry_addr_table);
+#ifdef	MR_NEED_ENTRY_LABEL_ARRAY
+		entry_array_next = 0;
+		entry_array_size = INIT_ENTRY_SIZE;
+		entry_array_sorted = TRUE;
+		entry_array = malloc(entry_array_size * sizeof(MR_Entry));
+#endif
+
+		init_table(internal_addr_table);
+
 		done = TRUE;
 	}
 }
 
-Label *
-insert_entry(const char *name, Code *addr, Word *entry_layout_info)
-{
-	Label	*entry;
+#ifdef	MR_NEED_ENTRY_LABEL_INFO
 
-	do_init_entries();
+static	int	compare_entry_addr(const void *e1, const void *e2);
 
-	entry = make(Label);
-	entry->e_name  = name;
-	entry->e_addr  = addr;
-	entry->e_layout = entry_layout_info;
+void
+MR_insert_entry_label(const char *name, Code *addr,
+	const MR_Stack_Layout_Entry *entry_layout)
+{
+	MR_do_init_label_tables();
 
 #ifdef	PROFILE_CALLS
 	if (MR_profiling) MR_prof_output_addr_decl(name, addr);
@@ -68,74 +100,132 @@
 
 #ifdef	MR_LOWLEVEL_DEBUG
 	if (progdebug) {
-		printf("inserting label %s at %p\n", name, addr);
+		printf("recording entry label %s at %p\n", name, addr);
 	}
 #endif
+
+#ifdef	MR_NEED_ENTRY_LABEL_ARRAY
 
-	if (insert_table(entry_name_table, entry)) {
-		printf("duplicated label name %s\n", name);
+	if (entry_array_next >= entry_array_size) {
+		entry_array_size *= 2;
+		if (realloc(entry_array, entry_array_size * sizeof(MR_Entry))
+				== NULL) {
+			fatal_error("run out of memory for entry label array");
+		}
 	}
 
-	/* two labels at same location will happen quite often */
-	/* when the code generated between them turns out to be empty */
+	entry_array[entry_array_next].e_addr = addr;
+	entry_array[entry_array_next].e_name = name;
+	entry_array[entry_array_next].e_layout = entry_layout;
+	entry_array_next++;
+	entry_array_sorted = FALSE;
+#endif
+}
+
+#endif
 
-	(void) insert_table(entry_addr_table, entry);
+#ifdef	MR_NEED_ENTRY_LABEL_ARRAY
 
-	return entry;
+static int
+compare_entry_addr(const void *e1, const void *e2)
+{
+	const MR_Entry	*entry1;
+	const MR_Entry	*entry2;
+
+	entry1 = (const MR_Entry *) e1;
+	entry2 = (const MR_Entry *) e2;
+
+	if (entry1->e_addr > entry2->e_addr) {
+		return 1;
+	} else if (entry1->e_addr < entry2->e_addr) {
+		return -1;
+	} else {
+		return 0;
+	}
 }
 
-Label *
-lookup_label_addr(const Code *addr)
+MR_Entry *
+MR_prev_entry_by_addr(const Code *addr)
 {
-	do_init_entries();
-	do_init_modules();
-#ifdef	MR_LOWLEVEL_DEBUG
-	if (progdebug) {
-		printf("looking for label at %p\n", addr);
+	int	lo;
+	int	hi;
+	int	mid;
+	int	i;
+
+	if (!entry_array_sorted) {
+		qsort(entry_array, entry_array_next, sizeof(MR_Entry),
+			compare_entry_addr);
+
+		entry_array_sorted = TRUE;
 	}
-#endif
+
+	lo = 0;
+	hi = entry_array_next-1;
 
-	return (Label *) lookup_table(entry_addr_table, addr);
+	while (lo <= hi) {
+		mid = (lo + hi) / 2;
+		if (entry_array[mid].e_addr == addr) {
+			return &entry_array[mid];
+		} else if (entry_array[mid].e_addr < addr) {
+			lo = mid + 1;
+		} else {
+			hi = mid - 1;
+		}
+	}
+
+	if (entry_array[lo].e_addr < addr) {
+		return &entry_array[lo];
+	} else {
+		return &entry_array[lo-1];
+	}
 }
 
-Label *
-lookup_label_name(const char *name)
-{
-	do_init_entries();
-	do_init_modules();
+#endif
+
+void
+MR_insert_internal_label(const char *name, Code *addr,
+	const MR_Stack_Layout_Label *label_layout)
+{
+	MR_Internal	*internal;
+
+	MR_do_init_label_tables();
+
+	internal = make(MR_Internal);
+	internal->i_addr = addr;
+	internal->i_layout = label_layout;
+	internal->i_name = name;
+
 #ifdef	MR_LOWLEVEL_DEBUG
 	if (progdebug) {
-		printf("looking for label %s\n", name);
+		printf("inserting internal label %s at %p\n", name, addr);
 	}
 #endif
 
-	return (Label *) lookup_table(entry_name_table, name);
+	/* two labels at same location will happen quite often */
+	/* when the code generated between them turns out to be empty */
+
+	(void) insert_table(internal_addr_table, internal);
 }
 
-List *
-get_all_labels(void)
+MR_Internal *
+MR_lookup_internal_by_addr(const Code *addr)
 {
-	do_init_entries();
+	MR_do_init_label_tables();
 	do_init_modules();
-	return get_all_entries(entry_name_table);
-}
 
-static const void *
-entry_name(const void *entry)
-{
-	return (const void *) (((const Label *) entry)->e_name);
-}
+#ifdef	MR_LOWLEVEL_DEBUG
+	if (progdebug) {
+		printf("looking for internal label at %p\n", addr);
+	}
+#endif
 
-static const void *
-entry_addr(const void *entry)
-{
-	return (const void *) (((const Label *) entry)->e_addr);
+	return (MR_Internal *) lookup_table(internal_addr_table, addr);
 }
 
-static bool 
-equal_name(const void *name1, const void *name2)
+static const void *
+internal_addr(const void *internal)
 {
-	return streq(((const char *) name1), ((const char *) name2));
+	return (const void *) (((const MR_Internal *) internal)->i_addr);
 }
 
 static bool 
@@ -145,13 +235,13 @@
 }
 
 static int 
-hash_name(const void *name)
+hash_addr(const void *addr)
 {
-	return str_to_int(((const char *) name)) % entry_table_size;
+	return (((Unsigned) addr) >> 3) % INTERNAL_SIZE;
 }
 
-static int 
-hash_addr(const void *addr)
+void
+MR_process_all_internal_labels(void f(const void *))
 {
-	return (((Unsigned) addr) >> 3) % entry_table_size;
+	process_all_entries(internal_addr_table, f);
 }
Index: runtime/mercury_label.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_label.h,v
retrieving revision 1.4
diff -u -u -r1.4 mercury_label.h
--- mercury_label.h	1998/04/21 05:51:37	1.4
+++ mercury_label.h	1998/07/01 04:09:15
@@ -15,24 +15,63 @@
 #ifndef	MERCURY_LABEL_H
 #define	MERCURY_LABEL_H
 
-#include "mercury_types.h"	/* for `Code *' */
-#include "mercury_dlist.h"		/* for `List' */
+#include "mercury_types.h"		/* for `Code *' */
+#include "mercury_dlist.h" 		/* for `List' */
+#include "mercury_stack_layout.h"	/* for `MR_Stack_Layout_*' */
 
-typedef struct s_label {
-	const char	*e_name;   /* name of the procedure	     */
-	Code		*e_addr;   /* address of the code	     */
-	Word		*e_layout; /* layout info for the label      */
-} Label;
-
-extern	void	do_init_entries(void);
-extern	Label	*insert_entry(const char *name, Code *addr,
-			Word * entry_layout_info);
-extern	Label	*lookup_label_name(const char *name);
-extern	Label	*lookup_label_addr(const Code *addr);
-extern	List	*get_all_labels(void);
-
-extern  int 	entry_table_size;
-	/* expected number of entries in the table */
-	/* we allocate 8 bytes per entry */
+#if     defined(NATIVE_GC) || defined(MR_DEBUG_GOTOS)
+  #define	MR_NEED_ENTRY_LABEL_ARRAY
+#endif
+
+#if     defined(MR_NEED_ENTRY_LABEL_ARRAY) || defined(PROFILE_CALLS)
+  #define	MR_NEED_ENTRY_LABEL_INFO
+#endif
+
+/*
+** This struct records information about entry labels. Elements in the
+** entry label array are of this type. The table is sorted on address,
+** to allow the garbage collector to locate the entry label of the procedure 
+** to which an internal label belongs by a variant of binary search.
+**
+** The name field is needed only for low-level debugging.
+*/
+
+typedef struct s_entry {
+	const Code			*e_addr;
+	const MR_Stack_Layout_Entry	*e_layout;
+	const char			*e_name;
+} MR_Entry;
+
+/*
+** This struct records information about internal (non-entry) labels.
+** The internal label table is organized as a hash table, with the address
+** being the key.
+**
+** The name field is needed only for low-level debugging.
+*/
+
+typedef struct s_internal {
+	const Code			*i_addr;
+	const MR_Stack_Layout_Label	*i_layout;
+	const char			*i_name;
+} MR_Internal;
+
+extern	void		MR_do_init_label_tables(void);
+
+#ifdef	MR_NEED_ENTRY_LABEL_INFO
+extern	void		MR_insert_entry_label(const char *name, Code *addr,
+				const MR_Stack_Layout_Entry *entry_layout);
+#else
+#define	MR_insert_entry_label(n, a, l)	/* nothing */
+#endif	/* not MR_NEED_ENTRY_LABEL_INFO */
+
+#ifdef	MR_NEED_ENTRY_LABEL_ARRAY
+extern	MR_Entry	*MR_prev_entry_by_addr(const Code *addr);
+#endif	/* MR_NEED_ENTRY_LABEL_ARRAY */
+
+extern	void		MR_insert_internal_label(const char *name, Code *addr,
+				const MR_Stack_Layout_Label *label_layout);
+extern	MR_Internal	*MR_lookup_internal_by_addr(const Code *addr);
+extern	void		MR_process_all_internal_labels(void f(const void *));
 
 #endif /* not MERCURY_LABEL_H */
Index: runtime/mercury_misc.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_misc.c,v
retrieving revision 1.7
diff -u -u -r1.7 mercury_misc.c
--- mercury_misc.c	1998/06/09 02:08:11	1.7
+++ mercury_misc.c	1998/06/23 07:34:23
@@ -8,6 +8,7 @@
 #include	"mercury_dlist.h"
 #include	"mercury_regs.h"
 #include	"mercury_trace.h"
+#include	"mercury_label.h"
 #include	"mercury_misc.h"
 
 #include	<stdio.h>
@@ -214,19 +215,13 @@
 
 #endif /* defined(MR_LOWLEVEL_DEBUG) */
 
-#if defined(MR_DEBUG_GOTOS)
+#ifdef MR_DEBUG_GOTOS
 
 void 
 goto_msg(/* const */ Code *addr)
 {
 	printf("\ngoto ");
 	printlabel(addr);
-
-	if (detaildebug) {
-		printregs("registers at goto");
-	}
-
-	return;
 }
 
 void 
@@ -254,7 +249,7 @@
 
 /*--------------------------------------------------------------------*/
 
-#if defined(MR_DEBUG_GOTOS)
+#ifdef MR_LOWLEVEL_DEBUG
 
 /* debugging printing tools */
 
@@ -410,16 +405,25 @@
 void 
 printlabel(/* const */ Code *w)
 {
-	Label	*label;
+	MR_Internal	*internal;
 
-	label = lookup_label_addr(w);
-	if (label != NULL) {
-		printf("label %s (0x%p)\n", label->e_name, w);
+	internal = MR_lookup_internal_by_addr(w);
+	if (internal != NULL) {
+		printf("label %s (0x%p)\n", internal->i_name, w);
 	} else {
+#ifdef	MR_DEBUG_GOTOS
+		MR_Entry	*entry;
+		entry = MR_prev_entry_by_addr(w);
+		if (entry->e_addr == w) {
+			printf("label %s (0x%p)\n", entry->e_name, w);
+		} else {
+			printf("label UNKNOWN (0x%p)\n", w);
+		}
+#else
 		printf("label UNKNOWN (0x%p)\n", w);
+#endif	/* not MR_DEBUG_GOTOS */
 	}
 }
-
 
 void *
 newmem(size_t n)
Index: runtime/mercury_misc.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_misc.h,v
retrieving revision 1.6
diff -u -u -r1.6 mercury_misc.h
--- mercury_misc.h	1998/06/09 02:08:12	1.6
+++ mercury_misc.h	1998/06/30 06:38:48
@@ -17,7 +17,6 @@
 #include "mercury_types.h"	/* for `Code *' */
 
 #ifdef MR_LOWLEVEL_DEBUG
-
 extern	void	mkframe_msg(void);
 extern	void	modframe_msg(void);
 extern	void	succeed_msg(void);
@@ -35,16 +34,13 @@
 extern	void	push_msg(Word val, const Word *addr);
 extern	void	pop_msg(Word val, const Word *addr);
 #endif
-
-#if defined(MR_DEBUG_GOTOS)
 
+#ifdef MR_DEBUG_GOTOS
 extern	void	goto_msg(/* const */ Code *addr);
 extern	void	reg_msg(void);
-
 #endif
 
 #ifdef MR_LOWLEVEL_DEBUG
-
 extern	void	printint(Word n);
 extern	void	printstring(const char *s);
 extern	void	printheap(const Word *h);
@@ -55,12 +51,10 @@
 extern	void	printlist(Word p);
 extern	void	printframe(const char *);
 extern	void	printregs(const char *msg);
-
 #endif
 
 extern	void	printlabel(/* const */ Code *w);
 
-
 #if __GNUC__
 	#define NO_RETURN __attribute__((noreturn))
 #else
@@ -76,6 +70,6 @@
 ** XXX We should fix this eventually by using -fno-builtin since pragma
 ** c_code may call the builtin functions.
 */
-void MR_memcpy(char *dest, const char *src, size_t nbytes);
+extern	void	MR_memcpy(char *dest, const char *src, size_t nbytes);
 
 #endif /* not MERCURY_MISC_H */
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.9
diff -u -u -r1.9 mercury_stack_trace.c
--- mercury_stack_trace.c	1998/06/18 06:08:05	1.9
+++ mercury_stack_trace.c	1998/06/29 06:36:17
@@ -39,15 +39,17 @@
 	"cc_multi"	/* 14 */
 };
 
-static	MR_Stack_Walk_Step_Result MR_stack_walk_step(MR_Stack_Layout_Entry *,
-			MR_Stack_Layout_Label **, Word **, Word **,
-			const char **);
+static	MR_Stack_Walk_Step_Result MR_stack_walk_step(
+			const MR_Stack_Layout_Entry *,
+			const MR_Stack_Layout_Label **,
+			Word **, Word **, const char **);
 
 static	void	MR_dump_stack_record_init(void);
-static	void	MR_dump_stack_record_frame(FILE *fp, MR_Stack_Layout_Entry *);
+static	void	MR_dump_stack_record_frame(FILE *fp,
+			const MR_Stack_Layout_Entry *);
 static	void	MR_dump_stack_record_flush(FILE *fp);
-static	void	MR_dump_stack_record_print(FILE *fp, MR_Stack_Layout_Entry *,
-			int, int);
+static	void	MR_dump_stack_record_print(FILE *fp,
+			const MR_Stack_Layout_Entry *, int, int);
 
 void
 MR_dump_stack(Code *success_pointer, Word *det_stack_pointer,
@@ -80,11 +82,11 @@
 }
 
 const char *
-MR_dump_stack_from_layout(FILE *fp, MR_Stack_Layout_Entry *entry_layout,
+MR_dump_stack_from_layout(FILE *fp, const MR_Stack_Layout_Entry *entry_layout,
 	Word *det_stack_pointer, Word *current_frame)
 {
 	MR_Stack_Walk_Step_Result	result;
-	MR_Stack_Layout_Label		*return_label_layout;
+	const MR_Stack_Layout_Label	*return_label_layout;
 	const char			*problem;
 	Word				*stack_trace_sp;
 	Word				*stack_trace_curfr;
@@ -125,7 +127,7 @@
 	const char **problem)
 {
 	MR_Stack_Walk_Step_Result	result;
-	MR_Stack_Layout_Label		*return_label_layout;
+	const MR_Stack_Layout_Label	*return_label_layout;
 	int				i;
 
 	*problem = NULL;
@@ -144,17 +146,17 @@
 }
 
 
-static	MR_Stack_Walk_Step_Result
-MR_stack_walk_step(MR_Stack_Layout_Entry *entry_layout,
-	MR_Stack_Layout_Label **return_label_layout,
+static 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)
 {
-	Label			*label;
+	MR_Internal		*label;
 	MR_Live_Lval		location;
-	MR_Stack_Layout_Label	*label_layout;
 	MR_Lval_Type		type;
-	int			number, determinism;
+	int			number;
+	int			determinism;
 	Code			*success;
 
 	*return_label_layout = NULL;
@@ -192,26 +194,25 @@
 		return STEP_OK;
 	}
 
-	label = lookup_label_addr(success);
+	label = MR_lookup_internal_by_addr(success);
 	if (label == NULL) {
 		*problem_ptr = "reached label with no stack trace info";
 		return STEP_ERROR_AFTER;
 	}
 
-	label_layout = (MR_Stack_Layout_Label *) label->e_layout;
-	if (label_layout == NULL) {
+	if (label->i_layout == NULL) {
 		*problem_ptr = "reached label with no stack layout info";
 		return STEP_ERROR_AFTER;
 	}
 
-	*return_label_layout = label_layout;
+	*return_label_layout = label->i_layout;
 	return STEP_OK;
 }
 
-static	MR_Stack_Layout_Entry	*prev_entry_layout;
-static	int			prev_entry_layout_count;
-static	int			prev_entry_start_level;
-static	int			current_level;
+static	const MR_Stack_Layout_Entry	*prev_entry_layout;
+static	int				prev_entry_layout_count;
+static	int				prev_entry_start_level;
+static	int				current_level;
 
 static void
 MR_dump_stack_record_init(void)
@@ -223,7 +224,7 @@
 }
 
 static void
-MR_dump_stack_record_frame(FILE *fp, MR_Stack_Layout_Entry *entry_layout)
+MR_dump_stack_record_frame(FILE *fp, const MR_Stack_Layout_Entry *entry_layout)
 {
 	if (entry_layout == prev_entry_layout) {
 		prev_entry_layout_count++;
@@ -247,7 +248,7 @@
 }
 
 static void
-MR_dump_stack_record_print(FILE *fp, MR_Stack_Layout_Entry *entry_layout,
+MR_dump_stack_record_print(FILE *fp, const MR_Stack_Layout_Entry *entry_layout,
 	int count, int start_level)
 {
 	fprintf(fp, "%9d ", start_level);
Index: runtime/mercury_stack_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.h,v
retrieving revision 1.6
diff -u -u -r1.6 mercury_stack_trace.h
--- mercury_stack_trace.h	1998/06/18 06:08:07	1.6
+++ mercury_stack_trace.h	1998/06/30 06:38:48
@@ -52,7 +52,7 @@
 */
 
 extern	const char	*MR_dump_stack_from_layout(FILE *fp,
-				MR_Stack_Layout_Entry *entry_layout,
+				const MR_Stack_Layout_Entry *entry_layout,
 				Word *det_stack_pointer, Word *current_frame);
 
 extern	const MR_Stack_Layout_Label *MR_find_nth_ancestor(
Index: runtime/mercury_table.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_table.c,v
retrieving revision 1.3
diff -u -u -r1.3 mercury_table.c
--- mercury_table.c	1997/11/23 09:31:50	1.3
+++ mercury_table.c	1998/06/23 07:50:07
@@ -120,6 +120,23 @@
 }
 
 /*
+**	Process all table entries with the specified function.
+*/
+
+void
+tab_process_all_entries(const Table *table, void f(const void *))
+{
+	reg	List	*ptr;
+	reg	int	i;
+
+	for (i = 0; i < table->ta_size; i++) {
+		for_list (ptr, table->ta_store[i]) {
+			(*f)(ldata(ptr));
+		}
+	}
+}
+
+/*
 **	Convert a string to a positive int. The return value
 **	mod the table size is a good hash value.
 */
Index: runtime/mercury_table.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_table.h,v
retrieving revision 1.4
diff -u -u -r1.4 mercury_table.h
--- mercury_table.h	1998/05/17 07:03:14	1.4
+++ mercury_table.h	1998/06/30 06:38:48
@@ -28,20 +28,22 @@
 						    /* applied to two keys */
 } Table;
 
-#define	init_table(t)		tab_init_table(&t)
-#define	lookup_table(t, k)	tab_lookup_table(&t, (const void *) k)
-#define	insert_table(t, e)	tab_insert_table(&t, (void *) e)
-#define	get_all_entries(t)	tab_get_all_entries(&t)
-#define	str_to_int(val)		tab_str_to_int(val)
+#define	init_table(t)			tab_init_table(&t)
+#define	lookup_table(t, k)		tab_lookup_table(&t, (const void *) k)
+#define	insert_table(t, e)		tab_insert_table(&t, (void *) e)
+#define	get_all_entries(t)		tab_get_all_entries(&t)
+#define	process_all_entries(t, f)	tab_process_all_entries(&t, f)
+#define	str_to_int(val)			tab_str_to_int(val)
 
-#define	tablekey(table)		(*(table->ta_key))
-#define	tablehash(table)	(*(table->ta_hash))
-#define	tableequal(table)	(*(table->ta_equal))
+#define	tablekey(table)			(*(table->ta_key))
+#define	tablehash(table)		(*(table->ta_hash))
+#define	tableequal(table)		(*(table->ta_equal))
 
 extern	void	tab_init_table(Table *);
 extern	void *	tab_lookup_table(const Table *, const void *);
 extern	bool	tab_insert_table(const Table *, void *);
 extern	List	*tab_get_all_entries(const Table *);
+extern	void	tab_process_all_entries(const Table *, void f(const void *));
 extern	int	tab_str_to_int(const char *);
 
 #endif /* not MERCURY_TABLE_H */
Index: runtime/mercury_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace.c,v
retrieving revision 1.13
diff -u -u -r1.13 mercury_trace.c
--- mercury_trace.c	1998/05/16 07:28:21	1.13
+++ mercury_trace.c	1998/06/23 08:33:07
@@ -31,71 +31,6 @@
 #include <stdio.h>
 #include <unistd.h>		/* for the write system call */
 
-/*
-** Do we want to use the debugger within this process, or do want to use
-** the Opium-style trace analyzer debugger implemented by an external process.
-** This variable is set in mercury_wrapper.c and never modified afterwards.
-*/
-
-MR_trace_type	MR_trace_handler = MR_TRACE_INTERNAL;
-
-/*
-** Compiler generated tracing code will check whether MR_trace_enabled is true,
-** before calling MR_trace. For now, and until we implement interface tracing,
-** MR_trace_enabled should keep the same value throughout the execution of
-** the entire program after being set in mercury_wrapper.c. There is one
-** exception to this: the Mercury routines called as part of the functionality
-** of the tracer itself (e.g. the term browser) should always be executed
-** with MR_trace_enabled set to FALSE.
-*/
-
-bool		MR_trace_enabled = FALSE;
-
-/*
-** MR_trace_call_seqno counts distinct calls. The prologue of every
-** procedure assigns the current value of this counter as the sequence number
-** of that invocation and increments the counter. This is the only way that
-** MR_trace_call_seqno is modified.
-**
-** MR_trace_call_depth records the current depth of the call tree. The prologue
-** of every procedure assigns the current value of this variable plus one
-** as the depth of that invocation. Just before making a call, the caller
-** will set MR_trace_call_depth to its own remembered depth value. 
-** These are the only ways in which MR_trace_call_depth is modified.
-**
-** Although neither MR_trace_call_seqno nor MR_trace_call_depth are used
-** directly in this module, the seqno and depth arguments of MR_trace
-** always derive their values from the saved values of these two global
-** variables.
-*/
-
-Unsigned	MR_trace_call_seqno = 0;
-Unsigned	MR_trace_call_depth = 0;
-
-/*
-** MR_trace_event_number is a simple counter of events. This is used in
-** two places: here, for display to the user and for skipping a given number
-** of events, and when printing an abort message, so that the programmer
-** can zero in on the source of the problem more quickly.
-*/
-
-Unsigned	MR_trace_event_number = 0;
-
-/*
-** MR_trace_from_full is a boolean that is set before every call;
-** it states whether the caller is being fully traced, or only interface
-** traced. If the called code is interface traced, it will generate
-** call, exit and fail trace events only if MR_trace_from_full is true.
-** (It will never generate internal events.) If the called code is fully
-** traced, it will always generate all trace events, external and internal,
-** regardless of the setting of this variable on entry.
-**
-** The initial value is set to TRUE to allow the programmer to gain
-** control in the debugger when main/2 is called.
-*/
-
-Bool	MR_trace_from_full = 1;
-
 static	MR_trace_cmd_info	MR_trace_ctrl = { MR_CMD_GOTO, 0, 0, FALSE };
 
 static	void	MR_trace_event(MR_trace_cmd_info *cmd,
@@ -107,40 +42,6 @@
 			MR_trace_port port, Unsigned seqno, Unsigned depth,
 			const char *path, int max_r_num);
 
-void
-MR_trace_init(void)
-{
-#ifdef MR_USE_EXTERNAL_DEBUGGER
-	if (MR_trace_handler == MR_TRACE_EXTERNAL)
-		MR_trace_init_external();
-#endif
-}
-
-void
-MR_trace_final(void)
-{
-#ifdef MR_USE_EXTERNAL_DEBUGGER
-	if (MR_trace_handler == MR_TRACE_EXTERNAL)
-		MR_trace_final_external();
-#endif
-}
-
-void
-MR_trace_start(bool enabled)
-{
-	MR_trace_event_number = 0;
-	MR_trace_call_seqno = 0;
-	MR_trace_call_depth = 0;
-	MR_trace_from_full = TRUE;
-	MR_trace_enabled = enabled;
-}
-
-void
-MR_trace_end(void)
-{
-	MR_trace_enabled = FALSE;
-}
-
 /*
 ** This function is called from compiled code whenever an event to be traced
 ** occurs.
@@ -261,35 +162,4 @@
 
 	MR_trace_event_internal_report(layout, port, seqno, depth, path);
 #endif
-}
-
-void
-MR_trace_report(FILE *fp)
-{
-	if (MR_trace_event_number > 0) {
-		/*
-		** This means that the executable was compiled with tracing,
-		** which implies that the user wants trace info on abort.
-		*/
-
-		fprintf(fp, "Last trace event was event #%ld.\n",
-			(long) MR_trace_event_number);
-	}
-}
-
-void
-MR_trace_report_raw(int fd)
-{
-	char	buf[80];	/* that ought to be more than long enough */
-
-	if (MR_trace_event_number > 0) {
-		/*
-		** This means that the executable was compiled with tracing,
-		** which implies that the user wants trace info on abort.
-		*/
-
-		sprintf(buf, "Last trace event was event #%ld.\n",
-			(long) MR_trace_event_number);
-		write(fd, buf, strlen(buf));
-	}
 }
Index: runtime/mercury_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace.h,v
retrieving revision 1.8
diff -u -u -r1.8 mercury_trace.h
--- mercury_trace.h	1998/05/16 07:28:23	1.8
+++ mercury_trace.h	1998/06/30 08:44:57
@@ -13,23 +13,28 @@
 ** (b)	It defines the interface by which the internal and external debuggers
 **	can control how the tracing subsystem treats events.
 **
-** The macros and functions defined in this module are intended to be called
-** only from code generated by the Mercury compiler, and from hand-written
-** code in the Mercury runtime or the Mercury standard library.
+** The macros, functions and variables of this module are intended to be
+** referred to only from code generated by the Mercury compiler, and from
+** hand-written code in the Mercury runtime or the Mercury standard library,
+** and even then only if at least some part of the program was compiled
+** with some form of execution tracing.
+**
+** The parts of the tracing system that need to be present even when no
+** part of the program is compiled with execution tracing are in the module
+** mercury_trace_base.
 */
 
 #ifndef MERCURY_TRACE_H
 #define MERCURY_TRACE_H
 
+#include "mercury_trace_base.h"
+
 /* The interface between the tracing subsystem and compiled code. */
 
 #define	MR_trace_incr_seq()	(++MR_trace_call_seqno)
 #define	MR_trace_incr_depth()	(++MR_trace_call_depth)
 #define	MR_trace_reset_depth(d)	do { MR_trace_call_depth = (d); } while (0)
 
-extern	Word	MR_trace_call_seqno;
-extern	Word	MR_trace_call_depth;
-
 /*
 ** This enum should exactly match the definition of the `trace_port' type in
 ** library/debugger_interface.
@@ -55,51 +60,6 @@
 	const char *,		/* path to event goal within procedure */
 	int,			/* highest numbered rN register in use */
 	bool);			/* is this event supposed to be traced */
-
-/*
-** These functions will report the number of the last event,
-** if there have been some events, and will do nothing otherwise.
-*/
-
-extern	void	MR_trace_report(FILE *fp);
-extern	void	MR_trace_report_raw(int fd);
-
-/*
-** MR_trace_init() is called from mercury_runtime_init()
-** when the debuggee programs begins, to perform any initialization
-** that must be done before any traced Mercury code is executed.
-** This includes the initialization code written in Mercury as well as main.
-**
-** MR_trace_start(enabled) is called from mercury_runtime_init()
-** after the initialization code written in Mercury is executed,
-** when we are about to start executing main. The argument says
-** whether tracing is enabled for main (it is never enabled for
-** initialization and finalization routines).
-**
-** MR_trace_end() is called from mercury_runtime_terminate() just
-** after main has terminated and just before we call the finalization
-** code written in Mercury.
-**
-** MR_trace_final() is called from mercury_runtime_terminate()
-** after all Mercury code, including finalization code, has terminated.
-*/
-
-extern	void	MR_trace_init(void);
-extern	void	MR_trace_start(bool enabled);
-extern	void	MR_trace_end(void);
-extern	void	MR_trace_final(void);
-
-typedef	enum {
-	MR_TRACE_INTERNAL,
-	MR_TRACE_EXTERNAL
-} MR_trace_type;
-
-extern	MR_trace_type	MR_trace_handler;
-extern	bool		MR_trace_enabled;
-
-extern	Unsigned	MR_trace_event_number;
-
-extern	Bool		MR_trace_from_full;
 
 /* The interface between the debuggers and the tracing subsystem. */
 
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.14
diff -u -u -r1.14 mercury_wrapper.c
--- mercury_wrapper.c	1998/06/18 04:30:47	1.14
+++ mercury_wrapper.c	1998/07/01 09:06:04
@@ -479,7 +479,7 @@
 	unsigned long size;
 	int c;
 
-	while ((c = getopt(argc, argv, "acC:d:D:hLlP:pr:s:tT:w:xz:")) != EOF)
+	while ((c = getopt(argc, argv, "acC:d:D:P:pr:s:tT:xz:")) != EOF)
 	{
 		switch (c)
 		{
@@ -563,31 +563,6 @@
 
 			break;
 
-		case 'h':
-			usage();
-			break;
-
-		case 'L': 
-			do_init_modules();
-			break;
-
-		case 'l': {
-			List	*ptr;
-			List	*label_list;
-
-			label_list = get_all_labels();
-			for_list (ptr, label_list) {
-				Label	*label;
-				label = (Label *) ldata(ptr);
-				printf("%lu %lx %s\n",
-					(unsigned long) label->e_addr,
-					(unsigned long) label->e_addr,
-					label->e_name);
-			}
-
-			exit(0);
-		}
-
 		case 'p':
 			MR_profiling = FALSE;
 			break;
@@ -619,9 +594,6 @@
 				detstack_size = size;
 			else if (optarg[0] == 'n')
 				nondstack_size = size;
-			else if (optarg[0] == 'l')
-				entry_table_size = size *
-					1024 / (2 * sizeof(List *));
 #ifdef MR_USE_TRAIL
 			else if (optarg[0] == 't')
 				trail_size = size;
@@ -656,22 +628,6 @@
 			}
 			break;
 
-		case 'w': {
-			Label *which_label;
-
-			which_label = lookup_label_name(optarg);
-			if (which_label == NULL)
-			{
-				fprintf(stderr, "Mercury runtime: "
-					"label name `%s' unknown\n",
-					optarg);
-				exit(1);
-			}
-
-			program_entry_point = which_label->e_addr;
-
-			break;
-		}
 		case 'x':
 #ifdef CONSERVATIVE_GC
 			GC_dont_gc = TRUE;
@@ -708,54 +664,10 @@
 static void 
 usage(void)
 {
-	printf("Mercury runtime usage:\n"
-		"MERCURY_OPTIONS=\"[-hclLtxp] [-T[rvp]] [-d[abcdghs]]\n"
-        "                  [-[szt][hdn]#] [-C#] [-r#]  [-w name] [-[123]#]\"\n"
-		"-h \t\tprint this usage message\n"
-		"-c \t\tcheck cross-function stack usage\n"
-		"-l \t\tprint all labels\n"
-		"-L \t\tcheck for duplicate labels\n"
-		"-t \t\ttime program execution\n"
-		"-x \t\tdisable garbage collection\n"
-		"-p \t\tdisable profiling\n"
-		"-Tr \t\tprofile real time (using ITIMER_REAL)\n"
-		"-Tv \t\tprofile user time (using ITIMER_VIRTUAL)\n"
-		"-Tp \t\tprofile user + system time (using ITIMER_PROF)\n"
-		"-dg \t\tdebug gotos\n"
-		"-dc \t\tdebug calls\n"
-		"-db \t\tdebug backtracking\n"
-		"-dh \t\tdebug heap\n"
-		"-ds \t\tdebug detstack\n"
-		"-df \t\tdebug final success/failure\n"
-		"-da \t\tdebug all\n"
-		"-dm \t\tdebug memory allocation\n"
-		"-dG \t\tdebug garbage collection\n"
-		"-dd \t\tdetailed debug\n"
-		"-Di \t\tdebug the program using the internal debugger\n"
-#ifdef MR_USE_EXTERNAL_DEBUGGER
-		"-De \t\tdebug the program using the external debugger\n"
-#endif
-		"-sh<n> \t\tallocate n kb for the heap\n"
-		"-sd<n> \t\tallocate n kb for the det stack\n"
-		"-sn<n> \t\tallocate n kb for the nondet stack\n"
-#ifdef MR_USE_TRAIL
-		"-st<n> \t\tallocate n kb for the trail\n"
-#endif
-		"-sl<n> \t\tallocate n kb for the label table\n"
-		"-zh<n> \t\tallocate n kb for the heap redzone\n"
-		"-zd<n> \t\tallocate n kb for the det stack redzone\n"
-		"-zn<n> \t\tallocate n kb for the nondet stack redzone\n"
-#ifdef MR_USE_TRAIL
-		"-zt<n> \t\tallocate n kb for the trail redzone\n"
-#endif
-		"-C<n> \t\tprimary cache size in kbytes\n"
-#ifdef PARALLEL
-		"-P<n> \t\tnumber of processes to use for parallel execution\n"
-		"\t\tapplies only if Mercury is configured with --enable-parallel\n"
-#endif
-		"-r<n> \t\trepeat n times\n"
-		"-w<name> \tcall predicate with given name (default: main/2)\n"
-		);
+	printf("The MERCURY_OPTIONS environment variable "
+		"contains an invalid option.\n"
+		"Please refer to the Environment Variables section of "
+		"the Mercury\nuser's guide for details.\n");
 	fflush(stdout);
 	exit(1);
 } /* end usage() */
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing scripts
Index: scripts/c2init.in
===================================================================
RCS file: /home/mercury1/repository/mercury/scripts/c2init.in,v
retrieving revision 1.15
diff -u -u -r1.15 c2init.in
--- c2init.in	1998/05/30 13:34:09	1.15
+++ c2init.in	1998/07/01 09:04:43
@@ -19,6 +19,16 @@
 Name:	c2init - Create Mercury initialization file.
 Usage:	c2init [options] *.c *.init ...
 Options: 
+	-c <n>, --max-calls <n>
+		Break up the initialization into groups of at most <n> function
+		calls.  (Default value of <n> is 40.)
+	-i, --include-initialization-code
+		Always include code that calls the initialization functions
+		of the various modules. With this option, the debugger can use
+		information from any modules that were compiled with execution
+		tracing to print (partial) stack traces, and to print the
+		values of variables in ancestors of the current call, even
+		in grades in which this not normally possible.
 	-l, --library
 		Don't generate a \`main()' function.
 		Instead, generate a function
@@ -26,18 +36,15 @@
 		(declared in \"init.h\") that can be called from C code.
 		(A more fine-grained interface is also available;
 		see \"init.h\" for details.)
+	-w <label>, --entry-point <label>
+		Set entry point to <label>.
+		(Default value is \`mercury__main_2_0'.)
 	-x, --extra-inits
 		Search \`.c' files for extra initialization functions.
 		(This may be necessary if the C files contain
 		hand-coded C code with \`INIT' comments, rather than
 		containing only C code that was automatically generated
 		by the Mercury compiler.)
-	-c <n>, --max-calls <n>
-		Break up the initialization into groups of at most <n> function
-		calls.  (Default value of <n> is 40.)
-	-w <label>, --entry-point <label>
-		Set entry point to <label>.
-		(Default value is \`mercury__main_2_0'.)
 Environment variables:
 	MERCURY_MOD_LIB_DIR, MERCURY_MOD_LIB_MODS, MERCURY_MKINIT.
 "
@@ -52,18 +59,21 @@
 # maximum number of calls to put in a single function
 maxcalls=40
 defentry=mercury__main_2_0
+init_opt=""
 library_opt=""
 extra_inits_opt=""
 while true; do
 	case "$1" in
 	-c|--max-calls)
 		maxcalls="$2"; shift; shift;;
-	-w|--entry-point)
-		defentry="$2"; shift; shift;;
+	-i|--include-initialization-code)
+		init_opt="-i"; shift;;
 	-l|--library)
 		library_opt="-l"; shift;;
 	-l-|--no-library)
 		library_opt=""; shift;;
+	-w|--entry-point)
+		defentry="$2"; shift; shift;;
 	-x|--extra-inits)
 		extra_inits_opt="-x"; shift;;
 	-x-|--no-extra-inits)
@@ -83,10 +93,10 @@
 done
 
 case $# in
-	0) exec $MKINIT -w"$defentry" -c"$maxcalls" $library_opt \
-		$extra_inits_opt $MERCURY_MOD_LIB_MODS
+	0) exec $MKINIT -c"$maxcalls" $init_opt $library_opt \
+		-w"$defentry" $extra_inits_opt $MERCURY_MOD_LIB_MODS
 	   ;;
-	*) exec $MKINIT -w"$defentry" -c"$maxcalls" $library_opt \
-		$extra_inits_opt "$@" $MERCURY_MOD_LIB_MODS
+	*) exec $MKINIT -c"$maxcalls" $init_opt $library_opt \
+		-w"$defentry" $extra_inits_opt "$@" $MERCURY_MOD_LIB_MODS
 	   ;;
 esac
cvs diff: Diffing tests
cvs diff: [22:47:49] waiting for zs's lock in /home/mercury1/repository/tests
cvs diff: [22:48:19] obtained lock in /home/mercury1/repository/tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
Index: tests/debugger/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/Mmakefile,v
retrieving revision 1.5
diff -u -u -r1.5 Mmakefile
--- Mmakefile	1998/05/18 02:05:11	1.5
+++ Mmakefile	1998/06/24 10:45:42
@@ -14,6 +14,7 @@
 	queens
 
 MCFLAGS = --trace all $(EXTRA_MCFLAGS)
+EXTRA_C2INITFLAGS = -i
 
 # Not all grades can be used with stack layouts
 #
Index: tests/debugger/debugger_regs_lib.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/debugger_regs_lib.exp,v
retrieving revision 1.1
diff -u -u -r1.1 debugger_regs_lib.exp
--- debugger_regs_lib.exp	1998/05/16 07:31:04	1.1
+++ debugger_regs_lib.exp	1998/06/25 06:27:19
@@ -2,14 +2,6 @@
 mtrace>        2:      2  2 CALL DET   debugger_regs_lib:data/41-0 
 mtrace>        3:      2  2 EXIT DET   debugger_regs_lib:data/41-0 
 mtrace>           HeadVar__1           		[1, 2, 3, 4, 5]
-          HeadVar__2           		a0
-          HeadVar__3           		a1
-          HeadVar__4           		a2
-          HeadVar__5           		a3
-          HeadVar__6           		a4
-          HeadVar__7           		a5
-          HeadVar__8           		a6
-          HeadVar__9           		a7
           HeadVar__10          		a8
           HeadVar__11          		a9
           HeadVar__12          		b0
@@ -20,6 +12,7 @@
           HeadVar__17          		b5
           HeadVar__18          		b6
           HeadVar__19          		b7
+          HeadVar__2           		a0
           HeadVar__20          		b8
           HeadVar__21          		b9
           HeadVar__22          		c0
@@ -30,6 +23,7 @@
           HeadVar__27          		c5
           HeadVar__28          		c6
           HeadVar__29          		c7
+          HeadVar__3           		a1
           HeadVar__30          		c8
           HeadVar__31          		c9
           HeadVar__32          		d0
@@ -40,8 +34,14 @@
           HeadVar__37          		d5
           HeadVar__38          		d6
           HeadVar__39          		d7
+          HeadVar__4           		a2
           HeadVar__40          		d8
           HeadVar__41          		d9
+          HeadVar__5           		a3
+          HeadVar__6           		a4
+          HeadVar__7           		a5
+          HeadVar__8           		a6
+          HeadVar__9           		a7
 mtrace> a0a1a2a3a4a5a6a7a8a9
 b0b1b2b3b4b5b6b7b8b9
 c0c1c2c3c4c5c6c7c8c9
Index: tests/debugger/debugger_regs_lib.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/debugger_regs_lib.inp,v
retrieving revision 1.1
diff -u -u -r1.1 debugger_regs_lib.inp
--- debugger_regs_lib.inp	1998/05/16 07:31:08	1.1
+++ debugger_regs_lib.inp	1998/06/25 06:26:14
@@ -1,4 +1,4 @@
 
 
-p
+p *
 c
Index: tests/debugger/interpreter_lib.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/interpreter_lib.exp,v
retrieving revision 1.1
diff -u -u -r1.1 interpreter_lib.exp
--- interpreter_lib.exp	1998/05/16 07:31:15	1.1
+++ interpreter_lib.exp	1998/06/25 06:37:34
@@ -9,23 +9,36 @@
 F:			finish this call, printing the trace.
 <N> g:			go to event #N, not printing the trace.
 <N> G:			go to event #N, printing the trace.
-p:			print the variables live at this point.
+v:			list the names of the variables live at this point.
+l <n>:			set ancestor level to <n>
+p <n>:			print variable #n (or all vars if <n> is '*')
 r:			continue until forward execution is resumed.
 [<N>] [s]:		skip N events, not printing the trace (default: N=1).
 [<N>] S:		skip N events, printing the trace (default: N=1).
 ?:			list all the breakpoints.
 + <N>:			enable breakpoint #N.
 - <N>:			disable breakpoint #N.
-mtrace> mtrace> Pure Prolog Interpreter.
+mtrace> Pure Prolog Interpreter.
 
 Consulting file `interpreter_lib.m'...
-      45:     20  4 CALL DET   interpreter_lib:consult_until_eof/4-0 
-mtrace>           HeadVar__1           		[]
-          HeadVar__3           		state('<<c_pointer>>')
-mtrace>       47:     22  6 CALL DET   parser:read_term/3-0 
+      46:     21  5 CALL DET   term_io:read_term/3-0 
+mtrace>         0 HeadVar__2
 mtrace>           HeadVar__2           		state('<<c_pointer>>')
-mtrace>    13300:     22  6 EXIT DET   parser:read_term/3-0 
-mtrace>           HeadVar__1           		term(varset(0, empty, empty), functor(atom(":-"), [functor(atom("module"), [functor(atom("interpreter"), [], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22)))
-          HeadVar__3           		state('<<c_pointer>>')
-mtrace>  0: + interpreter_lib:consult_until_eof
-mtrace> mtrace> ?- 
\ No newline at end of file
+mtrace>  0: + interpreter_lib:database_assert_clause
+mtrace>    13446:   5011  6 CALL DET   interpreter_lib:database_assert_clause/4-0 
+mtrace>           HeadVar__1           		[]
+          HeadVar__2           		varset(0, empty, empty)
+          HeadVar__3           		functor(atom(":-"), [functor(atom("module"), [functor(atom("interpreter_lib"), [], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22))
+mtrace>    13447:   5011  6 ELSE DET   interpreter_lib:database_assert_clause/4-0 e;
+   13448:   5012  7 CALL DET   term:context_init/1-0 
+   13449:   5012  7 EXIT DET   term:context_init/1-0 
+   13450:   5011  6 EXIT DET   interpreter_lib:database_assert_clause/4-0 
+mtrace>           HeadVar__1           		[]
+          HeadVar__2           		varset(0, empty, empty)
+          HeadVar__3           		functor(atom(":-"), [functor(atom("module"), [functor(atom("interpreter_lib"), [], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22))
+          HeadVar__4           		[clause(varset(0, empty, empty), functor(atom(":-"), [functor(atom("module"), [functor(atom("interpreter_lib"), [], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22))], context("interpreter_lib.m", 22)), functor(atom("true"), [], context("", 0)))]
+mtrace>    13451:   5013  6 CALL DET   interpreter_lib:consult_until_eof/4-0 
+mtrace>   368828:   5013  6 EXIT DET   interpreter_lib:consult_until_eof/4-0 
+mtrace>   368829:   5010  5 EXIT DET   interpreter_lib:consult_until_eof_2/5-0 
+mtrace>   368830:     20  4 EXIT DET   interpreter_lib:consult_until_eof/4-0 
+mtrace> ?- 
\ No newline at end of file
Index: tests/debugger/interpreter_lib.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/interpreter_lib.inp,v
retrieving revision 1.1
diff -u -u -r1.1 interpreter_lib.inp
--- interpreter_lib.inp	1998/05/16 07:31:19	1.1
+++ interpreter_lib.inp	1998/06/25 06:36:12
@@ -1,11 +1,14 @@
 h
-b interpreter_lib consult_until_eof
+45s
+v
+p *
+b interpreter_lib database_assert_clause
 c
-p
-2s
-p
+p *
+F
+p *
+
 f
-p
-?
-- 0
+
+
 c
Index: tests/debugger/queens_lib.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/queens_lib.exp,v
retrieving revision 1.1
diff -u -u -r1.1 queens_lib.exp
--- queens_lib.exp	1998/05/16 07:31:26	1.1
+++ queens_lib.exp	1998/06/25 06:27:48
@@ -1,7 +1,7 @@
        1:      1  1 CALL CCMUL queens_lib:main/2-0 
 mtrace>           HeadVar__1           		state('<<c_pointer>>')
 mtrace>        2:      2  2 CALL DET   queens_lib:data/1-0 
-mtrace> mtrace: no live variables
+mtrace> mtrace: there are no live variables
 mtrace>        3:      2  2 EXIT DET   queens_lib:data/1-0 
 mtrace>           HeadVar__1           		[1, 2, 3, 4, 5]
 mtrace>        4:      3  2 CALL NON   queens_lib:queen/2-0 
@@ -14,12 +14,17 @@
 mtrace>           HeadVar__2           		[1, 2, 3, 4, 5]
 mtrace>        8:      5  4 DISJ NON   queens_lib:qdelete/3-0 c2;d1;
 mtrace>           HeadVar__2           		[1, 2, 3, 4, 5]
-          V_11                 		1
           V_10                 		[2, 3, 4, 5]
+          V_11                 		1
+mtrace> Ancestor level set to 1
+mtrace>           HeadVar__1           		[1, 2, 3, 4, 5]
+mtrace> Ancestor level set to 2
+mtrace>         0 HeadVar__1
+mtrace>           HeadVar__1           		[1, 2, 3, 4, 5]
 mtrace>        9:      5  4 EXIT NON   queens_lib:qdelete/3-0 
 mtrace>           HeadVar__1           		1
-          HeadVar__3           		[2, 3, 4, 5]
           HeadVar__2           		[1, 2, 3, 4, 5]
+          HeadVar__3           		[2, 3, 4, 5]
 mtrace>       10:      6  4 CALL NON   queens_lib:qperm/2-0 
 mtrace>           HeadVar__1           		[2, 3, 4, 5]
 mtrace>       11:      6  4 SWTC NON   queens_lib:qperm/2-0 s1;
@@ -28,12 +33,12 @@
 mtrace>           HeadVar__2           		[2, 3, 4, 5]
 mtrace>       13:      7  5 DISJ NON   queens_lib:qdelete/3-0 c2;d1;
 mtrace>           HeadVar__2           		[2, 3, 4, 5]
-          V_11                 		2
           V_10                 		[3, 4, 5]
+          V_11                 		2
 mtrace>       14:      7  5 EXIT NON   queens_lib:qdelete/3-0 
 mtrace>           HeadVar__1           		2
-          HeadVar__3           		[3, 4, 5]
           HeadVar__2           		[2, 3, 4, 5]
+          HeadVar__3           		[3, 4, 5]
 mtrace>       15:      8  5 CALL NON   queens_lib:qperm/2-0 
 mtrace>           HeadVar__1           		[3, 4, 5]
 mtrace>       16:      8  5 SWTC NON   queens_lib:qperm/2-0 s1;
@@ -42,12 +47,12 @@
 mtrace>           HeadVar__2           		[3, 4, 5]
 mtrace>       18:      9  6 DISJ NON   queens_lib:qdelete/3-0 c2;d1;
 mtrace>           HeadVar__2           		[3, 4, 5]
-          V_11                 		3
           V_10                 		[4, 5]
+          V_11                 		3
 mtrace>       19:      9  6 EXIT NON   queens_lib:qdelete/3-0 
 mtrace>           HeadVar__1           		3
-          HeadVar__3           		[4, 5]
           HeadVar__2           		[3, 4, 5]
+          HeadVar__3           		[4, 5]
 mtrace>       20:     10  6 CALL NON   queens_lib:qperm/2-0 
 mtrace>           HeadVar__1           		[4, 5]
 mtrace>       21:     10  6 SWTC NON   queens_lib:qperm/2-0 s1;
@@ -56,12 +61,12 @@
 mtrace>           HeadVar__2           		[4, 5]
 mtrace>       23:     11  7 DISJ NON   queens_lib:qdelete/3-0 c2;d1;
 mtrace>           HeadVar__2           		[4, 5]
-          V_11                 		4
           V_10                 		[5]
+          V_11                 		4
 mtrace>       24:     11  7 EXIT NON   queens_lib:qdelete/3-0 
 mtrace>           HeadVar__1           		4
-          HeadVar__3           		[5]
           HeadVar__2           		[4, 5]
+          HeadVar__3           		[5]
 mtrace>       25:     12  7 CALL NON   queens_lib:qperm/2-0 
 mtrace>           HeadVar__1           		[5]
 mtrace>       26:     12  7 SWTC NON   queens_lib:qperm/2-0 s1;
@@ -70,33 +75,33 @@
 mtrace>           HeadVar__2           		[5]
 mtrace>       28:     13  8 DISJ NON   queens_lib:qdelete/3-0 c2;d1;
 mtrace>           HeadVar__2           		[5]
-          V_11                 		5
           V_10                 		[]
+          V_11                 		5
 mtrace>       29:     13  8 EXIT NON   queens_lib:qdelete/3-0 
 mtrace>           HeadVar__1           		5
-          HeadVar__3           		[]
           HeadVar__2           		[5]
+          HeadVar__3           		[]
 mtrace>       30:     14  8 CALL NON   queens_lib:qperm/2-0 
 mtrace>           HeadVar__1           		[]
 mtrace>       31:     14  8 SWTC NON   queens_lib:qperm/2-0 s2;
 mtrace> mtrace>       32:     14  8 EXIT NON   queens_lib:qperm/2-0 
-mtrace>           HeadVar__2           		[]
-          HeadVar__1           		[]
+mtrace>           HeadVar__1           		[]
+          HeadVar__2           		[]
 mtrace>       33:     12  7 EXIT NON   queens_lib:qperm/2-0 
-mtrace>           HeadVar__2           		[5]
-          HeadVar__1           		[5]
+mtrace>           HeadVar__1           		[5]
+          HeadVar__2           		[5]
 mtrace>       34:     10  6 EXIT NON   queens_lib:qperm/2-0 
-mtrace>           HeadVar__2           		[4, 5]
-          HeadVar__1           		[4, 5]
+mtrace>           HeadVar__1           		[4, 5]
+          HeadVar__2           		[4, 5]
 mtrace>       35:      8  5 EXIT NON   queens_lib:qperm/2-0 
-mtrace>           HeadVar__2           		[3, 4, 5]
-          HeadVar__1           		[3, 4, 5]
+mtrace>           HeadVar__1           		[3, 4, 5]
+          HeadVar__2           		[3, 4, 5]
 mtrace>       36:      6  4 EXIT NON   queens_lib:qperm/2-0 
-mtrace>           HeadVar__2           		[2, 3, 4, 5]
-          HeadVar__1           		[2, 3, 4, 5]
+mtrace>           HeadVar__1           		[2, 3, 4, 5]
+          HeadVar__2           		[2, 3, 4, 5]
 mtrace>       37:      4  3 EXIT NON   queens_lib:qperm/2-0 
-mtrace>           HeadVar__2           		[1, 2, 3, 4, 5]
-          HeadVar__1           		[1, 2, 3, 4, 5]
+mtrace>           HeadVar__1           		[1, 2, 3, 4, 5]
+          HeadVar__2           		[1, 2, 3, 4, 5]
 mtrace>       38:     15  3 CALL SEMI  queens_lib:safe/1-0 
 mtrace>           HeadVar__1           		[1, 2, 3, 4, 5]
 mtrace>       39:     15  3 SWTC SEMI  queens_lib:safe/1-0 s1;
cvs diff: Diffing tests/general
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trial
cvs diff: Diffing util
Index: util/mkinit.c
===================================================================
RCS file: /home/mercury1/repository/mercury/util/mkinit.c,v
retrieving revision 1.33
diff -u -u -r1.33 mkinit.c
--- mkinit.c	1998/06/08 08:29:17	1.33
+++ mkinit.c	1998/07/01 09:15:15
@@ -37,12 +37,13 @@
 static const char *progname = NULL;
 
 /* options and arguments, set by parse_options() */
-static const char *entry_point = "mercury__io__main_2_0";
+static const char *entry_point = "mercury__main_2_0";
 static int maxcalls = MAXCALLS;
 static int num_files;
 static char **files;
 static bool output_main_func = TRUE;
 static bool c_files_contain_extra_inits = FALSE;
+static bool need_initialization_code = FALSE;
 
 static int num_modules = 0;
 static int num_errors = 0;
@@ -178,6 +179,12 @@
 	"}\n"
 	;
 
+
+static const char if_need_to_init[] = 
+	"#if defined(MR_NEED_INITIALIZATION_CODE)\n\n"
+	;
+
+
 /* --- function prototypes --- */
 static	void parse_options(int argc, char *argv[]);
 static	void usage(void);
@@ -249,21 +256,25 @@
 parse_options(int argc, char *argv[])
 {
 	int	c;
-	while ((c = getopt(argc, argv, "c:w:lx")) != EOF) {
+	while ((c = getopt(argc, argv, "c:ilw:x")) != EOF) {
 		switch (c) {
 		case 'c':
 			if (sscanf(optarg, "%d", &maxcalls) != 1)
 				usage();
 			break;
 
-		case 'w':
-			entry_point = optarg;
+		case 'i':
+			need_initialization_code = TRUE;
 			break;
 
 		case 'l':
 			output_main_func = FALSE;
 			break;
 
+		case 'w':
+			entry_point = optarg;
+			break;
+
 		case 'x':
 			c_files_contain_extra_inits = TRUE;
 			break;
@@ -309,6 +320,10 @@
 {
 	int filenum;
 
+	if (! need_initialization_code) {
+		fputs(if_need_to_init, stdout);
+	}
+
 	fputs("static void init_modules_0(void)\n", stdout);
 	fputs("{\n", stdout);
 
@@ -316,7 +331,10 @@
 		process_file(files[filenum]);
 	}
 
-	fputs("}\n\n", stdout);
+	fputs("}\n", stdout);
+	if (! need_initialization_code) {
+		fputs("\n#endif\n\n", stdout);
+	}
 }
 
 static void 
@@ -327,8 +345,16 @@
 	fputs("static void init_modules(void)\n", stdout);
 	fputs("{\n", stdout);
 
+	if (! need_initialization_code) {
+		fputs(if_need_to_init, stdout);
+	}
+
 	for (i = 0; i <= num_modules; i++) {
 		printf("\tinit_modules_%d();\n", i);
+	}
+
+	if (! need_initialization_code) {
+		fputs("\n#endif\n", stdout);
 	}
 
 	fputs("}\n", stdout);



More information about the developers mailing list