diff: mdb I/O streams

Fergus Henderson fjh at cs.mu.OZ.AU
Fri Dec 18 00:29:17 AEDT 1998


This diff addresses Mark's review comments.
I'll commit this now.

--------------------

Estimated hours taken: 4

Add support to mdb for doing the debugger I/O in a different
window to the I/O of the program being debugged.

(TODO: I/O from the browser still goes to the standard I/O streams
rather than the debugger I/O streams.  I'll commit that later,
as a separate change.)

runtime/mercury_wrapper.h:
runtime/mercury_wrapper.c:
	Add new runtime options for specifying filenames
	for the mdb I/O streams.

doc/user_guide.texi:
	Document the new options.

trace/mercury_trace_internal.c:
	Add three new variables holding the mdb I/O streams.
	Initialise them based on the option settings.
	Change the code so that all I/O goes through these streams.

trace/mercury_trace_tables.c:
trace/mercury_trace_tables.h:
	Pass a `void *' parameter through MR_process_matching_procedures()
	to the function it calls.  This is needed by mercury_trace_internal.c
	to pass `MR_mdb_in' down to MR_print_proc_id_for_debugger().

runtime/mercury_stack_trace.c:
runtime/mercury_stack_trace.h:
	Add a `FILE *' parameter to MR_print_proc_id_for_debugger().

Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.154
diff -u -r1.154 user_guide.texi
--- user_guide.texi	1998/12/06 23:48:17	1.154
+++ user_guide.texi	1998/12/16 23:44:20
@@ -3790,36 +3790,60 @@
 @c Tells the Boehm collector not to perform any garbage collection.
 
 @sp 1
- at item --heap-size=@var{size}
+ at item --heap-size @var{size}
 Sets the size of the heap to @var{size} kilobytes.
 
 @sp 1
- at item --detstack-size=@var{size}
+ at item --detstack-size @var{size}
 Sets the size of the det stack to @var{size} kilobytes.
 
 @sp 1
- at item --nondetstack-size=@var{size}
+ at item --nondetstack-size @var{size}
 Sets the size of the nondet stack to @var{size} kilobytes.
 
 @sp 1
- at item --trail-size=@var{size}
+ at item --trail-size @var{size}
 Sets the size of the trail to @var{size} kilobytes.
 
 @c @sp 1
- at c @item --heap-redzone-size=@var{size}
+ at c @item --heap-redzone-size @var{size}
 @c Sets the size of the redzone on the heap to @var{size} kilobytes.
 
 @c @sp 1
- at c @item --detstack-redzone-size=@var{size}
+ at c @item --detstack-redzone-size @var{size}
 @c Sets the size of the redzone on the det stack to @var{size} kilobytes.
 
 @c @sp 1
- at c @item --nondetstack-redzone-size=@var{size}
+ at c @item --nondetstack-redzone-size @var{size}
 @c Sets the size of the redzone on the nondet stack to @var{size} kilobytes.
 
 @c @sp 1
- at c @item --trail-redzone-size=@var{size}
+ at c @item --trail-redzone-size @var{size}
 @c Sets the size of the redzone on the trail to @var{size} kilobytes.
+
+ at sp 1
+ at item -i @var{filename}
+ at itemx --mdb-in @var{filename}
+Read debugger input from the file or device specified by @var{filename},
+rather than from standard input.
+
+ at sp 1
+ at item -o @var{filename}
+ at item --mdb-out @var{filename}
+Print debugger output to the file or device specified by @var{filename},
+rather than to standard output.
+
+ at sp 1
+ at item -e @var{filename}
+ at itemx --mdb-err @var{filename}
+Print debugger error messages to the file or device specified by @var{filename},
+rather than to standard error.
+
+ at sp 1
+ at item -m @var{filename}
+ at itemx --mdb-tty @var{filename}
+Redirect all three debugger I/O streams -- input, output, and error messages --
+to the file or device specified by @var{filename}.
 
 @end table
 
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.23
diff -u -r1.23 mercury_stack_trace.c
--- mercury_stack_trace.c	1998/12/09 12:26:29	1.23
+++ mercury_stack_trace.c	1998/12/17 00:08:06
@@ -365,9 +365,10 @@
 }
 
 void
-MR_print_proc_id_for_debugger(const MR_Stack_Layout_Entry *entry_layout)
+MR_print_proc_id_for_debugger(FILE *fp,
+	const MR_Stack_Layout_Entry *entry_layout)
 {
-	MR_print_proc_id(stdout, entry_layout, NULL, NULL, NULL);
+	MR_print_proc_id(fp, entry_layout, NULL, NULL, NULL);
 }
 
 void
Index: runtime/mercury_stack_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.h,v
retrieving revision 1.13
diff -u -r1.13 mercury_stack_trace.h
--- mercury_stack_trace.h	1998/11/13 08:40:41	1.13
+++ mercury_stack_trace.h	1998/12/17 00:08:06
@@ -145,7 +145,7 @@
 ** call sequence number and call depth of the call.
 */
 
-extern	void	MR_print_proc_id_for_debugger(
+extern	void	MR_print_proc_id_for_debugger(FILE *fp,
 			const MR_Stack_Layout_Entry *entry);
 extern	void	MR_print_proc_id(FILE *fp, const MR_Stack_Layout_Entry *entry,
 			const char *extra, Word *base_sp, Word *base_curfr);
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.28
diff -u -r1.28 mercury_wrapper.c
--- mercury_wrapper.c	1998/11/05 03:53:48	1.28
+++ mercury_wrapper.c	1998/12/16 21:16:45
@@ -74,6 +74,11 @@
 /* primary cache size to optimize for, in bytes */
 size_t		pcache_size =	         8192;
 
+/* file names for mdb's debugger I/O streams */
+const char *MR_mdb_in_filename = NULL;
+const char *MR_mdb_out_filename = NULL;
+const char *MR_mdb_err_filename = NULL;
+
 /* other options */
 
 bool		check_space = FALSE;
@@ -510,7 +515,11 @@
 	MR_HEAP_REDZONE_SIZE,
 	MR_DETSTACK_REDZONE_SIZE,
 	MR_NONDETSTACK_REDZONE_SIZE,
-	MR_TRAIL_REDZONE_SIZE
+	MR_TRAIL_REDZONE_SIZE,
+	MR_MDB_TTY,
+	MR_MDB_IN,
+	MR_MDB_OUT,
+	MR_MDB_ERR
 };
 
 struct MR_option MR_long_opts[] = {
@@ -522,6 +531,10 @@
 	{ "detstack-redzone-size", 	1, 0, MR_DETSTACK_REDZONE_SIZE },
 	{ "nondetstack-redzone-size", 	1, 0, MR_NONDETSTACK_REDZONE_SIZE },
 	{ "trail-redzone-size", 	1, 0, MR_TRAIL_REDZONE_SIZE },
+	{ "mdb-tty", 			1, 0, MR_MDB_TTY },
+	{ "mdb-in", 			1, 0, MR_MDB_IN },
+	{ "mdb-out", 			1, 0, MR_MDB_OUT },
+	{ "mdb-err", 			1, 0, MR_MDB_ERR }
 };
 
 static void
@@ -531,7 +544,7 @@
 	int		c;
 	int		long_index;
 
-	while ((c = MR_getopt_long(argc, argv, "acC:d:D:P:pr:tT:x",
+	while ((c = MR_getopt_long(argc, argv, "acC:d:e:D:i:m:o:P:pr:tT:x",
 		MR_long_opts, &long_index)) != EOF)
 	{
 		switch (c)
@@ -591,6 +604,28 @@
 				usage();
 
 			trail_zone_size = size;
+			break;
+
+		case 'i':
+		case MR_MDB_IN:
+			MR_mdb_in_filename = MR_optarg;
+			break;
+
+		case 'o':
+		case MR_MDB_OUT:
+			MR_mdb_out_filename = MR_optarg;
+			break;
+
+		case 'e':
+		case MR_MDB_ERR:
+			MR_mdb_err_filename = MR_optarg;
+			break;
+
+		case 'm':
+		case MR_MDB_TTY:
+			MR_mdb_in_filename = MR_optarg;
+			MR_mdb_out_filename = MR_optarg;
+			MR_mdb_err_filename = MR_optarg;
 			break;
 
 		case 'a':
Index: runtime/mercury_wrapper.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.h,v
retrieving revision 1.15
diff -u -r1.15 mercury_wrapper.h
--- mercury_wrapper.h	1998/11/09 05:23:34	1.15
+++ mercury_wrapper.h	1998/12/16 21:15:36
@@ -135,6 +135,11 @@
 extern	size_t		global_heap_zone_size;
 extern	size_t		debug_heap_zone_size;
 
+/* file names for the mdb debugging streams */
+extern const char *MR_mdb_in_filename;
+extern const char *MR_mdb_out_filename;
+extern const char *MR_mdb_err_filename;
+
 /* size of the primary cache */
 extern	size_t		pcache_size;
 
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.18
diff -u -r1.18 mercury_trace_internal.c
--- mercury_trace_internal.c	1998/12/14 16:05:20	1.18
+++ mercury_trace_internal.c	1998/12/17 13:01:20
@@ -56,6 +56,19 @@
 ** should be thread local.
 */
 
+/*
+** Debugger I/O streams.
+** Replacements for stdin/stdout/stderr respectively.
+**
+** The distinction between MR_mdb_out and MR_mdb_err is analagous to
+** the distinction between stdout and stderr: ordinary output, including
+** information messages about conditions which are not errors, should
+** go to MR_mdb_out, but error messages should go to MR_mdb_err.
+*/
+static FILE *MR_mdb_in;
+static FILE *MR_mdb_out;
+static FILE *MR_mdb_err;
+
 static	MR_Trace_Print_Level	MR_default_print_level = MR_PRINT_LEVEL_SOME;
 
 /*
@@ -157,6 +170,9 @@
 static	void	MR_print_spy_point(int i);
 static	void	MR_trace_list_vars(const MR_Stack_Layout_Label *top_layout,
 			Word *saved_regs, int ancestor_level);
+static	void	MR_trace_set_level(const MR_Stack_Layout_Label *top_layout,
+			Word *saved_regs, int *ancestor_level,
+			int new_ancestor_level);
 static	const char *MR_trace_browse_check_level(const MR_Stack_Layout_Label
 			*top_layout, Word *saved_regs, int ancestor_level);
 static	void	MR_trace_browse_one(const MR_Stack_Layout_Label *top_layout,
@@ -172,6 +188,7 @@
 			*layout, int *var_count_ptr);
 static	const char *MR_trace_find_var(const MR_Stack_Layout_Label *layout,
 			MR_Var_Spec var_spec, int *which_var_ptr);
+static	void	MR_trace_do_noop(void);
 
 static	const char *MR_trace_read_help_text(void);
 static	bool	MR_trace_is_number(const char *word, int *value);
@@ -248,7 +265,7 @@
 	jumpaddr = NULL;
 
 	do {
-		line = MR_trace_getline("mdb> ", stdin);
+		line = MR_trace_getline("mdb> ", MR_mdb_in);
 		res = MR_trace_debug_cmd(line, cmd, layout, saved_regs,
 				&event_details, port, seqno, depth, path,
 				&ancestor_level, max_mr_num, &jumpaddr);
@@ -272,6 +289,23 @@
 mdb is free software, covered by the GNU General Public License.\n\
 There is absolutely no warranty for mdb.\n";
 
+static FILE *
+MR_try_fopen(const char *filename, const char *mode, FILE *default_file)
+{
+	if (filename == NULL) {
+		return default_file;
+	} else {
+		FILE *f = fopen(filename, mode);
+		if (f == NULL) {
+			fprintf(stderr, "mdb: error opening `%s': %s\n",
+				filename, strerror(errno));
+			return default_file;
+		} else {
+			return f;
+		}
+	}
+}
+
 static void
 MR_trace_internal_ensure_init(void)
 {
@@ -281,8 +315,12 @@
 		char	*env;
 		int	n;
 
+		MR_mdb_in = MR_try_fopen(MR_mdb_in_filename, "r", stdin);
+		MR_mdb_out = MR_try_fopen(MR_mdb_out_filename, "w", stdout);
+		MR_mdb_err = MR_try_fopen(MR_mdb_err_filename, "w", stderr);
+
 		if (getenv("MERCURY_SUPPRESS_MDB_BANNER") == NULL) {
-			printf(MR_trace_banner, MR_VERSION);
+			fprintf(MR_mdb_out, MR_trace_banner, MR_VERSION);
 		}
 
 		env = getenv("LINES");
@@ -348,6 +386,27 @@
 	free(buf);
 }
 
+static void
+MR_trace_do_noop(void)
+{
+	fprintf(MR_mdb_err,
+		"This command is a no-op from this port.\n");
+}
+
+/*
+** This function is just a wrapper for MR_print_proc_id_for_debugger,
+** with the first argument type being `void *' rather than `FILE *',
+** so that this function's address can be passed to
+** MR_process_matching_procedures().
+*/
+static void
+MR_mdb_print_proc_id(void *data, const MR_Stack_Layout_Entry *entry_layout)
+{
+	FILE *fp = data;
+	MR_print_proc_id_for_debugger(fp, entry_layout);
+}
+
+
 static MR_Next
 MR_trace_debug_cmd(char *line, MR_Trace_Cmd_Info *cmd,
 	const MR_Stack_Layout_Label *layout, Word *saved_regs,
@@ -386,13 +445,13 @@
 	}
 
 	if (MR_echo_commands) {
-		fputs(line, stdout);
-		putc('\n', stdout);
+		fputs(line, MR_mdb_out);
+		putc('\n', MR_mdb_out);
 	}
 
 	problem = MR_trace_parse_line(line, &words, &word_max, &word_count);
 	if (problem != NULL) {
-		printf("%s.\n", problem);
+		fprintf(MR_mdb_err, "%s.\n", problem);
 		goto return_keep_interacting;
 	}
 
@@ -420,7 +479,7 @@
 			cmd->MR_trace_print_level = MR_default_print_level;
 			goto return_stop_interacting;
 		} else {
-			printf("One of the first two words "
+			fprintf(MR_mdb_err, "One of the first two words "
 				"must be a command.\n");
 		}
 	} else if (streq(words[0], "step")) {
@@ -456,7 +515,8 @@
 				cmd->MR_trace_stop_event = n;
 				goto return_stop_interacting;
 			} else {
-				printf("The debugger cannot go "
+				/* XXX this message is misleading */
+				fprintf(MR_mdb_err, "The debugger cannot go "
 					"to a past event.\n");
 			}
 		} else {
@@ -483,7 +543,7 @@
 		}
 
 		if (depth == stop_depth && MR_port_is_final(port)) {
-			printf("This command is a no-op from this port.\n");
+			MR_trace_do_noop();
 		} else {
 			cmd->MR_trace_cmd = MR_CMD_FINISH;
 			cmd->MR_trace_stop_depth = stop_depth;
@@ -501,7 +561,7 @@
 				cmd->MR_trace_cmd = MR_CMD_RETURN;
 				goto return_stop_interacting;
 			} else {
-				printf("This command is a no-op from this port.\n");
+				MR_trace_do_noop();
 			}
 		} else {
 			MR_trace_usage("forward", "return");
@@ -521,7 +581,7 @@
 				cmd->MR_trace_cmd = MR_CMD_RESUME_FORWARD;
 				goto return_stop_interacting;
 			} else {
-				printf("This command is a no-op from this port.\n");
+				MR_trace_do_noop();
 			}
 		} else {
 			MR_trace_usage("forward", "forward");
@@ -611,7 +671,7 @@
 			cmd->MR_trace_print_level = MR_default_print_level;
 			goto return_stop_interacting;
 		} else if (stop_depth == depth && MR_port_is_entry(port)) {
-			printf("This command is a no-op from this port.\n");
+			MR_trace_do_noop();
 		} else {
 			char	*retry_cmd;
 
@@ -627,63 +687,28 @@
 		}
 	} else if (streq(words[0], "level")) {
 		if (word_count == 2 && MR_trace_is_number(words[1], &n)) {
-			problem = MR_trace_browse_check_level(layout,
-					saved_regs, n);
-			if (problem == NULL) {
-				*ancestor_level = n;
-				printf("Ancestor level set to %d.\n",
-					*ancestor_level);
-			} else {
-				printf("%s.\n", problem);
-			}
+			MR_trace_set_level(layout, saved_regs, ancestor_level,
+				n);
 		} else {
 			MR_trace_usage("browsing", "level");
 		}
 	} else if (streq(words[0], "up")) {
 		if (word_count == 2 && MR_trace_is_number(words[1], &n)) {
-			problem = MR_trace_browse_check_level(layout,
-					saved_regs, *ancestor_level + n);
-			if (problem == NULL) {
-				*ancestor_level += n;
-				printf("Ancestor level set to %d.\n",
-					*ancestor_level);
-			} else {
-				printf("%s.\n", problem);
-			}
+			MR_trace_set_level(layout, saved_regs, ancestor_level,
+				*ancestor_level + n);
 		} else if (word_count == 1) {
-			problem = MR_trace_browse_check_level(layout,
-					saved_regs, *ancestor_level + 1);
-			if (problem == NULL) {
-				*ancestor_level += 1;
-				printf("Ancestor level set to %d.\n",
-					*ancestor_level);
-			} else {
-				printf("%s.\n", problem);
-			}
+			MR_trace_set_level(layout, saved_regs, ancestor_level,
+				*ancestor_level + 1);
 		} else {
 			MR_trace_usage("browsing", "up");
 		}
 	} else if (streq(words[0], "down")) {
 		if (word_count == 2 && MR_trace_is_number(words[1], &n)) {
-			problem = MR_trace_browse_check_level(layout,
-					saved_regs, *ancestor_level - n);
-			if (problem == NULL) {
-				*ancestor_level -= n;
-				printf("Ancestor level set to %d.\n",
-					*ancestor_level);
-			} else {
-				printf("%s.\n", problem);
-			}
+			MR_trace_set_level(layout, saved_regs, ancestor_level,
+				*ancestor_level - n);
 		} else if (word_count == 1) {
-			problem = MR_trace_browse_check_level(layout,
-					saved_regs, *ancestor_level - 1);
-			if (problem == NULL) {
-				*ancestor_level -= 1;
-				printf("Ancestor level set to %d.\n",
-					*ancestor_level);
-			} else {
-				printf("%s.\n", problem);
-			}
+			MR_trace_set_level(layout, saved_regs, ancestor_level,
+				*ancestor_level - 1);
 		} else {
 			MR_trace_usage("browsing", "down");
 		}
@@ -742,16 +767,15 @@
 		{
 			; /* the usage message has already been printed */
 		} else if (word_count == 1) {
-			const char	*result;
-
+			const char	*msg;
 			do_init_modules();
-			result = MR_dump_stack_from_layout(stdout,
+			msg = MR_dump_stack_from_layout(MR_mdb_out,
 					layout->MR_sll_entry,
 					MR_saved_sp(saved_regs),
 					MR_saved_curfr(saved_regs),
 					include_trace_data);
-			if (result != NULL) {
-				printf("%s.\n", result);
+			if (msg != NULL) {
+				fprintf(MR_mdb_err, "%s.\n", msg);
 			}
 		} else {
 			MR_trace_usage("browsing", "stack");
@@ -783,7 +807,7 @@
 		{
 			; /* the usage message has already been printed */
 		} else if (word_count == 2 && streq(words[1], "here")) {
-			MR_register_all_modules_and_procs(stdout, TRUE);
+			MR_register_all_modules_and_procs(MR_mdb_out, TRUE);
 			MR_trace_internal_add_spy_point(MR_SPY_SPECIFIC,
 				action, layout->MR_sll_entry, layout);
 		} else if (word_count == 2 &&
@@ -792,7 +816,7 @@
 			const MR_Stack_Layout_Entry	*spy_proc;
 			bool				unique;
 
-			MR_register_all_modules_and_procs(stdout, TRUE);
+			MR_register_all_modules_and_procs(MR_mdb_out, TRUE);
 			spy_proc = MR_search_for_matching_procedure(&spec,
 					&unique);
 			if (spy_proc != NULL) {
@@ -800,14 +824,17 @@
 					MR_trace_internal_add_spy_point(when,
 						action, spy_proc, NULL);
 				} else {
-					printf("Ambiguous procedure "
+					fprintf(MR_mdb_err,
+						"Ambiguous procedure "
 						"specification. "
 						"The matches are:\n");
 					MR_process_matching_procedures(&spec,
-						MR_print_proc_id_for_debugger);
+						MR_mdb_print_proc_id,
+						MR_mdb_err);
 				}
 			} else {
-				printf("There is no such procedure.\n");
+				fprintf(MR_mdb_err,
+					"There is no such procedure.\n");
 			}
 		} else {
 			MR_trace_usage("breakpoint", "break");
@@ -818,7 +845,9 @@
 				MR_spy_points[n]->spy_enabled = TRUE;
 				MR_print_spy_point(n);
 			} else {
-				printf("Break point #%d does not exist.\n", n);
+				fprintf(MR_mdb_err,
+					"Break point #%d does not exist.\n",
+					n);
 			}
 		} else if (word_count == 2 && streq(words[1], "*")) {
 			for (i = 0; i < MR_spy_point_next; i++) {
@@ -827,7 +856,8 @@
 			}
 
 			if (MR_spy_point_next == 0) {
-				printf("There no break points yet.\n");
+				fprintf(MR_mdb_out,
+					"There no break points yet.\n");
 			}
 		} else {
 			MR_trace_usage("breakpoint", "enable");
@@ -838,7 +868,9 @@
 				MR_spy_points[n]->spy_enabled = FALSE;
 				MR_print_spy_point(n);
 			} else {
-				printf("Break point #%d does not exist.\n", n);
+				fprintf(MR_mdb_err,
+					"Break point #%d does not exist.\n",
+					n);
 			}
 		} else if (word_count == 2 && streq(words[1], "*")) {
 			for (i = 0; i < MR_spy_point_next; i++) {
@@ -847,7 +879,8 @@
 			}
 
 			if (MR_spy_point_next == 0) {
-				printf("There no break points yet.\n");
+				fprintf(MR_mdb_err,
+					"There no break points yet.\n");
 			}
 		} else {
 			MR_trace_usage("breakpoint", "disable");
@@ -860,21 +893,21 @@
 		{
 			; /* the usage message has already been printed */
 		} else if (word_count == 1) {
-			MR_register_all_modules_and_procs(stdout, verbose);
+			MR_register_all_modules_and_procs(MR_mdb_out, verbose);
 		} else {
 			MR_trace_usage("breakpoint", "register");
 		}
 	} else if (streq(words[0], "modules")) {
 		if (word_count == 1) {
-			MR_register_all_modules_and_procs(stdout, TRUE);
-			MR_dump_module_list(stdout);
+			MR_register_all_modules_and_procs(MR_mdb_out, TRUE);
+			MR_dump_module_list(MR_mdb_out);
 		} else {
 			MR_trace_usage("breakpoint", "modules");
 		}
 	} else if (streq(words[0], "procedures")) {
 		if (word_count == 2) {
-			MR_register_all_modules_and_procs(stdout, TRUE);
-			MR_dump_module_procs(stdout, words[1]);
+			MR_register_all_modules_and_procs(MR_mdb_out, TRUE);
+			MR_dump_module_procs(MR_mdb_out, words[1]);
 		} else {
 			MR_trace_usage("breakpoint", "procedures");
 		}
@@ -883,19 +916,22 @@
 			if (streq(words[1], "none")) {
 				MR_default_print_level = MR_PRINT_LEVEL_NONE;
 				if (MR_trace_internal_interacting) {
-					printf("Default print level set to "
+					fprintf(MR_mdb_out,
+						"Default print level set to "
 						"`none'.\n");
 				}
 			} else if (streq(words[1], "some")) {
 				MR_default_print_level = MR_PRINT_LEVEL_SOME;
 				if (MR_trace_internal_interacting) {
-					printf("Default print level set to "
+					fprintf(MR_mdb_out,
+						"Default print level set to "
 						"`some'.\n");
 				}
 			} else if (streq(words[1], "all")) {
 				MR_default_print_level = MR_PRINT_LEVEL_ALL;
 				if (MR_trace_internal_interacting) {
-					printf("Default print level set to "
+					fprintf(MR_mdb_out,
+						"Default print level set to "
 						"`all'.\n");
 				}
 			} else {
@@ -903,21 +939,21 @@
 					"printlevel");
 			}
 		} else if (word_count == 1) {
-			printf("The default print level is ");
+			fprintf(MR_mdb_out, "The default print level is ");
 			switch (MR_default_print_level) {
 				case MR_PRINT_LEVEL_NONE:
-					printf("`none'.\n");
+					fprintf(MR_mdb_out, "`none'.\n");
 					break;
 				case MR_PRINT_LEVEL_SOME:
-					printf("`some'.\n");
+					fprintf(MR_mdb_out, "`some'.\n");
 					break;
 				case MR_PRINT_LEVEL_ALL:
-					printf("`all'.\n");
+					fprintf(MR_mdb_out, "`all'.\n");
 					break;
 				default:
 					MR_default_print_level =
 						MR_PRINT_LEVEL_SOME;
-					printf("invalid "
+					fprintf(MR_mdb_out, "invalid "
 						"(now set to `some').\n");
 					break;
 			}
@@ -929,30 +965,33 @@
 			if (streq(words[1], "off")) {
 				MR_scroll_control = FALSE;
 				if (MR_trace_internal_interacting) {
-					printf("Scroll control disabled.\n");
+					fprintf(MR_mdb_out,
+						"Scroll control disabled.\n");
 				}
 			} else if (streq(words[1], "on")) {
 				MR_scroll_control = TRUE;
 				if (MR_trace_internal_interacting) {
-					printf("Scroll control enabled.\n");
+					fprintf(MR_mdb_out,
+						"Scroll control enabled.\n");
 				}
 			} else if (MR_trace_is_number(words[1], &n)) {
 				MR_scroll_limit = n;
 				if (MR_trace_internal_interacting) {
-					printf("Scroll window size set to "
+					fprintf(MR_mdb_out,
+						"Scroll window size set to "
 						"%d.\n", MR_scroll_limit);
 				}
 			} else {
 				MR_trace_usage("parameter", "scroll");
 			}
 		} else if (word_count == 1) {
-			printf("Scroll control is ");
+			fprintf(MR_mdb_out, "Scroll control is ");
 			if (MR_scroll_control) {
-				printf("on");
+				fprintf(MR_mdb_out, "on");
 			} else {
-				printf("off");
+				fprintf(MR_mdb_out, "off");
 			}
-			printf(", scroll window size is %d.\n",
+			fprintf(MR_mdb_out, ", scroll window size is %d.\n",
 				MR_scroll_limit);
 		} else {
 			MR_trace_usage("parameter", "scroll");
@@ -962,40 +1001,43 @@
 			if (streq(words[1], "off")) {
 				MR_echo_commands = FALSE;
 				if (MR_trace_internal_interacting) {
-					printf("Command echo disabled.\n");
+					fprintf(MR_mdb_out,
+						"Command echo disabled.\n");
 				}
 			} else if (streq(words[1], "on")) {
 				MR_echo_commands = TRUE;
 				if (MR_trace_internal_interacting) {
-					printf("Command echo enabled.\n");
+					fprintf(MR_mdb_out,
+						"Command echo enabled.\n");
 				}
 			} else {
 				MR_trace_usage("parameter", "echo");
 			}
 		} else if (word_count == 1) {
-			printf("Command echo is ");
+			fprintf(MR_mdb_out, "Command echo is ");
 			if (MR_echo_commands) {
-				printf("on.\n");
+				fprintf(MR_mdb_out, "on.\n");
 			} else {
-				printf("off.\n");
+				fprintf(MR_mdb_out, "off.\n");
 			}
 		} else {
 			MR_trace_usage("parameter", "echo");
 		}
 	} else if (streq(words[0], "alias")) {
 		if (word_count == 1) {
-			MR_trace_print_all_aliases(stdout);
+			MR_trace_print_all_aliases(MR_mdb_out);
 		} else if (word_count == 2) {
-			MR_trace_print_alias(stdout, words[1]);
+			MR_trace_print_alias(MR_mdb_out, words[1]);
 		} else {
 			if (MR_trace_valid_command(words[2])) {
 				MR_trace_add_alias(words[1],
 					words+2, word_count-2);
 				if (MR_trace_internal_interacting) {
-					MR_trace_print_alias(stdout, words[1]);
+					MR_trace_print_alias(MR_mdb_out, words[1]);
 				}
 			} else {
-				printf("%s is not a valid command.\n",
+				fprintf(MR_mdb_out,
+					"%s is not a valid command.\n",
 					words[2]);
 			}
 		}
@@ -1003,11 +1045,13 @@
 		if (word_count == 2) {
 			if (MR_trace_remove_alias(words[1])) {
 				if (MR_trace_internal_interacting) {
-					printf("Alias `%s' removed.\n",
+					fprintf(MR_mdb_out,
+						"Alias `%s' removed.\n",
 						words[1]);
 				}
 			} else {
-				printf("Alias `%s' cannot be removed, "
+				fprintf(MR_mdb_err,
+					"Alias `%s' cannot be removed, "
 					"since it does not exist.\n",
 					words[1]);
 			}
@@ -1027,7 +1071,8 @@
 		} else {
 			msg = MR_trace_add_cat(words[2], slot, help_text);
 			if (msg != NULL) {
-				printf("Document category `%s' not added: "
+				fprintf(MR_mdb_err,
+					"Document category `%s' not added: "
 					"%s.\n", words[2], msg);
 			}
 		}
@@ -1045,7 +1090,8 @@
 			msg = MR_trace_add_item(words[1], words[3], slot,
 				help_text);
 			if (msg != NULL) {
-				printf("Document item `%s' in category `%s' "
+				fprintf(MR_mdb_err,
+					"Document item `%s' in category `%s' "
 					"not added: %s.\n",
 					words[3], words[1], msg);
 			}
@@ -1117,14 +1163,15 @@
 	} else if (streq(words[0], "nondet_stack")) {
 		if (word_count == 1) {
 			do_init_modules();
-			MR_dump_nondet_stack_from_layout(stdout,
+			MR_dump_nondet_stack_from_layout(MR_mdb_out,
 				MR_saved_maxfr(saved_regs));
 		} else {
 			MR_trace_usage("developer", "nondet_stack");
 		}
 	} else if (streq(words[0], "stack_regs")) {
 		if (word_count == 1) {
-			printf("sp = %p, curfr = %p, maxfr = %p\n",
+			fprintf(MR_mdb_out,
+				"sp = %p, curfr = %p, maxfr = %p\n",
 				MR_saved_sp(saved_regs),
 				MR_saved_curfr(saved_regs),
 				MR_saved_maxfr(saved_regs));
@@ -1155,7 +1202,7 @@
 
 				line2 = MR_trace_getline(
 					"mdb: are you sure you want to quit? ",
-					stdin);
+					MR_mdb_in);
 				if (line2 == NULL) {
 					/* This means the user input EOF. */
 					confirmed = TRUE;
@@ -1183,7 +1230,7 @@
 			MR_trace_usage("misc", "quit");
 		}
 	} else {
-		printf("Unknown command `%s'. "
+		fprintf(MR_mdb_err, "Unknown command `%s'. "
 			"Give the command `help' for help.\n", words[0]);
 	}
 
@@ -1412,7 +1459,8 @@
 /* cat is unused now, but could be used later */
 {
 
-	printf("mdb: %s: usage error -- type `help %s' for help.\n",
+	fprintf(MR_mdb_err,
+		"mdb: %s: usage error -- type `help %s' for help.\n",
 		item, item);
 }
 
@@ -1435,7 +1483,8 @@
 	call_label = entry->MR_sle_call_label;
 
 	if (call_label->MR_sll_var_count < 0) {
-		printf("Cannot perform retry because information about "
+		fprintf(MR_mdb_err,
+			"Cannot perform retry, because information about "
 			"the input arguments is not available.\n");
 		return;
 	}
@@ -1458,7 +1507,8 @@
 				input_args->MR_slvs_names[i], &succeeded);
 
 		if (! succeeded) {
-			printf("Cannot perform retry because the values of "
+			fprintf(MR_mdb_err,
+				"Cannot perform retry because the values of "
 				"some input arguments are missing.\n");
 			return;
 		}
@@ -1584,12 +1634,12 @@
 static void
 MR_print_spy_point(int spy_point_num)
 {
-	printf("%2d: %1s %-5s %9s ",
+	fprintf(MR_mdb_out, "%2d: %1s %-5s %9s ",
 		spy_point_num,
 		MR_spy_points[spy_point_num]->spy_enabled ? "+" : "-",
 		MR_spy_action_string(MR_spy_points[spy_point_num]->spy_action),
 		MR_spy_when_string(MR_spy_points[spy_point_num]->spy_when));
-	MR_print_proc_id(stdout, MR_spy_points[spy_point_num]->spy_proc,
+	MR_print_proc_id(MR_mdb_out, MR_spy_points[spy_point_num]->spy_proc,
 		NULL, NULL, NULL);
 }
 
@@ -1612,19 +1662,37 @@
 				&base_sp, &base_curfr, &problem);
 
 	if (level_layout == NULL) {
-		printf("%s\n", problem);
+		fprintf(MR_mdb_err, "%s\n", problem);
 		return;
 	}
 
 	problem = MR_trace_validate_var_count(level_layout, &var_count);
 	if (problem != NULL) {
-		printf("mdb: %s.\n", problem);
+		fprintf(MR_mdb_err, "mdb: %s.\n", problem);
 		return;
 	}
 
 	vars = &level_layout->MR_sll_var_info;
 	for (i = 0; i < var_count; i++) {
-		printf("%9d %s\n", i, MR_name_if_present(vars, i));
+		fprintf(MR_mdb_out, "%9d %s\n",
+			i, MR_name_if_present(vars, i));
+	}
+}
+
+static void
+MR_trace_set_level(const MR_Stack_Layout_Label *layout,
+	Word *saved_regs, int *ancestor_level, int new_ancestor_level)
+{
+	const char *problem;
+	
+	problem = MR_trace_browse_check_level(layout, saved_regs,
+		new_ancestor_level);
+	if (problem == NULL) {
+		*ancestor_level = new_ancestor_level;
+		fprintf(MR_mdb_out, "Ancestor level set to %d.\n",
+			*ancestor_level);
+	} else {
+		fprintf(MR_mdb_err, "%s.\n", problem);
 	}
 }
 
@@ -1647,8 +1715,8 @@
 		return problem;
 	} else {
 		entry = label_layout->MR_sll_entry;
-		printf("%4d ", ancestor_level);
-		MR_print_proc_id(stdout, entry, "", base_sp, base_curfr);
+		fprintf(MR_mdb_out, "%4d ", ancestor_level);
+		MR_print_proc_id(MR_mdb_out, entry, "", base_sp, base_curfr);
 		if (MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry)) {
 			return NULL;
 		} else {
@@ -1677,13 +1745,13 @@
 				&base_sp, &base_curfr, &problem);
 
 	if (level_layout == NULL) {
-		printf("mdb: %s.\n", problem);
+		fprintf(MR_mdb_err, "mdb: %s.\n", problem);
 		return;
 	}
 
 	problem = MR_trace_find_var(level_layout, var_spec, &which_var);
 	if (problem != NULL) {
-		printf("mdb: %s.\n", problem);
+		fprintf(MR_mdb_err, "mdb: %s.\n", problem);
 		return;
 	}
 
@@ -1722,13 +1790,13 @@
 				&base_sp, &base_curfr, &problem);
 
 	if (level_layout == NULL) {
-		printf("mdb: %s.\n", problem);
+		fprintf(MR_mdb_err, "mdb: %s.\n", problem);
 		return;
 	}
 
 	problem = MR_trace_validate_var_count(level_layout, &var_count);
 	if (problem != NULL) {
-		printf("mdb: %s.\n", problem);
+		fprintf(MR_mdb_err, "mdb: %s.\n", problem);
 		return;
 	}
 
@@ -1775,12 +1843,13 @@
 
 	if (!browse) {
 		if (name != NULL) {
-			printf("%7s%-21s\t", "", name);
+			fprintf(MR_mdb_out, "%7s%-21s\t", "", name);
 		} else {
-			printf("%7s%-21s\t", "", "anonymous variable");
+			fprintf(MR_mdb_out, "%7s%-21s\t", "",
+				"anonymous variable");
 		}
 
-		fflush(stdout);
+		fflush(MR_mdb_out);
 	}
 
 
@@ -1794,10 +1863,12 @@
 			base_sp, base_curfr, type_params, &type_info, &value);
 	if (print_value) {
 		if (browse) {
+			/* XXX should use MR_mdb_in and MR_mdb_out */
 			MR_trace_browse(type_info, value);
 		} else {
-			printf("\t");
-			fflush(stdout);
+			fprintf(MR_mdb_out, "\t");
+			fflush(MR_mdb_out);
+			/* XXX should use MR_mdb_out */
 			MR_trace_print(type_info, value);
 		}
 	}
@@ -1890,7 +1961,7 @@
 	int	i;
 
 	next_char_slot = 0;
-	while ((text = MR_trace_getline("cat> ", stdin)) != NULL) {
+	while ((text = MR_trace_getline("cat> ", MR_mdb_in)) != NULL) {
 		if (streq(text, "end")) {
 			free(text);
 			break;
@@ -2130,7 +2201,7 @@
 		fclose(fp);
 		return TRUE;
 	} else {
-		printf("%s: %s.\n", filename, strerror(errno));
+		fprintf(MR_mdb_err, "%s: %s.\n", filename, strerror(errno));
 		return FALSE;
 	}
 }
@@ -2166,8 +2237,8 @@
 	}
 
 	MR_trace_internal_interacting = TRUE;
-	printf("%s", prompt);
-	fflush(stdout);
+	fprintf(MR_mdb_out, "%s", prompt);
+	fflush(MR_mdb_out);
 
 	return MR_trace_getline_raw(fp);
 }
@@ -2282,7 +2353,7 @@
 	/* We try to leave one line for the prompt itself. */
 	if (MR_scroll_control && MR_scroll_next >= MR_scroll_limit - 1) {
 	try_again:
-		buf = MR_trace_getline("--more-- ", stdin);
+		buf = MR_trace_getline("--more-- ", MR_mdb_in);
 		if (buf != NULL) {
 			for (i = 0; buf[i] != '\0' && MR_isspace(buf[i]); i++)
 				;
@@ -2316,7 +2387,8 @@
 								max_mr_num);
 
 					default:
-						printf("unknown command, "
+						fprintf(MR_mdb_err,
+							"unknown command, "
 							"try again\n");
 						free(buf);
 						goto try_again;
@@ -2339,65 +2411,68 @@
 MR_trace_event_print_internal_report(const MR_Stack_Layout_Label *layout,
 	MR_Trace_Port port, int seqno, int depth, const char *path)
 {
-	printf("%8ld: %6ld %2ld ",
+	fprintf(MR_mdb_out, "%8ld: %6ld %2ld ",
 		(long) MR_trace_event_number, (long) seqno, (long) depth);
 
 	MR_trace_print_port(port);
-	MR_print_proc_id(stdout, layout->MR_sll_entry, path, NULL, NULL);
+	MR_print_proc_id(MR_mdb_out, layout->MR_sll_entry, path, NULL, NULL);
 }
 
 static void
 MR_trace_print_port(MR_Trace_Port port)
 {
+	const char *port_name;
 	switch (port) {
 		case MR_PORT_CALL:
-			printf("CALL ");
+			port_name = "CALL";
 			break;
 
 		case MR_PORT_EXIT:
-			printf("EXIT ");
+			port_name = "EXIT";
 			break;
 
 		case MR_PORT_REDO:
-			printf("REDO ");
+			port_name = "REDO";
 			break;
 
 		case MR_PORT_FAIL:
-			printf("FAIL ");
+			port_name = "FAIL";
 			break;
 
 		case MR_PORT_THEN:
-			printf("THEN ");
+			port_name = "THEN";
 			break;
 
 		case MR_PORT_ELSE:
-			printf("ELSE ");
+			port_name = "ELSE";
 			break;
 
 		case MR_PORT_DISJ:
-			printf("DISJ ");
+			port_name = "DISJ";
 			break;
 
 		case MR_PORT_SWITCH:
-			printf("SWTC ");
+			port_name = "SWTC";
 			break;
 
 		case MR_PORT_PRAGMA_FIRST:
-			printf("FRST ");
+			port_name = "FRST";
 			break;
 
 		case MR_PORT_PRAGMA_LATER:
-			printf("LATR ");
+			port_name = "LATR";
 			break;
 
 		case MR_PORT_EXCEPTION:
-			printf("EXCP ");
+			port_name = "EXCP";
 			break;
 
 		default:
+			port_name = "????";
 			fatal_error("MR_trace_event_internal called "
 					"with bad port");
 	}
+	fprintf(MR_mdb_out, "%s ", port_name);
 }
 
 typedef struct
Index: trace/mercury_trace_tables.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_tables.c,v
retrieving revision 1.3
diff -u -r1.3 mercury_trace_tables.c
--- mercury_trace_tables.c	1998/11/14 03:43:11	1.3
+++ mercury_trace_tables.c	1998/12/17 13:27:59
@@ -35,7 +35,8 @@
 
 static	void		MR_process_matching_procedures_in_module(
 				MR_Module_Info *module, MR_Proc_Spec *spec,
-				void f(const MR_Stack_Layout_Entry *));
+				void f(void *, const MR_Stack_Layout_Entry *),
+				void *);
 
 void
 MR_register_all_modules_and_procs(FILE *fp, bool verbose)
@@ -297,34 +298,41 @@
 	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;
+/*
+** This struct is for communication between
+** MR_register_match and MR_search_for_matching_procedure.
+*/
+typedef struct {
+	const MR_Stack_Layout_Entry	*matching_entry;
+	bool	 			match_unique;
+} MR_match_info;
 
 static void
-MR_register_match(const MR_Stack_Layout_Entry *entry)
+MR_register_match(void *data, const MR_Stack_Layout_Entry *entry)
 {
-	if (matching_entry == NULL) {
-		matching_entry = entry;
+	MR_match_info *m = data;
+	if (m->matching_entry == NULL) {
+		m->matching_entry = entry;
 	} else {
-		match_unique = FALSE;
+		m->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;
+	MR_match_info m;
+	m.matching_entry = NULL;
+	m.match_unique = TRUE;
+	MR_process_matching_procedures(spec, MR_register_match, &m);
+	*unique = m.match_unique;
+	return m.matching_entry;
 }
 
 void
 MR_process_matching_procedures(MR_Proc_Spec *spec,
-	void f(const MR_Stack_Layout_Entry *))
+	void f(void *, const MR_Stack_Layout_Entry *),
+	void *data)
 {
 	if (spec->MR_proc_module != NULL) {
 		MR_Module_Info			*module;
@@ -332,14 +340,14 @@
 		module = MR_search_module_info(spec->MR_proc_module);
 		if (module != NULL) {
 			MR_process_matching_procedures_in_module(
-				module, spec, f);
+				module, spec, f, data);
 		}
 	} else {
 		int	i;
 
 		for (i = 0; i < MR_module_info_next; i++) {
 			MR_process_matching_procedures_in_module(
-				&MR_module_infos[i], spec, f);
+				&MR_module_infos[i], spec, f, data);
 		}
 	}
 }
@@ -362,7 +370,8 @@
 
 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_Spec *spec, void f(void *, const MR_Stack_Layout_Entry *),
+	void *data)
 {
 	MR_Proc_Node			*cur;
 	const MR_Stack_Layout_Entry	*cur_entry;
@@ -375,7 +384,7 @@
 				match_mode(spec, cur_entry) &&
 				match_pf(spec, cur_entry))
 		{
-			f(cur_entry);
+			f(data, cur_entry);
 		}
 	}
 }
Index: trace/mercury_trace_tables.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_tables.h,v
retrieving revision 1.1
diff -u -r1.1 mercury_trace_tables.h
--- mercury_trace_tables.h	1998/10/16 06:20:22	1.1
+++ mercury_trace_tables.h	1998/12/17 13:26:52
@@ -110,11 +110,15 @@
 					MR_Proc_Spec *spec, bool *unique);
 
 /*
-** Call f(entry) on the layout of every procedure that matches
-** the given specification.
+** MR_process_matching_procedures(spec, f, data):
+**	For each procedure that matches the specification given by `spec',
+**	call `f(data, entry)', where `entry' is the entry layout for that
+**	procedure.  The argument `data' is a `void *' which can be used
+**	to pass any other information needed by the function `f'.
 */
 
 extern	void	MR_process_matching_procedures(MR_Proc_Spec *spec,
-			void f(const MR_Stack_Layout_Entry *));
+			void f(void *, const MR_Stack_Layout_Entry *), 
+			void *data);
 
 #endif	/* not MERCURY_TRACE_TABLES_H */
Fergus Henderson <fjh at cs.mu.oz.au>  |  "Binaries may die
WWW: <http://www.cs.mu.oz.au/~fjh>  |   but source code lives forever"
PGP: finger fjh at 128.250.37.3        |     -- leaked Microsoft memo.



More information about the developers mailing list