[m-dev.] For review: Stacks dump in the external debugger (round 2)

Erwan Jahier Erwan.Jahier at irisa.fr
Wed Feb 17 07:28:26 AEDT 1999


| On 16-Feb-1999, Erwan Jahier <Erwan.Jahier at irisa.fr> wrote:
| > 
| > --- mercury_trace.c	1999/02/12 00:16:42	1.5
| > +++ mercury_trace.c	1999/02/16 16:26:48
| > @@ -432,3 +432,28 @@
| >  	*succeeded = FALSE;
| >  	return 0;
| >  }
| > +
| > +
| > +/*
| > +** The different Mercury determinisms are internaly represented by integers. 
| 
| s/internaly/internally

Ok.


| 
| > +** This array gives the correspondance with the internal representation and 
| > +** the names that are usually used to denote determinisms.
| > +*/
| > +
| > +extern const char * MR_detism_names[] = {
| > +	"failure",	/* 0 */
| > +	"",		/* 1 */
| > +	"semidet",	/* 2 */
| > +	"nondet",	/* 3 */
| > +	"erroneous",	/* 4 */
| > +	"",		/* 5 */
| > +	"det",		/* 6 */
| > +	"multi",	/* 7 */
| > +	"",		/* 8 */
| > +	"",		/* 9 */
| > +	"cc_nondet",	/* 10 */
| > +	"",		/* 11 */
| > +	"",		/* 12 */
| > +	"",		/* 13 */
| > +	"cc_multi"	/* 14 */
| > +};
| > Index: trace/mercury_trace.h
| > ===================================================================
| > RCS file: /home/mercury1/repository/mercury/trace/mercury_trace.h,v
| > retrieving revision 1.5
| > diff -u -r1.5 mercury_trace.h
| > --- mercury_trace.h	1999/02/12 00:16:43	1.5
| > +++ mercury_trace.h	1999/02/16 16:26:48
| > @@ -98,6 +98,8 @@
| >  	bool			MR_trace_must_check;
| >  } MR_Trace_Cmd_Info;
| >  
| > +extern const char * MR_detism_names[];
| 
| The comment above should go on the declaration here in the header file,
| instead of, or as well as, on the definition in mercury_trace.c.

I will recopy it in mercury_trace.c.

| 
| > +			case MR_REQUEST_STACK_REGS:
| > +				if (MR_debug_socket) {
| > +					fprintf(stderr, "\nMercury runtime: "
| > +						"REQUEST_STACK_REGS\n");
| > +				}
| > +				MR_send_message_to_socket_format(
| > +					"stack_regs(\"sp = %p, curfr = %p, "
| > +					"maxfr = %p\").\n",
| > +					MR_saved_sp(saved_regs),
| > +					MR_saved_curfr(saved_regs),
| > +					MR_saved_maxfr(saved_regs));
| > +				break;
| 
| The "%p" format is not guaranteed to give you a syntactically correct
| Prolog term.  On some systems, "%p" will give you a hexadecimal number,
| without any "0x" prefix, e.g. "0000ffff", which is not a syntactically
| correct Prolog term.
| 
| I suggest you use "%lu", and cast to `unsigned long'.

Well I was sending a string here (note the \") which is a valid Prolog term. 
But I'll do as you suggest anyway.

| However, even better would be to put something like
| 
| 	typedef unsigned long MR_intmax_t;
| 	#define MR_PRINTF_INTMAX_T "%lu"
| 
| in somewhere like runtime/mercury_types.h and then use those.
| 
| > -static void
| > -MR_send_message_to_socket_format(const char *format, const char *message)
| > +void    
| > +MR_send_message_to_socket_format(const char *format, ...)
| 
| Any particular reason why this became non-static?

No. Indeed I was confused by your comments.
 
| Sorry if my comments about "in header file", "in C file" confused you,
| but if this function isn't used from any other module, then there
| is no need to make it extern and declare it in the header file,
| instead it should remain static and the declaration should be moved
| from the header file to the start of the C file.
| 
| > +static void
| > +MR_dump_stack_record_print_to_socket(FILE *fp, 
| > +	const MR_Stack_Layout_Entry *entry_layout, int count, int start_level, 
| > +	Word *base_sp, Word *base_curfr)
| > +{
| > +	MR_send_message_to_socket_format( "%d.\n ", start_level);
| 
| Why the space after the \n ?

No reason. I'll remove it.
 
| > +	if (count > 1) {
| > +		MR_send_message_to_socket_format( " %d*.\n ", count);
| 
| "1*." is not valid syntax for a Prolog term.
| 
| > +	} else if ((base_sp == NULL) && (base_curfr == NULL)) {
| > +		MR_send_message_to_socket_format( "%s.\n ", "r1");
| > +	}
| 
| Why does it send "r1." in this case?  A comment might help.
| Also why use ("%s.\n", "r1") instead of just ("r1.\n")?

Oops. This old debugging code. I will remove it.
 
| > +	if (MR_ENTRY_LAYOUT_COMPILER_GENERATED(entry)) {
| > +		MR_send_message_to_socket_format(
| > +			"proc(%s for %s:%s/%ld-%ld).\n",
| 
| That won't be valid syntax for a Prolog term.
| I suggest
| 
| 			"proc('%s for %s:%s'/%ld-%ld).\n"
| 
| which should work OK except when one of the names contains a
| single quote ("'").

Can it happen?
Isn't that a problem?

| 
| > +		if (strcmp(entry->MR_sle_comp.MR_comp_type_module,
| > +				entry->MR_sle_comp.MR_comp_def_module) != 0)
| > +		{
| > +			MR_send_message_to_socket_format( " {%s}.\n",
| > +				entry->MR_sle_comp.MR_comp_def_module);
| > +		}
| 
| Likewise appending {...} won't be valid syntax for a Prolog term.
| 
| > +	} else {
| > +		if (entry->MR_sle_user.MR_user_pred_or_func == MR_PREDICATE) {
| > +			MR_send_message_to_socket("pred");
| > +		} else if (entry->MR_sle_user.MR_user_pred_or_func ==
| > +				MR_FUNCTION)
| > +		{
| > +			MR_send_message_to_socket( "func.\n");
| 
| Why do you print ".\n" for funcs but not for preds?
| That is probably a mistake.

Indeed.

| > +		MR_send_message_to_socket_format(
| > +			"proc(%s:%s/%ld-%ld).\n",
| 
| I suggest
| 
| 			"proc('%s:%s'/%ld-%ld).\n",
| 			      ^     ^

Ok.
 
| > +		if (strcmp(entry->MR_sle_user.MR_user_decl_module,
| > +				entry->MR_sle_user.MR_user_def_module) != 0)
| > +		{
| > +			MR_send_message_to_socket_format( "{%s}.\n",
| > +				entry->MR_sle_user.MR_user_def_module);
| > +		}
| 
| As above, that needs fixing.
| 
| > +	MR_send_message_to_socket_format( "%s.\n", 
| > +		MR_detism_names[entry->MR_sle_detism]);
| > +
| > +	if (extra != NULL) {
| > +		MR_send_message_to_socket_format( " %s.\n", extra);
| > +	}
| 
| Shouldn't that be sent as a string or an atom or something?
| i.e. in quotes?

Yes. 

But in fact, extra is always NULL except if it is called from 
MR_trace_event_print_internal_report() which is can only be called from the 
internal debugger. So I will remove that message.

| 
| > +	MR_send_message_to_socket("end_proc");
| > +}

This one was not necessary. I'll remove it.

| 
| It would be a good idea to document the protocol that is
| used by mercury_trace_external.c to communicate with the external
| debugger, especially since that protocol is becoming quite
| complex now.

Yes, it is a good idea. I'll do that.

| 
| > Index: trace/mercury_trace_internal.h
| > ===================================================================
| > RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.h,v
| > retrieving revision 1.5
| > diff -u -r1.5 mercury_trace_internal.h
| > --- mercury_trace_internal.h	1999/02/10 22:31:22	1.5
| > +++ mercury_trace_internal.h	1999/02/16 16:26:52
| > @@ -48,6 +48,7 @@
| >  			MR_Trace_Port port, int seqno, int depth,
| >  			const char *path, int *max_mr_num);
| >  
| > +
| >  /*
| >  ** Debugger I/O streams.
| >  ** Replacements for stdin/stdout/stderr respectively.
| 
| Please undo that accidental change.

Ok.

| 
| I'd like to see another diff please.

*************************************************************************
* relative diff  							*
*************************************************************************

Index: trace/mercury_trace_external.c
--- 0.11/trace/mercury_trace_external.c Tue, 16 Feb 1999 17:49:57 +0100 jahier (submitdiff/5_mercury_tr 1.10 640)
+++ 0.11(w)/trace/mercury_trace_external.c Tue, 16 Feb 1999 21:14:45 +0100 jahier (submitdiff/5_mercury_tr 1.10 640)
@@ -70,6 +70,21 @@
 static MercuryFile MR_debugger_socket_in;
 static MercuryFile MR_debugger_socket_out;
 
+/*
+** Use a GNU C extension to enforce static type checking
+** for printf-style functions. 
+** (See the "Function attributes" section of "C extensions"
+** chapter of the GNU C manual for detailed documentation.)
+*/
+#ifdef __GNUC__
+  #define MR_LIKE_PRINTF(format_argnum, vars_argnum) \
+    __attribute__ ((format (printf, (format_argnum), (vars_argnum))))
+#else
+  #define MR_LIKE_PRINTF(n, m) /* nothing */
+#endif
+void MR_send_message_to_socket_format(const char *format, ...)
+	MR_LIKE_PRINTF(1, 2);
+
 static void	MR_send_message_to_socket(const char *message);
 static void	MR_read_request_from_socket(
 			Word *debugger_request_ptr, 
@@ -503,10 +518,12 @@
 						"REQUEST_STACK_REGS\n");
 				}
 				MR_send_message_to_socket_format(
-					"stack_regs(\"sp = %p, curfr = %p, "
-					"maxfr = %p\").\n",
+					"stack_regs(%lu, %lu, %lu).\n",
+					(unsigned long)
 					MR_saved_sp(saved_regs),
+					(unsigned long)
 					MR_saved_curfr(saved_regs),
+					(unsigned long)
 					MR_saved_maxfr(saved_regs));
 				break;
 			
@@ -646,7 +663,7 @@
 	return result;
 }
 
-void    
+static void    
 MR_send_message_to_socket_format(const char *format, ...)
 {
 	va_list args;
@@ -807,22 +824,37 @@
 	);
 	return num;
 }
-#endif /* MR_USE_EXTERNAL_DEBUGGER */
 
+/*
+** The protocol between the debugged Mercury program and the external debugger
+** is the following: 
+** 1) The debugger sends "stack";
+** 2) For each procedure in the stack that is not generated by the compiler, the
+**    debuggee sends: 
+**	- level(int) (the level of the procedure in the stack)
+**	- detail(unsigned long, unsigned long, unsigned long) (the call event
+**	  number, call sequence number and depth of the goal of the procedure)
+**	- the atom 'pred' or 'func' depending if the procedure is a function 
+**	  or not
+**	- proc('string:string'/long-long) (the name of the procedure)
+**	- det(string) (the determinism of the procedure)
+**	- def_module(string) (the name of the defining module if different from
+**	  the current one)
+**
+**    For each compiler generated procedures, the debuggee sends:
+**	- level(int) (as above)
+**	- detail(unsigned long, unsigned long, unsigned long) (as above)
+**	- proc('string for string:string'/long-long) (the name of the 
+**	  compiler-generated procedure)
+**	- def_module(string) (as above)
+*/
 
 static void
 MR_dump_stack_record_print_to_socket(FILE *fp, 
 	const MR_Stack_Layout_Entry *entry_layout, int count, int start_level, 
 	Word *base_sp, Word *base_curfr)
 {
-	MR_send_message_to_socket_format( "%d.\n ", start_level);
-
-	if (count > 1) {
-		MR_send_message_to_socket_format( " %d*.\n ", count);
-	} else if ((base_sp == NULL) && (base_curfr == NULL)) {
-		MR_send_message_to_socket_format( "%s.\n ", "r1");
-	}
-
+	MR_send_message_to_socket_format("level(%d).\n", start_level);
 	MR_print_proc_id_to_socket(entry_layout, NULL, base_sp, base_curfr);
 }
 
@@ -886,7 +918,7 @@
 
 	if (MR_ENTRY_LAYOUT_COMPILER_GENERATED(entry)) {
 		MR_send_message_to_socket_format(
-			"proc(%s for %s:%s/%ld-%ld).\n",
+			"proc('%s for %s:%s'/%ld-%ld).\n",
 			entry->MR_sle_comp.MR_comp_pred_name,
 			entry->MR_sle_comp.MR_comp_type_module,
 			entry->MR_sle_comp.MR_comp_type_name,
@@ -896,7 +928,8 @@
 		if (strcmp(entry->MR_sle_comp.MR_comp_type_module,
 				entry->MR_sle_comp.MR_comp_def_module) != 0)
 		{
-			MR_send_message_to_socket_format( " {%s}.\n",
+			MR_send_message_to_socket_format(
+				"def_module(\"%s\").\n",
 				entry->MR_sle_comp.MR_comp_def_module);
 		}
 	} else {
@@ -905,13 +938,13 @@
 		} else if (entry->MR_sle_user.MR_user_pred_or_func ==
 				MR_FUNCTION)
 		{
-			MR_send_message_to_socket( "func.\n");
+			MR_send_message_to_socket("func");
 		} else {
 			fatal_error("procedure is not pred or func");
 		}
 		
 		MR_send_message_to_socket_format(
-			"proc(%s:%s/%ld-%ld).\n",
+			"proc('%s:%s'/%ld-%ld).\n",
 			entry->MR_sle_user.MR_user_decl_module,
 			entry->MR_sle_user.MR_user_name,
 			(long) entry->MR_sle_user.MR_user_arity,
@@ -920,16 +953,15 @@
 		if (strcmp(entry->MR_sle_user.MR_user_decl_module,
 				entry->MR_sle_user.MR_user_def_module) != 0)
 		{
-			MR_send_message_to_socket_format( "{%s}.\n",
+			MR_send_message_to_socket_format(
+				"def_module(\"%s\").\n",
 				entry->MR_sle_user.MR_user_def_module);
 		}
 	}
 
-	MR_send_message_to_socket_format( "%s.\n", 
+	MR_send_message_to_socket_format("det(\"%s\").\n", 
 		MR_detism_names[entry->MR_sle_detism]);
 
-	if (extra != NULL) {
-		MR_send_message_to_socket_format( " %s.\n", extra);
-	}
-	MR_send_message_to_socket("end_proc");
 }
+
+#endif /* MR_USE_EXTERNAL_DEBUGGER */
Index: trace/mercury_trace_external.h
--- 0.11/trace/mercury_trace_external.h Tue, 16 Feb 1999 17:49:57 +0100 jahier (submitdiff/7_mercury_tr 1.3 640)
+++ 0.11(w)/trace/mercury_trace_external.h Tue, 16 Feb 1999 18:46:35 +0100 jahier (submitdiff/7_mercury_tr 1.3 640)
@@ -17,23 +17,6 @@
 			Unsigned depth, const char *path, int *max_mr_num);
 
 
-/*
-** Use a GNU C extension to enforce static type checking
-** for printf-style functions. 
-** (See the "Function attributes" section of "C extensions"
-** chapter of the GNU C manual for detailed documentation.)
-*/
-#ifdef __GNUC__
-  #define MR_LIKE_PRINTF(format_argnum, vars_argnum) \
-    __attribute__ ((format (printf, (format_argnum), (vars_argnum))))
-#else
-  #define MR_LIKE_PRINTF(n, m) /* nothing */
-#endif
-
-void MR_send_message_to_socket_format(const char *format, ...)
-	MR_LIKE_PRINTF(1, 2);
-
-
 #endif	/* MR_USE_EXTERNAL_DEBUGGER */
 
 #endif	/* MERCURY_TRACE_EXTERNAL_H */
Index: trace/mercury_trace_internal.c
--- 0.11/trace/mercury_trace_internal.c Tue, 16 Feb 1999 17:49:57 +0100 jahier (submitdiff/10_mercury_tr 1.5 640)
+++ 0.11(w)/trace/mercury_trace_internal.c Tue, 16 Feb 1999 19:15:42 +0100 jahier (submitdiff/10_mercury_tr 1.5 640)
@@ -53,7 +53,6 @@
 ** XXX We should consider whether all the static variables in this module
 ** should be thread local.
 */
-
 /*
 ** Debugger I/O streams.
 ** Replacements for stdin/stdout/stderr respectively.
Index: trace/mercury_trace.h
--- 0.11/trace/mercury_trace.h Tue, 16 Feb 1999 17:49:57 +0100 jahier (submitdiff/11_mercury_tr 1.5 640)
+++ 0.11(w)/trace/mercury_trace.h Tue, 16 Feb 1999 18:34:34 +0100 jahier (submitdiff/11_mercury_tr 1.5 640)
@@ -98,6 +98,12 @@
 	bool			MR_trace_must_check;
 } MR_Trace_Cmd_Info;
 
+/*
+** The different Mercury determinisms are internally represented by integers. 
+** This array gives the correspondance with the internal representation and 
+** the names that are usually used to denote determinisms.
+*/
+
 extern const char * MR_detism_names[];
 
 #define	MR_port_is_final(port)		((port) == MR_PORT_EXIT || \
Index: trace/mercury_trace.c
--- 0.11/trace/mercury_trace.c Tue, 16 Feb 1999 17:49:57 +0100 jahier (submitdiff/12_mercury_tr 1.6 640)
+++ 0.11(w)/trace/mercury_trace.c Tue, 16 Feb 1999 18:33:32 +0100 jahier (submitdiff/12_mercury_tr 1.6 640)
@@ -435,7 +435,7 @@
 
 
 /*
-** The different Mercury determinisms are internaly represented by integers. 
+** The different Mercury determinisms are internally represented by integers. 
 ** This array gives the correspondance with the internal representation and 
 ** the names that are usually used to denote determinisms.
 */

*************************************************************************
* diff  								*
*************************************************************************
Index: browser/debugger_interface.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/debugger_interface.m,v
retrieving revision 1.5
diff -u -r1.5 debugger_interface.m
--- debugger_interface.m	1999/02/10 22:31:27	1.5
+++ debugger_interface.m	1999/02/16 20:21:51
@@ -118,6 +118,14 @@
 			% restarts execution at the call port of the call 
 			% corresponding to the current event
 	;	retry
+			% print the ancestors stack
+	;	stack
+			% prints the contents of the fixed slots of the 
+			% frames on the nondet stack
+	;	nondet_stack
+			% print the contents of the virtual machine registers 
+			% that point to the det and nondet stacks
+	;	stack_regs
 			% something went wrong when trying to get the
 			% next request
 	;	error(string)
@@ -383,6 +391,9 @@
 classify_request(current_live_var_names, 7).
 classify_request(current_nth_var(_), 8).
 classify_request(retry, 9).
+classify_request(stack, 10).
+classify_request(nondet_stack, 11).
+classify_request(stack_regs, 12).
 
 
 %-----------------------------------------------------------------------------%
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.24
diff -u -r1.24 mercury_stack_trace.c
--- mercury_stack_trace.c	1998/12/17 13:36:59	1.24
+++ mercury_stack_trace.c	1999/02/16 20:21:56
@@ -15,32 +15,17 @@
 #include <stdio.h>
 
 
-static const char * detism_names[] = {
-	"failure",	/* 0 */
-	"",		/* 1 */
-	"semidet",	/* 2 */
-	"nondet",	/* 3 */
-	"erroneous",	/* 4 */
-	"",		/* 5 */
-	"det",		/* 6 */
-	"multi",	/* 7 */
-	"",		/* 8 */
-	"",		/* 9 */
-	"cc_nondet",	/* 10 */
-	"",		/* 11 */
-	"",		/* 12 */
-	"",		/* 13 */
-	"cc_multi"	/* 14 */
-};
-
 static	void	MR_dump_stack_record_init(void);
 static	void	MR_dump_stack_record_frame(FILE *fp,
 			const MR_Stack_Layout_Entry *,
-			Word *base_sp, Word *base_curfr);
-static	void	MR_dump_stack_record_flush(FILE *fp);
-static	void	MR_dump_stack_record_print(FILE *fp,
-			const MR_Stack_Layout_Entry *, int, int,
-			Word *base_sp, Word *base_curfr);
+			Word *base_sp, Word *base_curfr, 
+			void *print_stack_record(
+				FILE *, const MR_Stack_Layout_Entry *, 
+				int, int, Word *, Word *));
+static	void	MR_dump_stack_record_flush(FILE *fp, 
+			void *print_stack_record(
+				FILE *, const MR_Stack_Layout_Entry *, 
+				int, int, Word *, Word *));
 
 void
 MR_dump_stack(Code *success_pointer, Word *det_stack_pointer,
@@ -75,7 +60,9 @@
 
 const char *
 MR_dump_stack_from_layout(FILE *fp, const MR_Stack_Layout_Entry *entry_layout,
-	Word *det_stack_pointer, Word *current_frame, bool include_trace_data)
+	Word *det_stack_pointer, Word *current_frame, bool include_trace_data,
+	void *print_stack_record(FILE *, const MR_Stack_Layout_Entry *, 
+	int, int, Word *, Word *))
 {
 	MR_Stack_Walk_Step_Result	result;
 	const MR_Stack_Layout_Label	*return_label_layout;
@@ -98,26 +85,30 @@
 		result = MR_stack_walk_step(entry_layout, &return_label_layout,
 				&stack_trace_sp, &stack_trace_curfr, &problem);
 		if (result == STEP_ERROR_BEFORE) {
-			MR_dump_stack_record_flush(fp);
+			MR_dump_stack_record_flush(fp, 
+				print_stack_record);
 			return problem;
 		} else if (result == STEP_ERROR_AFTER) {
 			if (include_trace_data) {
 				MR_dump_stack_record_frame(fp, entry_layout,
-					old_trace_sp, old_trace_curfr);
+					old_trace_sp, old_trace_curfr, 
+					print_stack_record);
 			} else {
 				MR_dump_stack_record_frame(fp, entry_layout,
-					NULL, NULL);
+					NULL, NULL, print_stack_record);
 			}
 
-			MR_dump_stack_record_flush(fp);
+			MR_dump_stack_record_flush(fp, 
+				print_stack_record);
 			return problem;
 		} else {
 			if (include_trace_data) {
 				MR_dump_stack_record_frame(fp, entry_layout,
-					old_trace_sp, old_trace_curfr);
+					old_trace_sp, old_trace_curfr, 
+					print_stack_record);
 			} else {
 				MR_dump_stack_record_frame(fp, entry_layout,
-					NULL, NULL);
+					NULL, NULL, print_stack_record);
 			}
 		}
 
@@ -128,7 +119,7 @@
 		entry_layout = return_label_layout->MR_sll_entry;
 	} while (TRUE); 
 
-	MR_dump_stack_record_flush(fp);
+	MR_dump_stack_record_flush(fp, print_stack_record);
 	return NULL;
 }
 
@@ -293,7 +284,8 @@
 
 static void
 MR_dump_stack_record_frame(FILE *fp, const MR_Stack_Layout_Entry *entry_layout,
-	Word *base_sp, Word *base_curfr)
+	Word *base_sp, Word *base_curfr, void *print_stack_record(
+		FILE *, const MR_Stack_Layout_Entry *, int, int, Word *, Word *))
 {
 	bool	must_flush;
 
@@ -319,7 +311,7 @@
 		((base_sp != NULL) || (base_curfr != NULL));
 
 	if (must_flush) {
-		MR_dump_stack_record_flush(fp);
+		MR_dump_stack_record_flush(fp, print_stack_record);
 
 		prev_entry_layout = entry_layout;
 		prev_entry_layout_count = 1;
@@ -334,145 +326,13 @@
 }
 
 static void
-MR_dump_stack_record_flush(FILE *fp)
+MR_dump_stack_record_flush(FILE *fp, void *print_stack_record(
+	FILE *, const MR_Stack_Layout_Entry *, int, int, Word *, Word *))
 {
 	if (prev_entry_layout != NULL) {
-		MR_dump_stack_record_print(fp, prev_entry_layout,
+		print_stack_record(fp, prev_entry_layout,
 			prev_entry_layout_count, prev_entry_start_level,
 			prev_entry_base_sp, prev_entry_base_curfr);
 	}
 }
 
-static void
-MR_dump_stack_record_print(FILE *fp, const MR_Stack_Layout_Entry *entry_layout,
-	int count, int start_level, Word *base_sp, Word *base_curfr)
-{
-	fprintf(fp, "%4d ", start_level);
-
-	if (count > 1) {
-		fprintf(fp, " %3d* ", count);
-	} else if ((base_sp == NULL) && (base_curfr == NULL)) {
-		fprintf(fp, "%5s ", "");
-	} else {
-		/*
-		** If we are printing trace data, we need all the horizonal
-		** room we can get, and there will not be any repeated lines,
-		** so we don't reserve space for the repeat counts.
-		*/
-	}
-
-	MR_print_proc_id(fp, entry_layout, NULL, base_sp, base_curfr);
-}
-
-void
-MR_print_proc_id_for_debugger(FILE *fp,
-	const MR_Stack_Layout_Entry *entry_layout)
-{
-	MR_print_proc_id(fp, entry_layout, NULL, NULL, NULL);
-}
-
-void
-MR_print_proc_id(FILE *fp, const MR_Stack_Layout_Entry *entry,
-	const char *extra, Word *base_sp, Word *base_curfr)
-{
-	if (! MR_ENTRY_LAYOUT_HAS_PROC_ID(entry)) {
-		fatal_error("cannot print procedure id without layout");
-	}
-
-	if (base_sp != NULL && base_curfr != NULL) {
-		bool print_details = FALSE;
-		if (MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry)) {
-			Word maybe_from_full = entry->MR_sle_maybe_from_full;
-			if (maybe_from_full > 0) {
-				/*
-				** for procedures compiled with shallow
-				** tracing, the details will be valid only
-				** if the value of MR_from_full saved in
-				** the appropriate stack slot was TRUE.
-			    	*/
-				if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
-					print_details = MR_based_stackvar(
-						base_sp, maybe_from_full);
-				} else {
-					print_details = MR_based_framevar(
-						base_curfr, maybe_from_full);
-				}
-			} else {
-				/*
-				** for procedures compiled with full tracing,
-				** always print out the details
-				*/
-				print_details = TRUE;
-			}
-		}
-		if (print_details) {
-			if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
-				fprintf(fp, "%7lu %7lu %4lu ",
-					(unsigned long)
-					MR_event_num_stackvar(base_sp) + 1,
-					(unsigned long)
-					MR_call_num_stackvar(base_sp),
-					(unsigned long)
-					MR_call_depth_stackvar(base_sp));
-			} else {
-				fprintf(fp, "%7lu %7lu %4lu ",
-					(unsigned long)
-					MR_event_num_framevar(base_curfr) + 1,
-					(unsigned long)
-					MR_call_num_framevar(base_curfr),
-					(unsigned long)
-					MR_call_depth_framevar(base_curfr));
-			}
-		} else {
-			/* ensure that the remaining columns line up */
-			fprintf(fp, "%21s", "");
-		}
-	}
-
-	if (MR_ENTRY_LAYOUT_COMPILER_GENERATED(entry)) {
-		fprintf(fp, "%s for %s:%s/%ld-%ld",
-			entry->MR_sle_comp.MR_comp_pred_name,
-			entry->MR_sle_comp.MR_comp_type_module,
-			entry->MR_sle_comp.MR_comp_type_name,
-			(long) entry->MR_sle_comp.MR_comp_arity,
-			(long) entry->MR_sle_comp.MR_comp_mode);
-
-		if (strcmp(entry->MR_sle_comp.MR_comp_type_module,
-				entry->MR_sle_comp.MR_comp_def_module) != 0)
-		{
-			fprintf(fp, " {%s}",
-				entry->MR_sle_comp.MR_comp_def_module);
-		}
-	} else {
-		if (entry->MR_sle_user.MR_user_pred_or_func == MR_PREDICATE) {
-			fprintf(fp, "pred");
-		} else if (entry->MR_sle_user.MR_user_pred_or_func ==
-				MR_FUNCTION)
-		{
-			fprintf(fp, "func");
-		} else {
-			fatal_error("procedure is not pred or func");
-		}
-
-		fprintf(fp, " %s:%s/%ld-%ld",
-			entry->MR_sle_user.MR_user_decl_module,
-			entry->MR_sle_user.MR_user_name,
-			(long) entry->MR_sle_user.MR_user_arity,
-			(long) entry->MR_sle_user.MR_user_mode);
-
-		if (strcmp(entry->MR_sle_user.MR_user_decl_module,
-				entry->MR_sle_user.MR_user_def_module) != 0)
-		{
-			fprintf(fp, " {%s}",
-				entry->MR_sle_user.MR_user_def_module);
-		}
-	}
-
-	fprintf(fp, " (%s)", detism_names[entry->MR_sle_detism]);
-
-	if (extra != NULL) {
-		fprintf(fp, " %s\n", extra);
-	} else {
-		fprintf(fp, "\n");
-	}
-}
Index: runtime/mercury_stack_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.h,v
retrieving revision 1.14
diff -u -r1.14 mercury_stack_trace.h
--- mercury_stack_trace.h	1998/12/17 13:37:00	1.14
+++ mercury_stack_trace.h	1999/02/16 20:21:56
@@ -56,7 +56,10 @@
 extern	const char	*MR_dump_stack_from_layout(FILE *fp,
 				const MR_Stack_Layout_Entry *entry_layout,
 				Word *det_stack_pointer, Word *current_frame,
-				bool include_trace_data);
+				bool include_trace_data,
+				void *print_stack_record(FILE *, 
+					const MR_Stack_Layout_Entry *, 
+					int, int, Word *, Word *));
 
 /*
 ** MR_dump_nondet_stack_from_layout:
@@ -134,20 +137,5 @@
 
 Word	*MR_nondet_stack_trace_bottom;
 
-/*
-** MR_print_proc_id prints an identification of the given procedure,
-** consisting of "pred" or "func", module name, pred or func name, arity,
-** mode number and determinism, followed by an optional extra string,
-** and a newline.
-**
-** If the procedure has trace layout information and the relevant one of
-** base_sp and base_curfr is not NULL, it also prints the call event number,
-** call sequence number and call depth of the call.
-*/
-
-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);
 
 #endif /* MERCURY_STACK_TRACE_H */
Index: trace/mercury_trace.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace.c,v
retrieving revision 1.5
diff -u -r1.5 mercury_trace.c
--- mercury_trace.c	1999/02/12 00:16:42	1.5
+++ mercury_trace.c	1999/02/16 20:21:57
@@ -432,3 +432,28 @@
 	*succeeded = FALSE;
 	return 0;
 }
+
+
+/*
+** The different Mercury determinisms are internally represented by integers. 
+** This array gives the correspondance with the internal representation and 
+** the names that are usually used to denote determinisms.
+*/
+
+extern const char * MR_detism_names[] = {
+	"failure",	/* 0 */
+	"",		/* 1 */
+	"semidet",	/* 2 */
+	"nondet",	/* 3 */
+	"erroneous",	/* 4 */
+	"",		/* 5 */
+	"det",		/* 6 */
+	"multi",	/* 7 */
+	"",		/* 8 */
+	"",		/* 9 */
+	"cc_nondet",	/* 10 */
+	"",		/* 11 */
+	"",		/* 12 */
+	"",		/* 13 */
+	"cc_multi"	/* 14 */
+};
Index: trace/mercury_trace.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace.h,v
retrieving revision 1.5
diff -u -r1.5 mercury_trace.h
--- mercury_trace.h	1999/02/12 00:16:43	1.5
+++ mercury_trace.h	1999/02/16 20:21:57
@@ -98,6 +98,14 @@
 	bool			MR_trace_must_check;
 } MR_Trace_Cmd_Info;
 
+/*
+** The different Mercury determinisms are internally represented by integers. 
+** This array gives the correspondance with the internal representation and 
+** the names that are usually used to denote determinisms.
+*/
+
+extern const char * MR_detism_names[];
+
 #define	MR_port_is_final(port)		((port) == MR_PORT_EXIT || \
 					 (port) == MR_PORT_FAIL || \
 					 (port) == MR_PORT_EXCEPTION)
Index: trace/mercury_trace_external.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_external.c,v
retrieving revision 1.6
diff -u -r1.6 mercury_trace_external.c
--- mercury_trace_external.c	1999/02/10 22:31:23	1.6
+++ mercury_trace_external.c	1999/02/16 20:21:59
@@ -30,6 +30,7 @@
 #include "mercury_layout_util.h"
 #include <stdio.h>
 #include <errno.h>
+#include <stdarg.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <sys/socket.h>
@@ -53,21 +54,38 @@
 	MR_REQUEST_ERROR         = 6, /* something went wrong                 */
 	MR_REQUEST_CURRENT_LIVE_VAR_NAMES  
 				 = 7, /* report data for 
-					 current_live_var_names query */
+					 current_live_var_names query	      */
 	MR_REQUEST_CURRENT_NTH_VAR 
 				 = 8, /* report data for 
-					 current_nth_var query */
-	MR_REQUEST_RETRY	 = 9  /* restart the execution to the call 
+					 current_nth_var query		      */
+	MR_REQUEST_RETRY	 = 9, /* restart the execution to the call 
 					 port of the current event	      */
+	MR_REQUEST_STACK         = 10,/* print the ancestors list             */
+	MR_REQUEST_NONDET_STACK  = 11,/* print the nondet stack		      */
+	MR_REQUEST_STACK_REGS    = 12 /* prints the contents of the virtual
+							   machine registers. */
 
 } MR_debugger_request_type;
 
 static MercuryFile MR_debugger_socket_in;
 static MercuryFile MR_debugger_socket_out;
 
+/*
+** Use a GNU C extension to enforce static type checking
+** for printf-style functions. 
+** (See the "Function attributes" section of "C extensions"
+** chapter of the GNU C manual for detailed documentation.)
+*/
+#ifdef __GNUC__
+  #define MR_LIKE_PRINTF(format_argnum, vars_argnum) \
+    __attribute__ ((format (printf, (format_argnum), (vars_argnum))))
+#else
+  #define MR_LIKE_PRINTF(n, m) /* nothing */
+#endif
+void MR_send_message_to_socket_format(const char *format, ...)
+	MR_LIKE_PRINTF(1, 2);
+
 static void	MR_send_message_to_socket(const char *message);
-static void	MR_send_message_to_socket_format(const char *format, 
-			const char *message);
 static void	MR_read_request_from_socket(
 			Word *debugger_request_ptr, 
 			Integer *debugger_request_type_ptr);
@@ -90,6 +108,11 @@
 static Word	MR_trace_make_nth_var(const MR_Stack_Layout_Label *layout, 
 			Word *saved_regs, Word debugger_request);
 static int	MR_get_var_number(Word debugger_request);
+static void	MR_print_proc_id_to_socket(const MR_Stack_Layout_Entry *entry,
+			const char *extra, Word *base_sp, Word *base_curfr);
+static void	MR_dump_stack_record_print_to_socket(FILE *fp, 
+			const MR_Stack_Layout_Entry *entry_layout, int count, 
+			int start_level, Word *base_sp, Word *base_curfr);
 
 #if 0
 This pseudocode should go in the debugger process:
@@ -344,6 +367,7 @@
 	Code		*jumpaddr = NULL;
 	MR_Event_Details	event_details;
 	char		*message;
+        bool		include_trace_data = TRUE;
 
 	event_details.MR_call_seqno = MR_trace_call_seqno;
 	event_details.MR_call_depth = MR_trace_call_depth;
@@ -444,7 +468,65 @@
 						"error(\"%s\").\n", message);
 				}
 				break;
-
+				
+			case MR_REQUEST_STACK:
+				if (MR_debug_socket) {
+					fprintf(stderr, "\nMercury runtime: "
+						"REQUEST_STACK\n");
+				}
+				do_init_modules();
+				message = MR_dump_stack_from_layout(
+					stdout,
+					layout->MR_sll_entry,
+					MR_saved_sp(saved_regs),
+					MR_saved_curfr(saved_regs),
+					include_trace_data,
+					&MR_dump_stack_record_print_to_socket);
+				MR_send_message_to_socket("end_stack");
+				if (message != NULL) {
+					MR_send_message_to_socket_format(
+						"error(\"%s\").\n", message);
+				} else {
+					MR_send_message_to_socket("ok");
+				}
+				break; 
+			
+			case MR_REQUEST_NONDET_STACK: 
+				if (MR_debug_socket) {
+					fprintf(stderr, "\nMercury runtime: "
+						"REQUEST_NONDET_STACK\n");
+				}
+				do_init_modules();
+				/* 
+			        ** XXX As in stack dump, we could send the
+				** output of this function on the socket. But
+				** the outputs are done via fprintf() and
+				** printlabel(), so we would need to define new
+				** fprintf() and printlabel() and pass them
+				** down as parameters of
+				** MR_dump_nondet_stack_from_layout() (as we do
+				** with MR_dump_stack_record_print()).
+				*/						
+				MR_dump_nondet_stack_from_layout(stdout,
+					MR_saved_maxfr(saved_regs));
+				MR_send_message_to_socket("ok");
+				break;
+			
+			case MR_REQUEST_STACK_REGS:
+				if (MR_debug_socket) {
+					fprintf(stderr, "\nMercury runtime: "
+						"REQUEST_STACK_REGS\n");
+				}
+				MR_send_message_to_socket_format(
+					"stack_regs(%lu, %lu, %lu).\n",
+					(unsigned long)
+					MR_saved_sp(saved_regs),
+					(unsigned long)
+					MR_saved_curfr(saved_regs),
+					(unsigned long)
+					MR_saved_maxfr(saved_regs));
+				break;
+			
 			case MR_REQUEST_NO_TRACE:
 				cmd->MR_trace_cmd = MR_CMD_TO_END;
 				return jumpaddr;
@@ -581,15 +663,20 @@
 	return result;
 }
 
-static void
-MR_send_message_to_socket_format(const char *format, const char *message)
+static void    
+MR_send_message_to_socket_format(const char *format, ...)
 {
-	fprintf(MR_debugger_socket_out.file, format, message);
-	fflush(MR_debugger_socket_out.file);
-	MR_debugger_socket_out.line_number++;
+	va_list args;
+
+       	va_start(args, format);
+       	vfprintf(MR_debugger_socket_out.file, format, args);
+       	va_end(args);
+       	fflush(MR_debugger_socket_out.file);
+       	MR_debugger_socket_out.line_number++;
 }
 
 
+
 static void
 MR_send_message_to_socket(const char *message)
 {
@@ -737,4 +824,144 @@
 	);
 	return num;
 }
+
+/*
+** The protocol between the debugged Mercury program and the external debugger
+** is the following: 
+** 1) The debugger sends "stack";
+** 2) For each procedure in the stack that is not generated by the compiler, the
+**    debuggee sends: 
+**	- level(int) (the level of the procedure in the stack)
+**	- detail(unsigned long, unsigned long, unsigned long) (the call event
+**	  number, call sequence number and depth of the goal of the procedure)
+**	- the atom 'pred' or 'func' depending if the procedure is a function 
+**	  or not
+**	- proc('string:string'/long-long) (the name of the procedure)
+**	- det(string) (the determinism of the procedure)
+**	- def_module(string) (the name of the defining module if different from
+**	  the current one)
+**
+**    For each compiler generated procedures, the debuggee sends:
+**	- level(int) (as above)
+**	- detail(unsigned long, unsigned long, unsigned long) (as above)
+**	- proc('string for string:string'/long-long) (the name of the 
+**	  compiler-generated procedure)
+**	- def_module(string) (as above)
+*/
+
+static void
+MR_dump_stack_record_print_to_socket(FILE *fp, 
+	const MR_Stack_Layout_Entry *entry_layout, int count, int start_level, 
+	Word *base_sp, Word *base_curfr)
+{
+	MR_send_message_to_socket_format("level(%d).\n", start_level);
+	MR_print_proc_id_to_socket(entry_layout, NULL, base_sp, base_curfr);
+}
+
+
+static void
+MR_print_proc_id_to_socket(const MR_Stack_Layout_Entry *entry,
+	const char *extra, Word *base_sp, Word *base_curfr)
+{
+	if (! MR_ENTRY_LAYOUT_HAS_PROC_ID(entry)) {
+		fatal_error("cannot retrieve procedure id without layout");
+	}
+
+	if (base_sp != NULL && base_curfr != NULL) {
+		bool print_details = FALSE;
+		if (MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry)) {
+			Word maybe_from_full = entry->MR_sle_maybe_from_full;
+			if (maybe_from_full > 0) {
+				/*
+				** for procedures compiled with shallow
+				** tracing, the details will be valid only
+				** if the value of MR_from_full saved in
+				** the appropriate stack slot was TRUE.
+			    	*/
+				if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
+					print_details = MR_based_stackvar(
+						base_sp, maybe_from_full);
+				} else {
+					print_details = MR_based_framevar(
+						base_curfr, maybe_from_full);
+				}
+			} else {
+				/*
+				** for procedures compiled with full tracing,
+				** always print out the details
+				*/
+				print_details = TRUE;
+			}
+		}
+		if (print_details) {
+			if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
+				MR_send_message_to_socket_format( 
+					"detail(%lu, %lu, %lu).\n",
+					(unsigned long)
+					MR_event_num_stackvar(base_sp) + 1,
+					(unsigned long)
+					MR_call_num_stackvar(base_sp),
+					(unsigned long)
+					MR_call_depth_stackvar(base_sp));
+			} else {
+				MR_send_message_to_socket_format( 
+					"detail(%lu, %lu, %lu).\n",
+					(unsigned long)
+					MR_event_num_framevar(base_curfr) + 1,
+					(unsigned long)
+					MR_call_num_framevar(base_curfr),
+					(unsigned long)
+					MR_call_depth_framevar(base_curfr));
+			}
+		} 
+	}
+
+	if (MR_ENTRY_LAYOUT_COMPILER_GENERATED(entry)) {
+		MR_send_message_to_socket_format(
+			"proc('%s for %s:%s'/%ld-%ld).\n",
+			entry->MR_sle_comp.MR_comp_pred_name,
+			entry->MR_sle_comp.MR_comp_type_module,
+			entry->MR_sle_comp.MR_comp_type_name,
+			(long) entry->MR_sle_comp.MR_comp_arity,
+			(long) entry->MR_sle_comp.MR_comp_mode);
+
+		if (strcmp(entry->MR_sle_comp.MR_comp_type_module,
+				entry->MR_sle_comp.MR_comp_def_module) != 0)
+		{
+			MR_send_message_to_socket_format(
+				"def_module(\"%s\").\n",
+				entry->MR_sle_comp.MR_comp_def_module);
+		}
+	} else {
+		if (entry->MR_sle_user.MR_user_pred_or_func == MR_PREDICATE) {
+			MR_send_message_to_socket("pred");
+		} else if (entry->MR_sle_user.MR_user_pred_or_func ==
+				MR_FUNCTION)
+		{
+			MR_send_message_to_socket("func");
+		} else {
+			fatal_error("procedure is not pred or func");
+		}
+		
+		MR_send_message_to_socket_format(
+			"proc('%s:%s'/%ld-%ld).\n",
+			entry->MR_sle_user.MR_user_decl_module,
+			entry->MR_sle_user.MR_user_name,
+			(long) entry->MR_sle_user.MR_user_arity,
+			(long) entry->MR_sle_user.MR_user_mode);
+
+		if (strcmp(entry->MR_sle_user.MR_user_decl_module,
+				entry->MR_sle_user.MR_user_def_module) != 0)
+		{
+			MR_send_message_to_socket_format(
+				"def_module(\"%s\").\n",
+				entry->MR_sle_user.MR_user_def_module);
+		}
+	}
+
+	MR_send_message_to_socket_format("det(\"%s\").\n", 
+		MR_detism_names[entry->MR_sle_detism]);
+
+}
+
 #endif /* MR_USE_EXTERNAL_DEBUGGER */
Index: trace/mercury_trace_external.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_external.h,v
retrieving revision 1.3
diff -u -r1.3 mercury_trace_external.h
--- mercury_trace_external.h	1999/02/10 22:31:24	1.3
+++ mercury_trace_external.h	1999/02/16 20:21:59
@@ -16,6 +16,7 @@
 			Word *saved_regs, MR_Trace_Port port, Unsigned seqno,
 			Unsigned depth, const char *path, int *max_mr_num);
 
+
 #endif	/* MR_USE_EXTERNAL_DEBUGGER */
 
 #endif	/* MERCURY_TRACE_EXTERNAL_H */
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.26
diff -u -r1.26 mercury_trace_internal.c
--- mercury_trace_internal.c	1999/02/12 02:50:01	1.26
+++ mercury_trace_internal.c	1999/02/16 20:22:02
@@ -53,7 +53,6 @@
 ** XXX We should consider whether all the static variables in this module
 ** should be thread local.
 */
-
 /*
 ** Debugger I/O streams.
 ** Replacements for stdin/stdout/stderr respectively.
@@ -215,6 +214,10 @@
 
 static	bool	MR_trace_valid_command(const char *word);
 
+static	void	MR_dump_stack_record_print(FILE *fp,
+			const MR_Stack_Layout_Entry *, int, int,
+			Word *base_sp, Word *base_curfr);
+
 Code *
 MR_trace_event_internal(MR_Trace_Cmd_Info *cmd, bool interactive,
 	const MR_Stack_Layout_Label *layout, Word *saved_regs,
@@ -789,7 +792,8 @@
 					layout->MR_sll_entry,
 					MR_saved_sp(saved_regs),
 					MR_saved_curfr(saved_regs),
-					include_trace_data);
+					include_trace_data,
+					&MR_dump_stack_record_print);
 			if (msg != NULL) {
 				fflush(MR_mdb_out);
 				fprintf(MR_mdb_err, "%s.\n", msg);
@@ -2460,3 +2464,25 @@
 
 	return FALSE;
 }
+
+static void
+MR_dump_stack_record_print(FILE *fp, const MR_Stack_Layout_Entry *entry_layout,
+	int count, int start_level, Word *base_sp, Word *base_curfr)
+{
+	fprintf(fp, "%4d ", start_level);
+
+	if (count > 1) {
+		fprintf(fp, " %3d* ", count);
+	} else if ((base_sp == NULL) && (base_curfr == NULL)) {
+		fprintf(fp, "%5s ", "");
+	} else {
+		/*
+		** If we are printing trace data, we need all the horizonal
+		** room we can get, and there will not be any repeated lines,
+		** so we don't reserve space for the repeat counts.
+		*/
+	}
+
+	MR_print_proc_id(fp, entry_layout, NULL, base_sp, base_curfr);
+}
+
Index: trace/mercury_trace_internal.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_internal.h,v
retrieving revision 1.5
diff -u -r1.5 mercury_trace_internal.h
--- mercury_trace_internal.h	1999/02/10 22:31:22	1.5
+++ mercury_trace_internal.h	1999/02/16 20:22:02
@@ -48,6 +48,7 @@
 			MR_Trace_Port port, int seqno, int depth,
 			const char *path, int *max_mr_num);
 
+
 /*
 ** Debugger I/O streams.
 ** Replacements for stdin/stdout/stderr respectively.
Index: trace/mercury_trace_tables.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_tables.c,v
retrieving revision 1.4
diff -u -r1.4 mercury_trace_tables.c
--- mercury_trace_tables.c	1998/12/17 13:37:17	1.4
+++ mercury_trace_tables.c	1999/02/16 20:22:02
@@ -15,6 +15,7 @@
 #include "mercury_label.h"
 #include "mercury_array_macros.h"
 #include "mercury_trace_tables.h"
+#include "mercury_trace.h"
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
@@ -386,5 +387,118 @@
 		{
 			f(data, cur_entry);
 		}
+	}
+}
+
+void
+MR_print_proc_id_for_debugger(FILE *fp,
+	const MR_Stack_Layout_Entry *entry_layout)
+{
+	MR_print_proc_id(fp, entry_layout, NULL, NULL, NULL);
+}
+
+void
+MR_print_proc_id(FILE *fp, const MR_Stack_Layout_Entry *entry,
+	const char *extra, Word *base_sp, Word *base_curfr)
+{
+	if (! MR_ENTRY_LAYOUT_HAS_PROC_ID(entry)) {
+		fatal_error("cannot print procedure id without layout");
+	}
+
+	if (base_sp != NULL && base_curfr != NULL) {
+		bool print_details = FALSE;
+		if (MR_ENTRY_LAYOUT_HAS_EXEC_TRACE(entry)) {
+			Word maybe_from_full = entry->MR_sle_maybe_from_full;
+			if (maybe_from_full > 0) {
+				/*
+				** for procedures compiled with shallow
+				** tracing, the details will be valid only
+				** if the value of MR_from_full saved in
+				** the appropriate stack slot was TRUE.
+			    	*/
+				if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
+					print_details = MR_based_stackvar(
+						base_sp, maybe_from_full);
+				} else {
+					print_details = MR_based_framevar(
+						base_curfr, maybe_from_full);
+				}
+			} else {
+				/*
+				** for procedures compiled with full tracing,
+				** always print out the details
+				*/
+				print_details = TRUE;
+			}
+		}
+		if (print_details) {
+			if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
+				fprintf(fp, "%7lu %7lu %4lu ",
+					(unsigned long)
+					MR_event_num_stackvar(base_sp) + 1,
+					(unsigned long)
+					MR_call_num_stackvar(base_sp),
+					(unsigned long)
+					MR_call_depth_stackvar(base_sp));
+			} else {
+				fprintf(fp, "%7lu %7lu %4lu ",
+					(unsigned long)
+					MR_event_num_framevar(base_curfr) + 1,
+					(unsigned long)
+					MR_call_num_framevar(base_curfr),
+					(unsigned long)
+					MR_call_depth_framevar(base_curfr));
+			}
+		} else {
+			/* ensure that the remaining columns line up */
+			fprintf(fp, "%21s", "");
+		}
+	}
+
+	if (MR_ENTRY_LAYOUT_COMPILER_GENERATED(entry)) {
+		fprintf(fp, "%s for %s:%s/%ld-%ld",
+			entry->MR_sle_comp.MR_comp_pred_name,
+			entry->MR_sle_comp.MR_comp_type_module,
+			entry->MR_sle_comp.MR_comp_type_name,
+			(long) entry->MR_sle_comp.MR_comp_arity,
+			(long) entry->MR_sle_comp.MR_comp_mode);
+
+		if (strcmp(entry->MR_sle_comp.MR_comp_type_module,
+				entry->MR_sle_comp.MR_comp_def_module) != 0)
+		{
+			fprintf(fp, " {%s}",
+				entry->MR_sle_comp.MR_comp_def_module);
+		}
+	} else {
+		if (entry->MR_sle_user.MR_user_pred_or_func == MR_PREDICATE) {
+			fprintf(fp, "pred");
+		} else if (entry->MR_sle_user.MR_user_pred_or_func ==
+				MR_FUNCTION)
+		{
+			fprintf(fp, "func");
+		} else {
+			fatal_error("procedure is not pred or func");
+		}
+
+		fprintf(fp, " %s:%s/%ld-%ld",
+			entry->MR_sle_user.MR_user_decl_module,
+			entry->MR_sle_user.MR_user_name,
+			(long) entry->MR_sle_user.MR_user_arity,
+			(long) entry->MR_sle_user.MR_user_mode);
+
+		if (strcmp(entry->MR_sle_user.MR_user_decl_module,
+				entry->MR_sle_user.MR_user_def_module) != 0)
+		{
+			fprintf(fp, " {%s}",
+				entry->MR_sle_user.MR_user_def_module);
+		}
+	}
+
+	fprintf(fp, " (%s)", MR_detism_names[entry->MR_sle_detism]);
+
+	if (extra != NULL) {
+		fprintf(fp, " %s\n", extra);
+	} else {
+		fprintf(fp, "\n");
 	}
 }
Index: trace/mercury_trace_tables.h
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_tables.h,v
retrieving revision 1.2
diff -u -r1.2 mercury_trace_tables.h
--- mercury_trace_tables.h	1998/12/17 13:37:19	1.2
+++ mercury_trace_tables.h	1999/02/16 20:22:02
@@ -121,4 +121,20 @@
 			void f(void *, const MR_Stack_Layout_Entry *), 
 			void *data);
 
+/*
+** MR_print_proc_id prints an identification of the given procedure,
+** consisting of "pred" or "func", module name, pred or func name, arity,
+** mode number and determinism, followed by an optional extra string,
+** and a newline.
+**
+** If the procedure has trace layout information and the relevant one of
+** base_sp and base_curfr is not NULL, it also prints the call event number,
+** call sequence number and call depth of the call.
+*/
+
+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);
+
 #endif	/* not MERCURY_TRACE_TABLES_H */



-- 
R1.





More information about the developers mailing list