for review: a primitive four-port debugger

Zoltan Somogyi zs at cs.mu.oz.au
Wed Dec 24 12:32:35 AEDT 1997


compiler/mercury_trace.[ch]:
	Implement a *very* rudimentary four-port debugger (actually with seven
	ports) using the trace function as a hook. Only predicate names, depths
	and call numbers are available as yet, not the values of any arguments
	or variables. The commands are:

		a: abort the current execution.
		c: continue to end, not printing the trace.
		d: continue to end, printing the trace.
		n: go to the next trace event.
		s: skip the current call, not printing trace.
		j: jump to end of current call, printing trace.

	Merge MR_trace and MR_trace_path into one function, with the path
	argument meaningful only for some ports. This reduces code duplication,
	which previously was not significant, but would be now.
	
compiler/trace.m:
	Emit code that conforms to the new interface in the runtime.

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/trace.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/trace.m,v
retrieving revision 1.2
diff -u -u -r1.2 trace.m
--- trace.m	1997/10/13 08:09:57	1.2
+++ trace.m	1997/12/23 08:47:35
@@ -103,38 +103,29 @@
 	predicate_arity(ModuleInfo, PredId, Arity),
 	string__int_to_string(Arity, ArityStr),
 	Quote = """",
+	Comma = ", ",
 	trace__port_to_string(Port, PortStr),
 	trace__code_model_to_string(CodeModel, CodeModelStr),
 	proc_id_to_int(ProcId, ProcInt),
 	ModeNum is ProcInt mod 10000,
 	string__int_to_string(ModeNum, ModeNumStr),
 	( trace__port_path(Port, Path) ->
-		trace__path_to_string(Path, PathStr),
-		string__append_list([
-			"MR_trace_path(",
-			PortStr, ", ",
-			CodeModelStr, ", ",
-			CallNumStr, ", ",
-			CallDepthStr, ", ",
-			Quote, ModuleName, Quote, ", ",
-			Quote, PredName, Quote, ", ",
-			ArityStr, ", ",
-			ModeNumStr, ", ",
-			Quote, PathStr, Quote, ");\n"],
-			TraceStmt)
+		trace__path_to_string(Path, PathStr)
 	;
-		string__append_list([
-			"MR_trace(",
-			PortStr, ", ",
-			CodeModelStr, ", ",
-			CallNumStr, ", ",
-			CallDepthStr, ", ",
-			Quote, ModuleName, Quote, ", ",
-			Quote, PredName, Quote, ", ",
-			ArityStr, ", ",
-			ModeNumStr, ");\n"],
-			TraceStmt)
+		PathStr = ""
 	),
+	string__append_list([
+		"MR_trace(",
+		PortStr, Comma,
+		CodeModelStr, Comma,
+		CallNumStr, Comma,
+		CallDepthStr, Comma,
+		Quote, ModuleName, Quote, Comma,
+		Quote, PredName, Quote, Comma,
+		ArityStr, Comma,
+		ModeNumStr, Comma,
+		Quote, PathStr, Quote, ");\n"],
+		TraceStmt),
 	TraceCode = node([c_code(TraceStmt) - ""])
 	}.
 
cvs diff: Diffing compiler/notes
cvs diff: Diffing doc
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/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
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/mercury_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace.c,v
retrieving revision 1.3
diff -u -u -r1.3 mercury_trace.c
--- mercury_trace.c	1997/11/23 07:21:40	1.3
+++ mercury_trace.c	1997/12/23 09:39:19
@@ -10,73 +10,144 @@
 ** For the general basis of trace analysis systems, see the paper
 ** "Opium: An extendable trace analyser for Prolog" by Mireille Ducasse,
 ** available from http://www.irisa.fr/lande/ducasse.
+**
+** Main author: Erwan Jahier.
+** Significant adaptations by Zoltan Somogyi.
 */
 
 #include "mercury_imp.h"
 #include "mercury_trace.h"
 #include <stdio.h>
 
+/*
+** 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_seqno 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.
+*/
+
 int	MR_trace_call_seqno = 0;
 int	MR_trace_call_depth = 0;
 
+/*
+** MR_trace_event_number is a simple counter of events; currently we only
+** use it for display.
+*/
+
+static	int			MR_trace_event_number = 0;
+
+/*
+** MR_trace_cmd and MR_trace_seqno are globals variables that we use
+** to manage an interface between the tracer and the user.
+**
+** MR_trace_cmd says what mode the tracer is in, i.e. what the last
+** trace command was.
+**
+** MR_trace_seqno is meaningful only when MR_trace_cmd is MR_SKIP or MR_JUMP.
+** In those cases, it holds the sequence number of the call at whose exit
+** control should be given back to the user.
+*/
+
+typedef enum {
+	MR_CMD_ABORT,	/* a: abort the current execution		  */
+	MR_CMD_CONT,	/* c: continue to end, not printing the trace	  */
+	MR_CMD_DUMP,	/* d: continue to end, printing the trace	  */
+	MR_CMD_NEXT,	/* n: go to the next trace event		  */
+	MR_CMD_SKIP,	/* s: skip the current call, not printing trace	  */
+	MR_CMD_JUMP	/* j: jump to end of current call, printing trace */
+} MR_trace_cmd_type;
+
+static	MR_trace_cmd_type	MR_trace_cmd = MR_CMD_NEXT;
+static	int			MR_trace_seqno = 0;
+
+void MR_trace_display(MR_trace_port port, MR_trace_code_model model, int seqno,
+	int depth, const char *modulename, const char *predname,
+	int arity, int modenum, const char *path);
+void MR_trace_interaction(MR_trace_port port, int seqno);
+void MR_trace_help(void);
+
+#define	port_is_final(port)	(port == MR_PORT_EXIT || port == MR_PORT_FAIL)
+
+/*
+** This function is called from compiled code whenever an event to be traced
+** occurs.
+*/
+
 void
 MR_trace(MR_trace_port port, MR_trace_code_model model, int seqno, int depth,
-	const char *modulename, const char *predname, int arity, int modenum)
+	 const char *modulename, const char *predname, int arity, int modenum,
+	 const char *path)
 {
-	int	i;
+	MR_trace_event_number++;
+	switch (MR_trace_cmd)
+	{
+		case MR_CMD_NEXT:
+			MR_trace_display(port, model, seqno, depth, modulename,
+				predname, arity, modenum, path);
+			MR_trace_interaction(port, seqno);
+			break;
 
-	fprintf(stderr, "%4d %2d ", seqno, depth);
+		case MR_CMD_JUMP:
+			MR_trace_display(port, model, seqno, depth,
+				modulename, predname, arity,
+				modenum, path);
 
-	for (i = 0; i < depth; i++)
-	{
-		putc(' ', stderr);
-	}
+			if (MR_trace_seqno == seqno && port_is_final(port))
+			{
+				MR_trace_interaction(port, seqno);
+			}
 
-	switch (port)
-	{
-		case MR_PORT_CALL:
-			fprintf(stderr, "CALL ");
 			break;
 
-		case MR_PORT_EXIT:
-			fprintf(stderr, "EXIT ");
-			break;
+		case MR_CMD_SKIP:
+			if (MR_trace_seqno == seqno && port_is_final(port))
+			{
+				MR_trace_display(port, model, seqno, depth,
+					modulename, predname, arity,
+					modenum, path);
+
+				MR_trace_interaction(port, seqno);
+			}
 
-		case MR_PORT_FAIL:
-			fprintf(stderr, "FAIL ");
 			break;
 
-		default:
-			fatal_error("MR_trace called with inappropriate port");
-	}
+		case MR_CMD_CONT:
+			break;
 
-	switch (model)
-	{
-		case MR_MODEL_DET:
-			fprintf(stderr, "DET  ");
+		case MR_CMD_DUMP:
+			MR_trace_display(port, model, seqno, depth,
+				modulename, predname, arity,
+				modenum, path);
 			break;
 
-		case MR_MODEL_SEMI:
-			fprintf(stderr, "SEMI ");
+		case MR_CMD_ABORT:
+			fatal_error("aborting the execution on user request");
 			break;
 
-		case MR_MODEL_NON:
-			fprintf(stderr, "NON  ");
+		default:
+			fatal_error("MR_trace called with inappropriate port");
 			break;
 	}
-
-	fprintf(stderr, "%s:%s/%d-%d\n", modulename, predname, arity, modenum);
 }
 
-void
-MR_trace_path(MR_trace_port port, MR_trace_code_model model,
-	int seqno, int depth,
-	const char *modulename, const char *predname, int arity, int modenum,
-	const char *path)
+void MR_trace_display(MR_trace_port port, MR_trace_code_model model, int seqno,
+	int depth, const char *modulename, const char *predname,
+	int arity, int modenum, const char *path)
 {
 	int	i;
 
-	fprintf(stderr, "%4d %2d ", seqno, depth);
+	fprintf(stderr, "%8d: %6d %2d ", MR_trace_event_number, seqno, depth);
 
 	for (i = 0; i < depth; i++)
 	{
@@ -85,6 +156,18 @@
 
 	switch (port)
 	{
+		case MR_PORT_CALL:
+			fprintf(stderr, "CALL ");
+			break;
+
+		case MR_PORT_EXIT:
+			fprintf(stderr, "EXIT ");
+			break;
+
+		case MR_PORT_FAIL:
+			fprintf(stderr, "FAIL ");
+			break;
+
 		case MR_PORT_THEN:
 			fprintf(stderr, "THEN ");
 			break;
@@ -102,7 +185,7 @@
 			break;
 
 		default:
-			fatal_error("MR_trace_path called with inappropriate port");
+			fatal_error("MR_trace_display called with inappropriate port");
 	}
 
 	switch (model)
@@ -122,4 +205,84 @@
 
 	fprintf(stderr, "%s:%s/%d-%d %s\n",
 		modulename, predname, arity, modenum, path);
+}
+
+void
+MR_trace_interaction(MR_trace_port port, int seqno)
+{
+	int	cmd;
+	int	c;
+
+	fprintf(stderr, "trace command [a|c|d|j|n|s] ");
+
+	cmd = getchar();	/* read the trace command */
+
+	/* skip the rest of the line */
+	c = cmd;
+	while (c != EOF && c != '\n')
+		c = getchar();
+
+	switch (cmd)
+	{
+		case 'n':
+		case '\n':
+			MR_trace_cmd = MR_CMD_NEXT;
+			break;
+
+		case 'c':
+			MR_trace_cmd = MR_CMD_CONT;
+			break;
+
+		case 'd':
+			MR_trace_cmd = MR_CMD_DUMP;
+			break;
+
+		case 'j':
+			if (port_is_final(port))
+			{
+				fprintf(stderr, "cannot jump from this port\n");
+				MR_trace_interaction(port, seqno);
+			}
+			else
+			{
+				MR_trace_cmd = MR_CMD_JUMP;
+				MR_trace_seqno = seqno;
+			}
+
+			break;
+
+		case 's':
+			if (port_is_final(port))
+			{
+				fprintf(stderr, "cannot skip from this port\n");
+				MR_trace_interaction(port, seqno);
+			}
+			else
+			{
+				MR_trace_cmd = MR_CMD_SKIP;
+				MR_trace_seqno = seqno;
+			}
+
+			break;
+
+		case 'a':
+			MR_trace_cmd = MR_CMD_ABORT;
+			break;
+
+		default:
+			MR_trace_help();
+			MR_trace_interaction(port, seqno);
+	}
+}
+
+void
+MR_trace_help(void)
+{
+	fprintf(stderr, "valid commands are:\n");
+	fprintf(stderr, " a: abort the current execution.\n");
+	fprintf(stderr, " c: continue to end, not printing the trace.\n");
+	fprintf(stderr, " d: continue to end, printing the trace.\n");
+	fprintf(stderr, " n: go to the next trace event.\n");
+	fprintf(stderr, " s: skip the current call, not printing trace.\n");
+	fprintf(stderr, " j: jump to end of current call, printing trace.\n");
 }
Index: runtime/mercury_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace.h,v
retrieving revision 1.3
diff -u -u -r1.3 mercury_trace.h
--- mercury_trace.h	1997/10/13 08:10:49	1.3
+++ mercury_trace.h	1997/11/27 04:47:23
@@ -40,16 +40,6 @@
 	const char *,		/* module name */
 	const char *,		/* predicate name */
 	int,			/* predicate arity */
-	int);			/* mode number within predicate */
-
-extern	void	MR_trace_path(
-	MR_trace_port,
-	MR_trace_code_model,
-	int,			/* call sequence number */
-	int,			/* call depth */
-	const char *,		/* module name */
-	const char *,		/* predicate name */
-	int,			/* predicate arity */
 	int,			/* mode number within predicate */
 	const char *);		/* path to event goal within procedure */
 
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/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/general
cvs diff: Diffing tests/hard_coded
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



More information about the developers mailing list