for review: new debugger command set, part 2
Zoltan Somogyi
zs at cs.mu.OZ.AU
Mon Jul 6 19:17:07 AEST 1998
Index: runtime/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_internal.c,v
retrieving revision 1.7
diff -u -u -r1.7 mercury_trace_internal.c
--- mercury_trace_internal.c 1998/06/18 06:08:12 1.7
+++ mercury_trace_internal.c 1998/07/06 10:10:58
@@ -14,36 +14,57 @@
#include "mercury_trace.h"
#include "mercury_trace_internal.h"
#include "mercury_trace_util.h"
+#include "mercury_trace_spy.h"
+#include "mercury_trace_tables.h"
#include <stdio.h>
#include <ctype.h>
+#include <unistd.h>
+extern int optind;
+
#define MR_isdigit(c) isdigit((unsigned char) (c))
#define MR_isspace(c) isspace((unsigned char) (c))
-#define MR_NAME_LEN 80
-#define MR_MAX_SPY_POINTS 100
-#define MR_LOG10_MAX_SPY_POINTS 20
-
#define MR_MAX_LINE_LEN 256
+
+#define MR_INIT_SPY_POINTS 10
-typedef struct {
- bool enabled;
- char module_name[MR_NAME_LEN];
- char pred_name[MR_NAME_LEN];
-} MR_spy_point;
+static MR_Spy_Point **MR_spy_points;
+static int MR_spy_point_next = 0;
+static int MR_spy_point_max = 0;
+
+static MR_Trace_Print_Level MR_default_print_level = MR_PRINT_LEVEL_SOME;
+
+static bool MR_scroll_control = FALSE;
+static int MR_scroll_next = 0;
+static int MR_scroll_limit = 20;
+static bool MR_echo_commands = FALSE;
+
+static int MR_trace_saved_call_seqno;
+static int MR_trace_saved_call_depth;
+static int MR_trace_saved_event_number;
typedef enum {
KEEP_INTERACTING,
STOP_INTERACTING
} MR_next;
-static MR_spy_point MR_spy_points[MR_MAX_SPY_POINTS];
-static int MR_next_spy_point = 0;
-
-static MR_next MR_trace_debug_cmd(MR_trace_cmd_info *cmd,
+static void MR_trace_internal_ensure_init(void);
+static MR_next MR_trace_debug_cmd(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout,
- MR_trace_port port, int seqno, int depth,
+ MR_Trace_Port port, int seqno, int depth,
const char *path, int *ancestor_level);
+static bool MR_trace_options_strict_print(MR_Trace_Cmd_Info *cmd,
+ char ***words, int *word_count, const char *usage);
+static bool MR_trace_options_when_action(MR_Spy_When *when,
+ MR_Spy_Action *action, char ***words, int *word_count,
+ const char *usage);
+static void MR_trace_restart(const MR_Stack_Layout_Label *layout,
+ int seqno, int depth);
+static Word MR_trace_find_input_arg(const MR_Stack_Layout_Label *label,
+ const char *name, bool *succeeded);
+static void MR_ensure_room_for_spy_point(void);
+static void MR_print_spy_point(int i);
static void MR_trace_list_vars(const MR_Stack_Layout_Label *top_layout,
int ancestor_level);
static void MR_trace_browse_one(const MR_Stack_Layout_Label *top_layout,
@@ -59,33 +80,75 @@
static bool MR_trace_is_number(char *word, int *value);
static bool MR_trace_is_number_prefix(char *word, char **suffix,
int *value);
-static int MR_trace_break_into_words(char line[], char *words[]);
-static int MR_trace_getline(FILE *file, char line[], int line_max);
+static const char *MR_trace_parse_line(char *line,
+ char ***words_ptr, int *word_count_ptr);
+static int MR_trace_break_into_words(char *line,
+ char ***words_ptr, int *words_max);
+static char *MR_trace_getline(FILE *file);
-static void MR_trace_print_port(MR_trace_port port);
-static void MR_trace_print_detism(Word detism);
+static void MR_trace_event_print_internal_report(
+ const MR_Stack_Layout_Label *layout,
+ MR_Trace_Port port, int seqno, int depth,
+ const char *path);
+static void MR_trace_print_port(MR_Trace_Port port);
+
+/* If you add a usage message, add it to MR_trace_help as well. */
+static char step_usage[] = "step [-NSans] [<number>]";
+static char goto_usage[] = "goto [-NSans] <number>";
+static char finish_usage[] = "finish [-NSans]";
+static char forward_usage[] = "forward [-NSans]";
+static char continue_usage[] = "continue [-NSans]";
+static char restart_usage[] = "restart";
+static char level_usage[] = "level <number>";
+static char up_usage[] = "up <number>";
+static char down_usage[] = "down <number>";
+static char vars_usage[] = "vars";
+static char print_usage[] = "print (<number> | *)";
+static char stack_usage[] = "stack";
+static char stack_regs_usage[] = "stack_regs";
+static char break_usage[] = "break (info | [-PSaei] (<module> <pred> [<arity> [<mode>]] | here))";
+static char enable_usage[] = "enable (<number> | *)";
+static char disable_usage[] = "disable (<number> | *)";
+static char register_usage[] = "register";
+static char module_table_usage[] = "module_table";
+#ifdef MR_TRACE_HISTOGRAM
+static char histogram_all_usage[] = "histogram_all";
+static char histogram_exp_usage[] = "histogram_exp";
+static char clear_histogram_usage[] = "clear_histogram";
+#endif
+static char printlevel_usage[] = "printlevel [none | some | all]";
+static char scroll_usage[] = "scroll [on | off]";
+static char echo_usage[] = "echo [on | off]";
+static char help_usage[] = "help";
+static char quit_usage[] = "quit";
void
-MR_trace_event_internal(MR_trace_cmd_info *cmd,
+MR_trace_event_internal(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout,
- MR_trace_port port, int seqno, int depth, const char *path)
+ MR_Trace_Port port, int seqno, int depth, const char *path)
{
int i;
int c;
int count;
bool count_given;
- Word saved_seqno;
- Word saved_depth;
- Word saved_event;
int ancestor_level;
- MR_trace_event_internal_report(layout, port, seqno, depth, path);
+ MR_trace_internal_ensure_init();
- /* these globals can be overwritten when we call Mercury code */
- saved_seqno = MR_trace_call_seqno;
- saved_depth = MR_trace_call_depth;
- saved_event = MR_trace_event_number;
+ MR_trace_event_print_internal_report(layout, port, seqno, depth, path);
+ /*
+ ** These globals can be overwritten when we call Mercury code,
+ ** such as the term browser. We therefore save and restore them
+ ** across calls to MR_trace_debug_cmd. However, we store the
+ ** saved values in global instead of local variables, to allow them
+ ** to be modified by MR_trace_restart().
+ */
+
+ MR_trace_saved_call_seqno = MR_trace_call_seqno;
+ MR_trace_saved_call_depth = MR_trace_call_depth;
+ MR_trace_saved_event_number = MR_trace_event_number;
+
/* by default, print variables from the current procedure */
ancestor_level = 0;
@@ -93,211 +156,243 @@
&ancestor_level) == KEEP_INTERACTING) {
; /* all the work is done in MR_trace_debug_cmd */
}
+
+ cmd->MR_trace_must_check = (! cmd->MR_trace_strict) ||
+ (cmd->MR_trace_print_level != MR_PRINT_LEVEL_NONE);
+
+ MR_trace_call_seqno = MR_trace_saved_call_seqno;
+ MR_trace_call_depth = MR_trace_saved_call_depth;
+ MR_trace_event_number = MR_trace_saved_event_number;
- MR_trace_call_seqno = saved_seqno;
- MR_trace_call_depth = saved_depth;
- MR_trace_event_number = saved_event;
+ MR_scroll_next = 1;
}
+static void
+MR_trace_internal_ensure_init(void)
+{
+ static bool done = FALSE;
+
+ if (! done) {
+ printf("Melbourne Mercury Debugger\n");
+ done = TRUE;
+ }
+}
+
static MR_next
-MR_trace_debug_cmd(MR_trace_cmd_info *cmd, const MR_Stack_Layout_Label *layout,
- MR_trace_port port, int seqno, int depth, const char *path,
+MR_trace_debug_cmd(MR_Trace_Cmd_Info *cmd, const MR_Stack_Layout_Label *layout,
+ MR_Trace_Port port, int seqno, int depth, const char *path,
int *ancestor_level)
{
- char line[MR_MAX_LINE_LEN];
- char count_buf[MR_MAX_LINE_LEN];
- char *raw_words[MR_MAX_LINE_LEN / 2 + 1];
- char **words;
- char raw_word_count;
- char word_count;
- char *s;
- int i, n;
+ char *line;
+ char **words;
+ char **orig_words;
+ int word_count;
+ const char *problem;
+ int i;
+ int n;
- printf("mtrace> ");
+ printf("mdb> ");
- if (MR_trace_getline(stdin, line, MR_MAX_LINE_LEN) == 0) {
+ line = MR_trace_getline(stdin);
+
+ if (line == NULL) {
/*
- ** We got a line without even a newline character,
- ** which must mean that the user typed EOF.
+ ** We got an EOF.
** We arrange things so we don't have to treat this case
** specially in the command interpreter below.
*/
- (void) strcpy(line, "a\n");
+ line = checked_malloc(sizeof("quit\n") + 1);
+ (void) strcpy(line, "quit\n");
}
- /*
- ** Handle a possible number prefix on the first word on the line,
- ** separating it out into a word on its own.
- */
-
- raw_word_count = MR_trace_break_into_words(line, raw_words + 1);
-
- if (raw_word_count > 0 && MR_isdigit(*raw_words[1])) {
- i = 0;
- s = raw_words[1];
- while (MR_isdigit(*s)) {
- count_buf[i] = *s;
- i++;
- s++;
- }
-
- count_buf[i] = '\0';
-
- if (*s == '\0') {
- /* all of the first word constitutes a number */
- /* exchange it with the command, if it exists */
-
- if (raw_word_count > 1) {
- s = raw_words[1];
- raw_words[1] = raw_words[2];
- raw_words[2] = s;
- }
-
- words = raw_words + 1;
- word_count = raw_word_count;
- } else {
- /* only part of the first word constitutes a number */
- /* put it in an extra word at the start */
-
- raw_words[0] = count_buf;
- raw_words[1] = s;
- words = raw_words;
- word_count = raw_word_count + 1;
- }
- } else {
- words = raw_words + 1;
- word_count = raw_word_count;
+ if (MR_echo_commands) {
+ fputs(line, stdout);
}
-
- /*
- ** If the first word is a number, try to exchange it
- ** with the command word, to put the command word first.
- */
- if (word_count > 1 && MR_trace_is_number(words[0], &n)
- && ! MR_trace_is_number(words[1], &n)) {
- s = words[0];
- words[0] = words[1];
- words[1] = s;
+ problem = MR_trace_parse_line(line, &words, &word_count);
+ if (problem != NULL) {
+ printf("%s\n", problem);
+ goto return_keep_interacting;
}
/*
** At this point, the first word_count members of the words
- ** array contain the command.
+ ** array contain the command. We save the value of words for
+ ** freeing just before return, since the variable words itself
+ ** can be overwritten by option processing.
*/
-
- cmd->MR_trace_print_intermediate = FALSE;
+ orig_words = words;
if (word_count == 0) {
cmd->MR_trace_cmd = MR_CMD_GOTO;
- cmd->MR_trace_print_intermediate = FALSE;
cmd->MR_trace_stop_event = MR_trace_event_number + 1;
- return STOP_INTERACTING;
+ cmd->MR_trace_strict = FALSE;
+ cmd->MR_trace_print_level = MR_default_print_level;
+ goto return_stop_interacting;
} else if (MR_trace_is_number(words[0], &n)) {
if (word_count == 1) {
cmd->MR_trace_cmd = MR_CMD_GOTO;
- cmd->MR_trace_print_intermediate = FALSE;
cmd->MR_trace_stop_event = MR_trace_event_number + n;
- return STOP_INTERACTING;
+ cmd->MR_trace_strict = FALSE;
+ cmd->MR_trace_print_level = MR_default_print_level;
+ goto return_stop_interacting;
} else {
printf("One of the first two words "
"must be a command.\n");
}
- } else if (streq(words[0], "S") || streq(words[0], "s")) {
- if (word_count == 1) {
+ } else if (streq(words[0], "step")) {
+ cmd->MR_trace_strict = FALSE;
+ cmd->MR_trace_print_level = MR_default_print_level;
+ if (! MR_trace_options_strict_print(cmd, &words, &word_count,
+ step_usage)) {
+ ; /* the usage message has already been printed */
+ } else if (word_count == 1) {
cmd->MR_trace_cmd = MR_CMD_GOTO;
- cmd->MR_trace_print_intermediate = streq(words[0], "S");
cmd->MR_trace_stop_event = MR_trace_event_number + 1;
- return STOP_INTERACTING;
+ goto return_stop_interacting;
} else if (word_count == 2
&& MR_trace_is_number(words[1], &n)) {
cmd->MR_trace_cmd = MR_CMD_GOTO;
- cmd->MR_trace_print_intermediate = streq(words[0], "S");
cmd->MR_trace_stop_event = MR_trace_event_number + n;
- return STOP_INTERACTING;
+ goto return_stop_interacting;
} else {
- printf("This command expects at most one argument,\n"
- "which must be a number.\n");
+ printf("Usage: %s\n", step_usage);
}
- } else if (streq(words[0], "g") || streq(words[0], "G")) {
- if (word_count == 2 && MR_trace_is_number(words[1], &n)) {
+ } else if (streq(words[0], "goto")) {
+ cmd->MR_trace_strict = FALSE;
+ cmd->MR_trace_print_level = MR_default_print_level;
+ if (! MR_trace_options_strict_print(cmd, &words, &word_count,
+ goto_usage)) {
+ ; /* the usage message has already been printed */
+ } else if (word_count == 2 && MR_trace_is_number(words[1], &n))
+ {
if (MR_trace_event_number < n) {
cmd->MR_trace_cmd = MR_CMD_GOTO;
- cmd->MR_trace_print_intermediate =
- streq(words[0], "G");
cmd->MR_trace_stop_event = n;
- return STOP_INTERACTING;
+ goto return_stop_interacting;
} else {
printf("The debugger cannot go "
"to a past event.\n");
}
} else {
- printf("This command expects exactly one argument,\n");
- printf("which must be a number.\n");
+ printf("Usage: %s\n", goto_usage);
}
- } else if (streq(words[0], "f") || streq(words[0], "F")) {
- if (word_count == 1) {
+ } else if (streq(words[0], "finish")) {
+ cmd->MR_trace_strict = TRUE;
+ cmd->MR_trace_print_level = MR_default_print_level;
+ if (! MR_trace_options_strict_print(cmd, &words, &word_count,
+ finish_usage)) {
+ ; /* the usage message has already been printed */
+ } else if (word_count == 1) {
if (MR_port_is_final(port)) {
printf("This command is a no-op "
"from this port.\n");
} else {
cmd->MR_trace_cmd = MR_CMD_FINISH;
- cmd->MR_trace_print_intermediate =
- streq(words[0], "F");
cmd->MR_trace_stop_seqno = seqno;
- return STOP_INTERACTING;
+ cmd->MR_trace_strict = TRUE;
+ goto return_stop_interacting;
}
} else {
- printf("This command expects no argument.\n");
+ printf("Usage: %s\n", finish_usage);
}
- } else if (streq(words[0], "c") || streq(words[0], "C")) {
- if (word_count == 1) {
+ } else if (streq(words[0], "forward")) {
+ cmd->MR_trace_strict = TRUE;
+ cmd->MR_trace_print_level = MR_default_print_level;
+ if (! MR_trace_options_strict_print(cmd, &words, &word_count,
+ forward_usage)) {
+ ; /* the usage message has already been printed */
+ } else if (word_count == 1) {
+ cmd->MR_trace_cmd = MR_CMD_RESUME_FORWARD;
+ goto return_stop_interacting;
+ } else {
+ printf("Usage: %s\n", forward_usage);
+ }
+ } else if (streq(words[0], "continue")) {
+ cmd->MR_trace_strict = FALSE;
+ cmd->MR_trace_print_level = (MR_Trace_Cmd_Type) -1;
+ if (! MR_trace_options_strict_print(cmd, &words, &word_count,
+ continue_usage)) {
+ ; /* the usage message has already been printed */
+ } else if (word_count == 1) {
cmd->MR_trace_cmd = MR_CMD_TO_END;
- cmd->MR_trace_print_intermediate =
- streq(words[0], "C");
- return STOP_INTERACTING;
+ if (cmd->MR_trace_print_level ==
+ (MR_Trace_Cmd_Type) -1) {
+ /*
+ ** The user did not specify the print level;
+ ** select the intelligent default.
+ */
+ if (cmd->MR_trace_strict) {
+ cmd->MR_trace_print_level =
+ MR_PRINT_LEVEL_NONE;
+ } else {
+ cmd->MR_trace_print_level =
+ MR_PRINT_LEVEL_SOME;
+ }
+ }
+ goto return_stop_interacting;
} else {
- printf("This command expects no argument.\n");
+ printf("Usage: %s\n", continue_usage);
}
- } else if (streq(words[0], "r") || streq(words[0], "R")) {
+ } else if (streq(words[0], "restart")) {
if (word_count == 1) {
- cmd->MR_trace_cmd = MR_CMD_RESUME_FORWARD;
- cmd->MR_trace_print_intermediate =
- streq(words[0], "R");
- return STOP_INTERACTING;
+ if (! MR_port_is_final(port)) {
+ printf("For technical reasons, "
+ "it is not yet possible to "
+ "restart from a non-final port.\n");
+ }
+
+ MR_trace_restart(layout, seqno, depth);
+
+ cmd->MR_trace_cmd = MR_CMD_GOTO;
+ cmd->MR_trace_stop_event = MR_trace_event_number + 1;
+ cmd->MR_trace_strict = FALSE;
+ cmd->MR_trace_print_level = MR_default_print_level;
+ goto return_stop_interacting;
} else {
- printf("This command expects no argument.\n");
+ printf("Usage: %s\n", restart_usage);
}
- } else if (streq(words[0], "l")) {
+ } else if (streq(words[0], "level")) {
if (word_count == 2 && MR_trace_is_number(words[1], &n)) {
*ancestor_level = n;
printf("Ancestor level set to %d\n", n);
} else {
- printf("This command expects one argument,\n");
- printf("a number denoting an ancestor level.\n");
+ printf("Usage: %s\n", level_usage);
}
- } else if (streq(words[0], "v")) {
+ } else if (streq(words[0], "up")) {
+ if (word_count == 2 && MR_trace_is_number(words[1], &n)) {
+ *ancestor_level += n;
+ printf("Ancestor level set to %d\n", n);
+ } else {
+ printf("Usage: %s\n", up_usage);
+ }
+ } else if (streq(words[0], "down")) {
+ if (word_count == 2 && MR_trace_is_number(words[1], &n)) {
+ *ancestor_level -= n;
+ printf("Ancestor level set to %d\n", n);
+ } else {
+ printf("Usage: %s\n", down_usage);
+ }
+ } else if (streq(words[0], "vars")) {
if (word_count == 1) {
MR_trace_list_vars(layout, *ancestor_level);
} else {
- printf("This command expects no argument.\n");
+ printf("Usage: %s\n", vars_usage);
}
- } else if (streq(words[0], "p")) {
+ } else if (streq(words[0], "print")) {
if (word_count == 2) {
if (MR_trace_is_number(words[1], &n)) {
MR_trace_browse_one(layout, *ancestor_level, n);
} else if streq(words[1], "*") {
MR_trace_browse_all(layout, *ancestor_level);
} else {
- printf("The argument of this command should be,\n");
- printf("a variable number or a '*' indicating all variables.\n");
+ printf("Usage: %s\n", print_usage);
}
} else {
- printf("This command expects one argument,\n");
- printf("a variable number or a '*' indicating all variables.\n");
+ printf("Usage: %s\n", print_usage);
}
- } else if (streq(words[0], "d")) {
+ } else if (streq(words[0], "stack")) {
if (word_count == 1) {
const char *result;
@@ -310,110 +405,299 @@
printf("%s\n", result);
}
} else {
- printf("This command expects no argument.\n");
+ printf("Usage: %s\n", stack_usage);
}
- } else if (streq(words[0], "X")) {
- printf("sp = %p, curfr = %p, maxfr = %p\n",
- MR_saved_sp(MR_saved_regs),
- MR_saved_curfr(MR_saved_regs),
- MR_saved_maxfr(MR_saved_regs));
- } else if (streq(words[0], "b")) {
- if (word_count != 3) {
- printf("This command expects two arguments,\n");
- printf("a module name and a predicate name.\n");
- } else {
- if (MR_next_spy_point >= MR_MAX_SPY_POINTS) {
- printf("There is no room "
- "for any more spy points.\n");
- } else {
- printf("%2d: %s %s:%s\n", MR_next_spy_point,
- "+", words[1], words[2]);
- strcpy(MR_spy_points[MR_next_spy_point]
- .module_name, words[1]);
- strcpy(MR_spy_points[MR_next_spy_point]
- .pred_name, words[2]);
- MR_spy_points[MR_next_spy_point].enabled
- = TRUE;
- MR_next_spy_point++;
- }
- }
- } else if (streq(words[0], "?")) {
- for (i = 0; i < MR_next_spy_point; i++) {
- printf("%2d: %s %s:%s\n", i,
- MR_spy_points[i].enabled ? "+" : "-",
- MR_spy_points[i].module_name,
- MR_spy_points[i].pred_name);
+ } else if (streq(words[0], "stack_regs")) {
+ if (word_count == 1) {
+ printf("sp = %p, curfr = %p, maxfr = %p\n",
+ MR_saved_sp(MR_saved_regs),
+ MR_saved_curfr(MR_saved_regs),
+ MR_saved_maxfr(MR_saved_regs));
+ } else {
+ printf("Usage: %s\n", stack_regs_usage);
}
- } else if (streq(words[0], "+")) {
- if (word_count == 2) {
- if (MR_trace_is_number(words[1], &n)) {
- if (0 <= n && n < MR_next_spy_point) {
- MR_spy_points[n].enabled = TRUE;
- printf("%2d: %s %s:%s\n", n,
- "+",
- MR_spy_points[n].module_name,
- MR_spy_points[n].pred_name);
+ } else if (streq(words[0], "break")) {
+ MR_Spy_When when;
+ MR_Spy_Action action;
+ int arity;
+ int mode;
+
+ if (word_count == 2 && streq(words[1], "info")) {
+ for (i = 0; i < MR_spy_point_next; i++) {
+ MR_print_spy_point(i);
+ }
+
+ goto return_keep_interacting;
+ }
+
+ when = MR_SPY_INTERFACE;
+ action = MR_SPY_STOP;
+ if (! MR_trace_options_when_action(&when, &action,
+ &words, &word_count, break_usage)) {
+ ; /* the usage message has already been printed */
+ } else if (word_count == 2 && streq(words[1], "here")) {
+ MR_register_all_modules_and_procs(stdout);
+ MR_ensure_room_for_spy_point();
+ MR_spy_points[MR_spy_point_next] = MR_add_spy_point(
+ MR_SPY_SPECIFIC, action,
+ layout->MR_sll_entry, layout,
+ path);
+ MR_print_spy_point(MR_spy_point_next);
+ MR_spy_point_next++;
+ } else if (word_count == 3) {
+ const MR_Stack_Layout_Entry *spy_proc;
+ bool unique;
+
+ MR_register_all_modules_and_procs(stdout);
+ spy_proc = MR_search_for_module_proc(words[1], words[2],
+ &unique);
+ if (spy_proc != NULL) {
+ if (unique) {
+ MR_ensure_room_for_spy_point();
+ MR_spy_points[MR_spy_point_next] =
+ MR_add_spy_point(
+ when, action,
+ spy_proc, NULL,
+ path);
+ MR_print_spy_point(MR_spy_point_next);
+ MR_spy_point_next++;
} else {
- printf("Break point #%d "
- "does not exist.\n", n);
+ printf("Ambiguous procedure "
+ "specification. "
+ "The matches are:\n");
+ MR_process_all_module_proc(
+ MR_print_proc_id_to_stdout,
+ words[1], words[2]);
}
- } else if (streq(words[1], "*")) {
- for (i = 0; i < MR_next_spy_point; i++) {
- MR_spy_points[i].enabled = TRUE;
- printf("%2d: %s %s:%s\n", i,
- "+",
- MR_spy_points[i].module_name,
- MR_spy_points[i].pred_name);
+ } else {
+ printf("There is no such procedure.\n");
+ }
+ } else if (word_count == 4 &&
+ MR_trace_is_number(words[3], &arity)) {
+ const MR_Stack_Layout_Entry *spy_proc;
+ bool unique;
+
+ MR_register_all_modules_and_procs(stdout);
+ spy_proc = MR_search_for_module_proc_arity(words[1],
+ words[2], arity, &unique);
+ if (spy_proc != NULL) {
+ if (unique) {
+ MR_ensure_room_for_spy_point();
+ MR_spy_points[MR_spy_point_next] =
+ MR_add_spy_point(
+ when, action,
+ spy_proc, NULL,
+ path);
+ MR_print_spy_point(MR_spy_point_next);
+ MR_spy_point_next++;
+ } else {
+ printf("Ambiguous procedure "
+ "specification. "
+ "The matches are:\n");
+ MR_process_all_module_proc_arity(
+ MR_print_proc_id_to_stdout,
+ words[1], words[2], arity);
}
} else {
- printf("The argument of this command must be "
- "a break point number or a `*'.\n");
+ printf("There is no such procedure.\n");
}
+ } else if (word_count == 5 &&
+ MR_trace_is_number(words[3], &arity) &&
+ MR_trace_is_number(words[4], &mode)) {
+ const MR_Stack_Layout_Entry *spy_proc;
+ bool unique;
+
+ MR_register_all_modules_and_procs(stdout);
+ spy_proc = MR_search_for_module_proc_arity_mode(
+ words[1], words[2], arity, mode,
+ &unique);
+ if (spy_proc != NULL) {
+ if (unique) {
+ MR_ensure_room_for_spy_point();
+ MR_spy_points[MR_spy_point_next] =
+ MR_add_spy_point(
+ when, action,
+ spy_proc, NULL,
+ path);
+ MR_print_spy_point(MR_spy_point_next);
+ MR_spy_point_next++;
+ } else {
+ printf("Ambiguous procedure "
+ "specification. "
+ "The matches are:\n");
+ MR_process_all_module_proc_arity_mode(
+ MR_print_proc_id_to_stdout,
+ words[1], words[2],
+ arity, mode);
+ }
+ } else {
+ printf("There is no such procedure.\n");
+ }
+ } else {
+ printf("Usage: %s\n", break_usage);
+ }
+ } else if (streq(words[0], "enable")) {
+ if (word_count == 2 && MR_trace_is_number(words[1], &n)) {
+ if (0 <= n && n < MR_spy_point_next) {
+ MR_spy_points[n]->spy_enabled = TRUE;
+ MR_print_spy_point(n);
+ } else {
+ printf("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++) {
+ MR_spy_points[i]->spy_enabled = TRUE;
+ MR_print_spy_point(n);
+ }
+
+ if (MR_spy_point_next == 0) {
+ printf("There no break points yet.\n");
+ }
+ } else {
+ printf("Usage: %s\n", enable_usage);
+ }
+ } else if (streq(words[0], "disable")) {
+ if (word_count == 2 && MR_trace_is_number(words[1], &n)) {
+ if (0 <= n && n < MR_spy_point_next) {
+ MR_spy_points[n]->spy_enabled = FALSE;
+ MR_print_spy_point(n);
+ } else {
+ printf("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++) {
+ MR_spy_points[i]->spy_enabled = FALSE;
+ MR_print_spy_point(n);
+ }
+
+ if (MR_spy_point_next == 0) {
+ printf("There no break points yet.\n");
+ }
} else {
- printf("This command expects one argument,\n");
- printf("which must be a break point number "
- "or a `*'.\n");
+ printf("Usage: %s\n", disable_usage);
}
- } else if (streq(words[0], "-")) {
+ } else if (streq(words[0], "register")) {
+ if (word_count == 1) {
+ MR_register_all_modules_and_procs(stdout);
+ } else {
+ printf("Usage: %s\n", register_usage);
+ }
+ } else if (streq(words[0], "module_table")) {
+ if (word_count == 1) {
+ MR_register_all_modules_and_procs(stdout);
+ MR_dump_module_tables(stdout);
+ } else {
+ printf("Usage: %s\n", module_table_usage);
+ }
+#ifdef MR_TRACE_HISTOGRAM
+ } else if (streq(words[0], "histogram_all")) {
+ if (word_count == 1) {
+ MR_trace_print_histogram(stdout, "All-inclusive",
+ MR_trace_histogram_all, MR_trace_histogram_hwm);
+ } else {
+ printf("Usage: %s\n", histogram_all_usage);
+ }
+ } else if (streq(words[0], "histogram_exp")) {
+ if (word_count == 1) {
+ MR_trace_print_histogram(stdout, "Experimental",
+ MR_trace_histogram_exp, MR_trace_histogram_hwm);
+ } else {
+ printf("Usage: %s\n", histogram_exp_usage);
+ }
+ } else if (streq(words[0], "clear_histogram")) {
+ if (word_count == 1) {
+ for (i = 0; i <= MR_trace_histogram_hwm; i++) {
+ MR_trace_histogram_exp[i] = 0;
+ }
+ } else {
+ printf("Usage: %s\n", clear_histogram_usage);
+ }
+#endif
+ } else if (streq(words[0], "printlevel")) {
if (word_count == 2) {
- if (MR_trace_is_number(words[1], &n)) {
- if (0 <= n && n < MR_next_spy_point) {
- MR_spy_points[n].enabled = FALSE;
- printf("%2d: %s %s:%s\n", n,
- "-",
- MR_spy_points[n].module_name,
- MR_spy_points[n].pred_name);
- } else {
- printf("Break point #%d "
- "does not exist.\n", n);
- }
- } else if (streq(words[1], "*")) {
- for (i = 0; i < MR_next_spy_point; i++) {
- MR_spy_points[i].enabled = FALSE;
- printf("%2d: %s %s:%s\n", i,
- "-",
- MR_spy_points[i].module_name,
- MR_spy_points[i].pred_name);
- }
+ if (streq(words[1], "none")) {
+ MR_default_print_level = MR_PRINT_LEVEL_NONE;
+ printf("Default print level set to none.\n");
+ } else if (streq(words[1], "some")) {
+ MR_default_print_level = MR_PRINT_LEVEL_SOME;
+ printf("Default print level set to some.\n");
+ } else if (streq(words[1], "all")) {
+ MR_default_print_level = MR_PRINT_LEVEL_ALL;
+ printf("Default print level set to all.\n");
} else {
- printf("The argument of this command must be "
- "a break point number or a `*'.\n");
+ printf("Usage: %s\n", printlevel_usage);
}
+ } else if (word_count == 1) {
+ printf("The default print level is ");
+ switch (MR_default_print_level) {
+ case MR_PRINT_LEVEL_NONE:
+ printf("none.\n");
+ break;
+ case MR_PRINT_LEVEL_SOME:
+ printf("some.\n");
+ break;
+ case MR_PRINT_LEVEL_ALL:
+ printf("all.\n");
+ break;
+ default:
+ printf("something weird.\n");
+ break;
+ }
} else {
- printf("This command expects one argument,\n");
- printf("which must be a break point number "
- "or a `*'.\n");
+ printf("Usage: %s\n", printlevel_usage);
}
- } else if (streq(words[0], "h")) {
+ } else if (streq(words[0], "scroll")) {
+ if (word_count == 2) {
+ if (streq(words[1], "off")) {
+ MR_scroll_control = FALSE;
+ printf("Scroll control disabled\n");
+ } else if (streq(words[1], "on")) {
+ MR_scroll_control = TRUE;
+ printf("Scroll control enabled\n");
+ } else {
+ printf("Usage: %s\n", scroll_usage);
+ }
+ } else if (word_count == 1) {
+ printf("Scroll control is ");
+ if (MR_scroll_control) {
+ printf("on.\n");
+ } else {
+ printf("off.\n");
+ }
+ } else {
+ printf("Usage: %s\n", scroll_usage);
+ }
+ } else if (streq(words[0], "echo")) {
+ if (word_count == 2) {
+ if (streq(words[1], "off")) {
+ MR_echo_commands = FALSE;
+ printf("Command echo disabled\n");
+ } else if (streq(words[1], "on")) {
+ MR_echo_commands = TRUE;
+ printf("Command echo enabled\n");
+ } else {
+ printf("Usage: %s\n", echo_usage);
+ }
+ } else if (word_count == 1) {
+ printf("Command echo is ");
+ if (MR_echo_commands) {
+ printf("on.\n");
+ } else {
+ printf("off.\n");
+ }
+ } else {
+ printf("Usage: %s\n", echo_usage);
+ }
+ } else if (streq(words[0], "help")) {
if (word_count != 1) {
- printf("This command expects no argument.\n");
+ printf("Usage: %s\n", help_usage);
}
MR_trace_help();
- } else if (streq(words[0], "a")) {
+ } else if (streq(words[0], "quit")) {
if (word_count == 1) {
- printf("mtrace: are you sure you want to abort? ");
- if (MR_trace_getline(stdin, line, MR_MAX_LINE_LEN)
- == 0) {
+ printf("mdb: are you sure you want to quit? ");
+ line = MR_trace_getline(stdin);
+ if (line == NULL) {
/* This means the user input EOF. */
exit(0);
} else {
@@ -423,19 +707,302 @@
if (line[i] == 'y' || line[i] == 'Y') {
exit(0);
}
+
+ free(line);
}
} else {
- printf("This command expects no argument.\n");
+ printf("Usage: %s\n", quit_usage);
}
} else {
- printf("Command not recognized. "
- "Give the command `h' for help.\n");
+ printf("Unknown command. Give the command `help' for help.\n");
}
+ /* fall through */
+return_keep_interacting:
+ free(line);
+ free(orig_words);
return KEEP_INTERACTING;
+
+return_stop_interacting:
+ free(line);
+ free(orig_words);
+ return STOP_INTERACTING;
+}
+
+static bool
+MR_trace_options_strict_print(MR_Trace_Cmd_Info *cmd,
+ char ***words, int *word_count, const char *usage)
+{
+ int c;
+
+ optind = 0;
+ while ((c = getopt(*word_count, *words, "NSans")) != EOF) {
+ switch (c) {
+
+ case 'N':
+ cmd->MR_trace_strict = FALSE;
+ break;
+
+ case 'S':
+ cmd->MR_trace_strict = TRUE;
+ break;
+
+ case 'a':
+ cmd->MR_trace_print_level = MR_PRINT_LEVEL_ALL;
+ break;
+
+ case 'n':
+ cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE;
+ break;
+
+ case 's':
+ cmd->MR_trace_print_level = MR_PRINT_LEVEL_SOME;
+ break;
+
+ default:
+ printf("Usage: %s\n", usage);
+ return FALSE;
+ }
+
+#if 0
+ printf("option %c recognized\n", c);
+#endif
+ }
+
+#if 0
+ printf("optind = %d, word_count = %d\n", optind, *word_count);
+ for (c = 1; c < *word_count; c++) {
+ printf("argv[%d] = <%s>\n", c, (*words)[c]);
+ }
+#endif
+
+ *words = *words + optind - 1;
+ *word_count = *word_count - optind + 1;
+ return TRUE;
}
+static bool
+MR_trace_options_when_action(MR_Spy_When *when, MR_Spy_Action *action,
+ char ***words, int *word_count, const char *usage)
+{
+ int c;
+
+ optind = 0;
+ while ((c = getopt(*word_count, *words, "PSaei")) != EOF) {
+ switch (c) {
+
+ case 'a':
+ *when = MR_SPY_ALL;
+ break;
+
+ case 'e':
+ *when = MR_SPY_ENTRY;
+ break;
+
+ case 'i':
+ *when = MR_SPY_INTERFACE;
+ break;
+
+ case 'P':
+ *action = MR_SPY_PRINT;
+ break;
+
+ case 'S':
+ *action = MR_SPY_STOP;
+ break;
+
+ default:
+ printf("Usage: %s\n", usage);
+ return FALSE;
+ }
+
+#if 0
+ printf("option %c recognized\n", c);
+#endif
+ }
+
+#if 0
+ printf("optind = %d, word_count = %d\n", optind, *word_count);
+ for (c = 1; c < *word_count; c++) {
+ printf("argv[%d] = <%s>\n", c, (*words)[c]);
+ }
+#endif
+
+ *words = *words + optind - 1;
+ *word_count = *word_count - optind + 1;
+ return TRUE;
+}
+
+#define MR_INIT_ARG_COUNT 20
+
static void
+MR_trace_restart(const MR_Stack_Layout_Label *this_label, int seqno, int depth)
+{
+ const MR_Stack_Layout_Entry *entry;
+ const MR_Stack_Layout_Label *call_label;
+ const MR_Stack_Layout_Vars *input_args;
+ Word *args;
+ int arg_max;
+ int arg_num;
+ Word arg_value;
+ int i;
+ bool succeeded;
+
+ entry = this_label->MR_sll_entry;
+ call_label = entry->MR_sle_call_label;
+
+ if (call_label->MR_sll_var_count < 0) {
+ printf("Cannot perform restart because information about "
+ "the input arguments is not available.\n");
+ return;
+ }
+
+ input_args = &call_label->MR_sll_var_info;
+
+ arg_max = MR_INIT_ARG_COUNT;
+ args = checked_malloc(arg_max * sizeof(Word));
+
+ for (i = 0; i < call_label->MR_sll_var_count; i++) {
+ arg_value = MR_trace_find_input_arg(this_label,
+ input_args->MR_slvs_names[i], &succeeded);
+
+ if (! succeeded) {
+ printf("Cannot perform restart because the values of "
+ "some input arguments are missing.\n");
+ return;
+ }
+
+ arg_num = MR_trace_get_register_number(
+ input_args->MR_slvs_pairs[i].MR_slv_locn);
+ if (arg_num > 0) {
+ if (arg_num >= arg_max) {
+ arg_max *= 2;
+ args = checked_realloc(args,
+ arg_max * sizeof(Word));
+ }
+
+ args[arg_num] = arg_value;
+ } else {
+ fatal_error("illegal location for input argument");
+ }
+ }
+
+ MR_trace_saved_call_seqno = seqno - 1;
+ MR_trace_saved_call_depth = depth - 1;
+
+ if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
+ MR_Live_Lval location;
+ Word *this_frame;
+
+ /*
+ ** We are at a final port, so both curfr and maxfr
+ ** must already have been reset to their original values.
+ ** We only need to set up the succip register for the "call",
+ ** and then remove this frame from the det stack.
+ */
+
+ location = entry->MR_sle_succip_locn;
+ if (MR_LIVE_LVAL_TYPE(location) != MR_LVAL_TYPE_STACKVAR) {
+ fatal_error("illegal location for stored succip");
+ }
+
+ this_frame = MR_saved_sp(MR_saved_regs);
+ MR_saved_succip(MR_saved_regs) = based_detstackvar(this_frame,
+ MR_LIVE_LVAL_NUMBER(location));
+ MR_saved_sp(MR_saved_regs) -= entry->MR_sle_stack_slots;
+ MR_trace_saved_event_number = based_detstackvar(this_frame,
+ entry->MR_sle_event_slot);
+ } else {
+ Word *this_frame;
+
+ /*
+ ** We are at a final port, so sp must already have been reset
+ ** to its original value. We only need to set up the succip
+ ** and curfr registers for the "call", and remove this frame,
+ ** and any other frames above it, from the nondet stack.
+ */
+
+ this_frame = MR_saved_curfr(MR_saved_regs);
+
+ MR_saved_succip(MR_saved_regs) = bt_succip(this_frame);
+ MR_saved_curfr(MR_saved_regs) = bt_succfr(this_frame);
+ MR_saved_maxfr(MR_saved_regs) = bt_prevfr(this_frame);
+ MR_trace_saved_event_number = based_framevar(this_frame,
+ entry->MR_sle_event_slot);
+ }
+
+ for (i = 1; i < arg_max; i++) {
+ saved_reg(MR_saved_regs, i) = args[i];
+ }
+
+ free(args);
+
+ MR_trace_goto_reg_count = max(MR_trace_goto_reg_count, arg_max);
+ MR_trace_goto = entry->MR_sle_code_addr;
+
+ MR_trace_call_seqno = MR_trace_saved_call_seqno;
+ MR_trace_call_depth = MR_trace_saved_call_depth;
+ MR_trace_event_number = MR_trace_saved_event_number;
+}
+
+static Word
+MR_trace_find_input_arg(const MR_Stack_Layout_Label *label,
+ const char *name, bool *succeeded)
+{
+ const MR_Stack_Layout_Vars *vars;
+ int i;
+
+ vars = &label->MR_sll_var_info;
+ if (vars->MR_slvs_names == NULL) {
+ *succeeded = FALSE;
+ return 0;
+ }
+
+ for (i = 0; i < label->MR_sll_var_count; i++) {
+ if (streq(vars->MR_slvs_names[i], name)) {
+ return MR_trace_lookup_live_lval_base(
+ vars->MR_slvs_pairs[i].MR_slv_locn,
+ TRUE, MR_saved_sp(MR_saved_regs), MR_saved_curfr(MR_saved_regs), succeeded);
+ }
+ }
+
+ *succeeded = FALSE;
+ return 0;
+}
+
+static void
+MR_ensure_room_for_spy_point(void)
+{
+ if (MR_spy_point_next >= MR_spy_point_max) {
+ if (MR_spy_point_max == 0) {
+ MR_spy_point_max = MR_INIT_SPY_POINTS;
+ MR_spy_points = checked_malloc(
+ MR_spy_point_max *
+ sizeof(MR_Spy_Point *));
+ } else {
+ MR_spy_point_max *= 2;
+ MR_spy_points = checked_realloc(MR_spy_points,
+ MR_spy_point_max *
+ sizeof(MR_Spy_Point *));
+ }
+ }
+}
+
+static void
+MR_print_spy_point(int i)
+{
+ printf("%2d: %1s %5s %9s %s:%s/%ld-%ld\n",
+ i,
+ MR_spy_points[i]->spy_enabled ? "+" : "-",
+ MR_spy_action_string(MR_spy_points[i]->spy_action),
+ MR_spy_when_string(MR_spy_points[i]->spy_when),
+ MR_spy_points[i]->spy_proc->MR_sle_def_module,
+ MR_spy_points[i]->spy_proc->MR_sle_name,
+ (long) MR_spy_points[i]->spy_proc->MR_sle_arity,
+ (long) MR_spy_points[i]->spy_proc->MR_sle_mode);
+}
+
+static void
MR_trace_list_vars(const MR_Stack_Layout_Label *top_layout, int ancestor_level)
{
const MR_Stack_Layout_Label *level_layout;
@@ -459,10 +1026,10 @@
var_count = (int) level_layout->MR_sll_var_count;
if (var_count < 0) {
- printf("mtrace: there is no information about live variables\n");
+ printf("mdb: there is no information about live variables\n");
return;
} else if (var_count == 0) {
- printf("mtrace: there are no live variables\n");
+ printf("mdb: there are no live variables\n");
return;
}
@@ -497,10 +1064,10 @@
var_count = (int) level_layout->MR_sll_var_count;
if (var_count < 0) {
- printf("mtrace: there is no information about live variables\n");
+ printf("mdb: there is no information about live variables\n");
return;
} else if (which_var >= var_count) {
- printf("mtrace: there is no such variable\n");
+ printf("mdb: there is no such variable\n");
return;
}
@@ -541,10 +1108,10 @@
var_count = (int) level_layout->MR_sll_var_count;
if (var_count < 0) {
- printf("mtrace: there is no information about live variables\n");
+ printf("mdb: there is no information about live variables\n");
return;
} else if (var_count == 0) {
- printf("mtrace: there are no live variables\n");
+ printf("mdb: there are no live variables\n");
return;
}
@@ -590,9 +1157,9 @@
/* the variable names from the prompt. */
if (name != NULL) {
- printf("%10s%-21s\t", "", name);
+ printf("%7s%-21s\t", "", name);
} else {
- printf("%10s%-21s\t", "", "anonymous variable");
+ printf("%7s%-21s\t", "", "anonymous variable");
}
fflush(stdout);
@@ -637,27 +1204,6 @@
printf("\n");
}
-bool
-MR_event_matches_spy_point(const MR_Stack_Layout_Label *layout)
-{
- const MR_Stack_Layout_Entry *entry;
- int i;
-
- entry = layout->MR_sll_entry;
-
- for (i = 0; i < MR_next_spy_point; i++) {
- if (MR_spy_points[i].enabled
- && streq(MR_spy_points[i].pred_name,
- entry->MR_sle_name)
- && streq(MR_spy_points[i].module_name,
- entry->MR_sle_def_module)) {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
/*
** Is the string pointed to by word an integer?
** If yes, return its value in *value.
@@ -684,22 +1230,109 @@
/*
** Given a text line, break it up into words composed of non-space characters
-** separated by space characters. Make each word a NULL-terminated string
-** (overwriting some spaces in the line array in the process), return pointers
-** to them in the words array, and return the number of words in the return
-** value of the function.
+** separated by space characters. Make each word a NULL-terminated string,
+** overwriting some spaces in the line array in the process.
+**
+** If the first word is a number but the second is not, swap the two.
+** If the first word has a number prefix, separate it out.
**
-** This function assumes that the words array is as long as necessary.
-** This can be (and is) ensured by making the words array have one element
-** for every two characters in the line array (since you need at least one
-** non-space and one space or newline character per word).
+** On return *words_ptr will point to an array of strings, with space for
+** *words_max strings. The number of strings (words) filled in will be
+** given by the return value.
+**
+** The lifetime of the elements of the *words_ptr array expires when
+** the line array is freed or further modified or when MR_trace_parse_line
+** is called again, whichever comes first.
+*/
+
+/* If a number is more than 80 chars long, the user is in trouble. */
+#define MR_NUMBER_LEN 80
+
+static const char *
+MR_trace_parse_line(char *line, char ***words_ptr, int *word_count_ptr)
+{
+ char **raw_words;
+ int raw_words_max;
+ char raw_words_count;
+ static char count_buf[MR_NUMBER_LEN];
+ char *s;
+ int i;
+
+ /*
+ ** Handle a possible number prefix on the first word on the line,
+ ** separating it out into a word on its own.
+ */
+
+ raw_words_count = MR_trace_break_into_words(line,
+ &raw_words, &raw_words_max);
+
+ if (raw_words_count > 0 && MR_isdigit(*raw_words[0])) {
+ i = 0;
+ s = raw_words[0];
+ while (MR_isdigit(*s)) {
+ if (i >= MR_NUMBER_LEN) {
+ return "too large a number";
+ }
+
+ count_buf[i] = *s;
+ i++;
+ s++;
+ }
+
+ count_buf[i] = '\0';
+
+ if (*s != '\0') {
+ /* Only part of the first word constitutes a number. */
+ /* Put it in an extra word at the start. */
+
+ if (raw_words_count + 1 >= raw_words_max) {
+ raw_words_max += 1;
+ raw_words = checked_realloc(raw_words,
+ raw_words_max
+ * sizeof(char **));
+ }
+
+ for (i = raw_words_count; i > 0; i--) {
+ raw_words[i] = raw_words[i-1];
+ }
+
+ raw_words[0] = count_buf;
+ raw_words[1] = s;
+ raw_words_count++;
+ }
+ }
+
+ /*
+ ** If the first word is a number, try to exchange it
+ ** with the command word, to put the command word first.
+ */
+
+ if (raw_words_count > 1 && MR_trace_is_number(raw_words[0], &i)
+ && ! MR_trace_is_number(raw_words[1], &i)) {
+ s = raw_words[0];
+ raw_words[0] = raw_words[1];
+ raw_words[1] = s;
+ }
+
+ *words_ptr = raw_words;
+ *word_count_ptr = raw_words_count;
+ return NULL;
+}
+
+/*
+** Given a text line, break it up into words composed of non-space characters
+** separated by space characters. Make each word a NULL-terminated string,
+** overwriting some spaces in the line array in the process.
**
-** This function also assumes that line[] is guaranteed to have a white space
-** character (which will usually be a newline) just before the null character.
+** On return *words_ptr will point to an array of strings, with space for
+** *words_max strings. The number of strings (words) filled in will be
+** given by the return value.
*/
+#define INIT_WORD_COUNT 20
+
static int
-MR_trace_break_into_words(char line[], char *words[])
+MR_trace_break_into_words(char *line, char ***words_ptr, int *words_max)
{
int token_number;
int char_pos;
@@ -708,6 +1341,9 @@
token_number = 0;
char_pos = 0;
+ *words_max = INIT_WORD_COUNT;
+ *words_ptr = checked_malloc(*words_max * sizeof(char **));
+
/* each iteration of this loop processes one token, or end of line */
for (;;) {
while (line[char_pos] != '\0' && MR_isspace(line[char_pos])) {
@@ -718,56 +1354,134 @@
return token_number;
}
- words[token_number] = line + char_pos;
+ if (token_number >= *words_max) {
+ *words_max *= 2;
+ *words_ptr = checked_realloc(*words_ptr,
+ *words_max * sizeof(char **));
+ }
+
+ (*words_ptr)[token_number] = line + char_pos;
+
while (line[char_pos] != '\0' && !MR_isspace(line[char_pos])) {
char_pos++;
}
- line[char_pos] = '\0';
- char_pos++;
+ if (line[char_pos] != '\0') {
+ line[char_pos] = '\0';
+ char_pos++;
+ }
+
token_number++;
}
}
/*
-** Read a line from a file. If the line does not fit in the array,
-** read the whole line anyway but store only the first part.
-** If the last line ends without a newline, insert it.
-** Return the length of the (possibly truncated) line.
-** This will be zero only if getline is called at EOF;
-** it will be one only if line contains a single newline;
-** otherwise it will contain a newline terminated string.
+** Read a line from a file, and return a pointer to a malloc'd buffer
+** holding the line (without the final newline). If EOF occurs on a
+** nonempty line, treat the EOF as a newline; if EOF occurs on an empty
+** line, return NULL.
*/
-static int
-MR_trace_getline(FILE *file, char line[], int line_max)
+#define INIT_BUF_LEN 80
+
+static char *
+MR_trace_getline(FILE *file)
{
- int c, i;
+ char *buf;
+ int max;
+ int c;
+ int i;
+
+ max = INIT_BUF_LEN;
+ buf = checked_malloc(max * sizeof(char));
i = 0;
while ((c = getc(file)) != EOF && c != '\n') {
- if (i < line_max-1) {
- line[i++] = c;
+ if (i >= max) {
+ max *= 2;
+ buf = checked_realloc(buf, max * sizeof(char));
}
+
+ buf[i++] = c;
}
if (c == '\n' || i > 0) {
- line[i++] = '\n';
+ buf[i] = '\0';
+ return buf;
+ } else {
+ free(buf);
+ return NULL;
}
+}
- line[i] = '\0';
- return i;
+void
+MR_trace_event_internal_report(MR_Trace_Cmd_Info *cmd,
+ const MR_Stack_Layout_Label *layout, MR_Trace_Port port,
+ int seqno, int depth, const char *path)
+{
+ char *buf;
+ int i;
+
+ if (MR_scroll_control && MR_scroll_next >= MR_scroll_limit) {
+ printf("--more--");
+ fflush(stdout);
+
+ try_again:
+ buf = MR_trace_getline(stdin);
+ if (buf != NULL) {
+ for (i = 0; buf[i] != '\0' && MR_isspace(buf[i]); i++)
+ ;
+
+ if (buf[i] != '\0' && !MR_isspace(buf[i])) {
+ switch (buf[i]) {
+ case 'a':
+ cmd->MR_trace_print_level =
+ MR_PRINT_LEVEL_ALL;
+ break;
+
+ case 'n':
+ cmd->MR_trace_print_level =
+ MR_PRINT_LEVEL_NONE;
+ break;
+
+ case 's':
+ cmd->MR_trace_print_level =
+ MR_PRINT_LEVEL_SOME;
+ break;
+
+ case 'q':
+ free(buf);
+ MR_trace_event_internal(cmd,
+ layout, port, seqno,
+ depth, path);
+ break;
+
+ default:
+ printf("unknown command, "
+ "try again\n");
+ free(buf);
+ goto try_again;
+ }
+ }
+
+ free(buf);
+ }
+
+ MR_scroll_next = 1;
+ }
+
+ MR_trace_event_print_internal_report(layout, port, seqno, depth, path);
+ MR_scroll_next++;
}
void
-MR_trace_event_internal_report(const MR_Stack_Layout_Label *layout,
- MR_trace_port port, int seqno, int depth, const char *path)
+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 ",
(long) MR_trace_event_number, (long) seqno, (long) depth);
MR_trace_print_port(port);
- MR_trace_print_detism(layout->MR_sll_entry->MR_sle_detism);
/*
** The following should be a full identification of the procedure
@@ -775,16 +1489,11 @@
** not interested in tracing compiler-generated procedures.
*/
- printf("%s:%s/%ld-%ld %s\n",
- layout->MR_sll_entry->MR_sle_def_module,
- layout->MR_sll_entry->MR_sle_name,
- (long) layout->MR_sll_entry->MR_sle_arity,
- (long) layout->MR_sll_entry->MR_sle_mode,
- path);
+ MR_print_proc_id(stdout, layout->MR_sll_entry, path);
}
static void
-MR_trace_print_port(MR_trace_port port)
+MR_trace_print_port(MR_Trace_Port port)
{
switch (port) {
case MR_PORT_CALL:
@@ -830,85 +1539,35 @@
}
static void
-MR_trace_print_detism(Word detism)
-{
- switch ((int) detism) {
- case MR_DETISM_DET:
- printf("DET ");
- break;
-
- case MR_DETISM_SEMI:
- printf("SEMI ");
- break;
-
- case MR_DETISM_NON:
- printf("NON ");
- break;
-
- case MR_DETISM_MULTI:
- printf("MUL ");
- break;
-
- case MR_DETISM_ERRONEOUS:
- printf("ERR ");
- break;
-
- case MR_DETISM_FAILURE:
- printf("FAIL ");
- break;
-
- case MR_DETISM_CCNON:
- printf("CCNON ");
- break;
-
- case MR_DETISM_CCMULTI:
- printf("CCMUL ");
- break;
-
- default:
- printf("BAD DETERMINISM\n");
- break;
- }
-}
-
-static void
MR_trace_help(void)
{
- printf("valid commands are:\n"
- "a, EOF:\t\t"
- "\tabort the current execution.\n"
- "b <module> <name>:"
- "\tset a breakpoint on the predicate\n"
- "\t\t\tor function <module>:<name>.\n"
- "c:\t\t"
- "\tcontinue to end of program, not printing the trace.\n"
- "C:\t\t"
- "\tcontinue to end of program, printing the trace.\n"
- "f:\t\t"
- "\tfinish this call, not printing the trace.\n"
- "F:\t\t"
- "\tfinish this call, printing the trace.\n"
- "<N> g:\t\t"
- "\tgo to event #N, not printing the trace.\n"
- "<N> G:\t\t"
- "\tgo to event #N, printing the trace.\n"
- "v:\t\t"
- "\tlist the names of the variables live at this point.\n"
- "l <n>:\t\t"
- "\tset ancestor level to <n>\n"
- "p <n>:\t\t"
- "\tprint variable #n (or all vars if <n> is '*')\n"
- "r:\t\t"
- "\tcontinue until forward execution is resumed.\n"
- "[<N>] [s]:\t"
- "\tskip N events, not printing the trace (default: N=1).\n"
- "[<N>] S:\t"
- "\tskip N events, printing the trace (default: N=1).\n"
- "?:\t\t"
- "\tlist all the breakpoints.\n"
- "+ <N>:\t\t"
- "\tenable breakpoint #N.\n"
- "- <N>:\t\t"
- "\tdisable breakpoint #N.\n"
- );
+ printf("valid commands are:\n");
+ printf(" %s\n", step_usage);
+ printf(" %s\n", goto_usage);
+ printf(" %s\n", finish_usage);
+ printf(" %s\n", forward_usage);
+ printf(" %s\n", continue_usage);
+ printf(" %s\n", restart_usage);
+ printf(" %s\n", level_usage);
+ printf(" %s\n", up_usage);
+ printf(" %s\n", down_usage);
+ printf(" %s\n", vars_usage);
+ printf(" %s\n", print_usage);
+ printf(" %s\n", stack_usage);
+ printf(" %s\n", stack_regs_usage);
+ printf(" %s\n", break_usage);
+ printf(" %s\n", enable_usage);
+ printf(" %s\n", disable_usage);
+ printf(" %s\n", register_usage);
+ printf(" %s\n", module_table_usage);
+#ifdef MR_TRACE_HISTOGRAM
+ printf(" %s\n", histogram_all_usage);
+ printf(" %s\n", histogram_exp_usage);
+ printf(" %s\n", clear_histogram_usage);
+#endif
+ printf(" %s\n", printlevel_usage);
+ printf(" %s\n", scroll_usage);
+ printf(" %s\n", echo_usage);
+ printf(" %s\n", help_usage);
+ printf(" %s\n", quit_usage);
}
Index: runtime/mercury_trace_internal.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_internal.h,v
retrieving revision 1.1
diff -u -u -r1.1 mercury_trace_internal.h
--- mercury_trace_internal.h 1998/05/16 07:28:28 1.1
+++ mercury_trace_internal.h 1998/07/06 10:01:13
@@ -7,16 +7,14 @@
#ifndef MERCURY_TRACE_INTERNAL_H
#define MERCURY_TRACE_INTERNAL_H
-extern void MR_trace_event_internal(MR_trace_cmd_info *cmd,
+extern void MR_trace_event_internal(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout,
- MR_trace_port port, int seqno, int depth,
+ MR_Trace_Port port, int seqno, int depth,
const char *path);
-extern void MR_trace_event_internal_report(
+extern void MR_trace_event_internal_report(MR_Trace_Cmd_Info *cmd,
const MR_Stack_Layout_Label *layout,
- MR_trace_port port, int seqno, int depth,
+ MR_Trace_Port port, int seqno, int depth,
const char *path);
-
-extern bool MR_event_matches_spy_point(const MR_Stack_Layout_Label *layout);
#endif /* MERCURY_TRACE_INTERNAL_H */
Index: runtime/mercury_trace_spy.c
===================================================================
RCS file: mercury_trace_spy.c
diff -N mercury_trace_spy.c
--- /dev/null Wed May 28 10:49:58 1997
+++ mercury_trace_spy.c Sat Jul 4 20:43:51 1998
@@ -0,0 +1,204 @@
+/*
+** Copyright (C) 1998 The University of Melbourne.
+** This file may only be copied under the terms of the GNU Library General
+** Public License - see the file COPYING.LIB in the Mercury distribution.
+*/
+
+/*
+** This file contains code to manage spy points for both
+** the internal and external debuggers.
+**
+** Main author: Zoltan Somogyi.
+*/
+
+#include "mercury_imp.h"
+#include "mercury_trace_base.h"
+#include "mercury_trace.h"
+#include "mercury_trace_spy.h"
+
+typedef struct {
+ const MR_Stack_Layout_Entry *spy_proc;
+ MR_Spy_Point *spy_points;
+} MR_Spied_Proc;
+
+static MR_Spied_Proc *MR_spied_procs;
+static int MR_spied_procs_next = 0;
+static int MR_spied_procs_max = 0;
+
+#define INIT_SPY_TABLE_SIZE 10
+
+bool
+MR_event_matches_spy_point(const MR_Stack_Layout_Label *layout,
+ MR_Trace_Port port, MR_Spy_Action *action_ptr)
+{
+ const MR_Stack_Layout_Entry *entry;
+ int lo;
+ int hi;
+ int mid;
+ int i;
+ bool found;
+ bool enabled;
+ MR_Spy_Point *point;
+ MR_Spy_Action action;
+
+ entry = layout->MR_sll_entry;
+
+ lo = 0;
+ hi = MR_spied_procs_next-1;
+ found = FALSE;
+ while (lo <= hi) {
+ mid = (lo + hi) / 2;
+ if (MR_spied_procs[mid].spy_proc == entry) {
+ found = TRUE;
+ break;
+ } else if (MR_spied_procs[mid].spy_proc < entry) {
+ lo = mid + 1;
+ } else {
+ hi = mid - 1;
+ }
+ }
+
+ if (! found) {
+ return FALSE;
+ }
+
+ enabled = FALSE;
+ action = MR_SPY_PRINT;
+ for (point = MR_spied_procs[mid].spy_points; point != NULL;
+ point = point->spy_next) {
+ if (! point->spy_enabled) {
+ continue;
+ }
+
+ switch (point->spy_when) {
+
+ case MR_SPY_ALL:
+ enabled = TRUE;
+ action = max(action, point->spy_action);
+
+ case MR_SPY_ENTRY:
+ if (MR_port_is_entry(port)) {
+ enabled = TRUE;
+ action = max(action, point->spy_action);
+ } else {
+ continue;
+ }
+
+ case MR_SPY_INTERFACE:
+ if (MR_port_is_interface(port)) {
+ enabled = TRUE;
+ action = max(action, point->spy_action);
+ } else {
+ continue;
+ }
+
+ case MR_SPY_SPECIFIC:
+ if (layout == point->spy_label) {
+ enabled = TRUE;
+ action = max(action, point->spy_action);
+ } else {
+ continue;
+ }
+
+ default:
+ fatal_error("bad spy point when in "
+ "MR_event_matches_spy_point");
+ }
+ }
+
+ if (enabled) {
+ *action_ptr = action;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static bool MR_need_move(int i, const MR_Stack_Layout_Entry *entry);
+
+MR_Spy_Point *
+MR_add_spy_point(MR_Spy_When when, MR_Spy_Action action,
+ const MR_Stack_Layout_Entry *entry, const MR_Stack_Layout_Label *label,
+ const char *path)
+{
+ MR_Spy_Point *point;
+ int lo;
+ int hi;
+ int mid;
+ bool found;
+
+ lo = 0;
+ hi = MR_spied_procs_next-1;
+ found = FALSE;
+ while (lo <= hi) {
+ mid = (lo + hi) / 2;
+ if (MR_spied_procs[mid].spy_proc == entry) {
+ found = TRUE;
+ break;
+ } else if (MR_spied_procs[mid].spy_proc < entry) {
+ lo = mid + 1;
+ } else {
+ hi = mid - 1;
+ }
+ }
+
+ if (! found) {
+ int i;
+
+ /* make sure the MR_spied_procs array is big enough */
+ if (MR_spied_procs_next >= MR_spied_procs_max) {
+ if (MR_spied_procs_max == 0) {
+ MR_spied_procs_max = INIT_SPY_TABLE_SIZE;
+ MR_spied_procs = checked_malloc(
+ MR_spied_procs_max *
+ sizeof(MR_Spied_Proc));
+ } else {
+ MR_spied_procs_max *= 2;
+ MR_spied_procs = checked_realloc(
+ MR_spied_procs,
+ MR_spied_procs_max *
+ sizeof(MR_Spied_Proc));
+ }
+ }
+
+ /* move all the spied procs above the one to be inserted */
+ for (i = MR_spied_procs_next - 1;
+ i >= 0 && MR_need_move(i, entry); i--) {
+ MR_spied_procs[i+1] = MR_spied_procs[i];
+ }
+
+ MR_spied_procs_next++;
+ mid = i + 1;
+
+ /* insert the newly spied proc */
+ MR_spied_procs[mid].spy_proc = entry;
+ MR_spied_procs[mid].spy_points = NULL;
+ }
+
+ /* insert the spy point at the head of the list for the proc */
+ point = checked_malloc(sizeof(MR_Spy_Point));
+ point->spy_when = when;
+ point->spy_enabled = TRUE;
+ point->spy_action = action;
+ point->spy_proc = entry;
+ point->spy_label = label;
+ point->spy_next = MR_spied_procs[mid].spy_points;
+ MR_spied_procs[mid].spy_points = point;
+
+ return point;
+}
+
+/*
+** The only reason why MR_need_move is function is that
+** gcc gets an internal error ("fixed or forbidden register was spilled")
+** if it isn't a function.
+**/
+
+static bool
+MR_need_move(int i, const MR_Stack_Layout_Entry *entry)
+{
+ if (MR_spied_procs[i].spy_proc > entry)
+ return TRUE;
+ else
+ return FALSE;
+}
Index: runtime/mercury_trace_spy.h
===================================================================
RCS file: mercury_trace_spy.h
diff -N mercury_trace_spy.h
--- /dev/null Wed May 28 10:49:58 1997
+++ mercury_trace_spy.h Sun Jul 5 14:02:53 1998
@@ -0,0 +1,56 @@
+/*
+** Copyright (C) 1998 The University of Melbourne.
+** This file may only be copied under the terms of the GNU Library General
+** Public License - see the file COPYING.LIB in the Mercury distribution.
+*/
+
+/*
+** This file contains the declarations of the types and functions that
+** the internal and external debuggers can use to manipulate spy points.
+**
+** Main author: Zoltan Somogyi.
+*/
+
+#ifndef MERCURY_TRACE_SPY_H
+#define MERCURY_TRACE_SPY_H
+
+typedef enum {
+ MR_SPY_PRINT, MR_SPY_STOP
+} MR_Spy_Action;
+
+#define MR_spy_action_string(a) ((a == MR_SPY_STOP) ? "stop" : \
+ (a == MR_SPY_PRINT) ? "print" : \
+ "weird spy action")
+
+typedef enum {
+ MR_SPY_ALL, MR_SPY_INTERFACE, MR_SPY_ENTRY, MR_SPY_SPECIFIC
+} MR_Spy_When;
+
+#define MR_spy_when_string(w) ((w == MR_SPY_ALL) ? "all" : \
+ (w == MR_SPY_INTERFACE) ? "interface":\
+ (w == MR_SPY_ENTRY) ? "entry" : \
+ (w == MR_SPY_SPECIFIC) ? "specific" : \
+ "weird spy when")
+
+typedef struct struct_mr_spy_point MR_Spy_Point;
+
+struct struct_mr_spy_point {
+ MR_Spy_When spy_when;
+ bool spy_enabled;
+ MR_Spy_Action spy_action;
+ const MR_Stack_Layout_Entry *spy_proc;
+ const MR_Stack_Layout_Label *spy_label; /* if MR_SPY_SPECIFIC */
+ MR_Spy_Point *spy_next;
+};
+
+extern bool MR_event_matches_spy_point(const MR_Stack_Layout_Label
+ *layout, MR_Trace_Port port,
+ MR_Spy_Action *action);
+
+extern MR_Spy_Point *MR_add_spy_point(MR_Spy_When when,
+ MR_Spy_Action action,
+ const MR_Stack_Layout_Entry *entry,
+ const MR_Stack_Layout_Label *label,
+ const char *path);
+
+#endif /* not MERCURY_TRACE_SPY_H */
Index: runtime/mercury_trace_tables.c
===================================================================
RCS file: mercury_trace_tables.c
diff -N mercury_trace_tables.c
--- /dev/null Wed May 28 10:49:58 1997
+++ mercury_trace_tables.c Mon Jul 6 17:32:09 1998
@@ -0,0 +1,420 @@
+/*
+** Copyright (C) 1998 The University of Melbourne.
+** This file may only be copied under the terms of the GNU Library General
+** Public License - see the file COPYING.LIB in the Mercury distribution.
+*/
+
+/*
+** This file manages a table listing the debuggable modules of the program,
+** and subsidiary tables listing the procedures of each of those modules.
+**
+** Main author: Zoltan Somogyi.
+*/
+
+#include "mercury_imp.h"
+#include "mercury_label.h"
+#include "mercury_trace_tables.h"
+#include <stdio.h>
+
+static MR_Module_Info *MR_module_infos;
+static int MR_module_info_next = 0;
+static int MR_module_info_max = 0;
+
+#define INIT_MODULE_TABLE_SIZE 10
+
+static void MR_register_from_internal_label(const void *info);
+static void MR_ensure_proc_node_is_present(MR_Module_Info *module,
+ const MR_Stack_Layout_Entry *entry);
+static MR_Module_Info *MR_search_module_info(const char *name);
+static MR_Module_Info *MR_insert_module_info(const char *name);
+static MR_Module_Info *MR_ensure_module_info_is_present(const char *name);
+
+void
+MR_register_all_modules_and_procs(FILE *fp)
+{
+ static bool done = FALSE;
+
+ if (! done) {
+ fprintf(fp, "Registering all debuggable procedures... ");
+ fflush(fp);
+ do_init_modules();
+ MR_process_all_internal_labels(MR_register_from_internal_label);
+ done = TRUE;
+ fprintf(fp, "done\n");
+ }
+}
+
+static void
+MR_register_from_internal_label(const void *info)
+{
+ const MR_Stack_Layout_Label *label;
+ const MR_Stack_Layout_Entry *entry;
+ MR_Module_Info *module;
+
+ label = ((const MR_Internal *) info)->i_layout;
+
+ if (label == NULL) {
+ /* some labels have no layout structure */
+ return;
+ }
+
+ if (label->MR_sll_entry == NULL) {
+ /* some hand-crafted label structures have no entry */
+ return;
+ }
+
+ entry = label->MR_sll_entry;
+ module = MR_ensure_module_info_is_present(entry->MR_sle_def_module);
+ MR_ensure_proc_node_is_present(module, entry);
+}
+
+static void
+MR_ensure_proc_node_is_present(MR_Module_Info *module,
+ const MR_Stack_Layout_Entry *entry)
+{
+ MR_Proc_Node *cur;
+
+ for (cur = module->MR_module_procs; cur != NULL;
+ cur = cur->MR_proc_next) {
+ if (entry == cur->MR_proc_layout) {
+ return;
+ }
+ }
+
+ cur = checked_malloc(sizeof(MR_Proc_Node));
+ cur->MR_proc_layout = entry;
+ cur->MR_proc_next = module->MR_module_procs;
+ module->MR_module_procs = cur;
+}
+
+static MR_Module_Info *
+MR_search_module_info(const char *name)
+{
+ int lo;
+ int hi;
+ int mid;
+ int diff;
+
+ lo = 0;
+ hi = MR_module_info_next-1;
+ while (lo <= hi) {
+ mid = (lo + hi) / 2;
+ diff = strcmp(MR_module_infos[mid].MR_module_name, name);
+ if (diff == 0) {
+ return &MR_module_infos[mid];
+ } else if (diff < 0) {
+ lo = mid + 1;
+ } else {
+ hi = mid - 1;
+ }
+ }
+
+ return NULL;
+}
+
+static MR_Module_Info *
+MR_insert_module_info(const char *name)
+{
+ int i;
+
+ /* make sure the MR_module_infos array is big enough */
+ if (MR_module_info_next >= MR_module_info_max) {
+ if (MR_module_info_max == 0) {
+ MR_module_info_max = INIT_MODULE_TABLE_SIZE;
+ MR_module_infos = checked_malloc(
+ MR_module_info_max *
+ sizeof(MR_Module_Info));
+ } else {
+ MR_module_info_max *= 2;
+ MR_module_infos = checked_realloc(
+ MR_module_infos,
+ MR_module_info_max *
+ sizeof(MR_Module_Info));
+ }
+ }
+
+ /* move all the spied procs above the one to be inserted */
+ for (i = MR_module_info_next - 1;
+ i >= 0 &&
+ (strcmp(name, MR_module_infos[i].MR_module_name) < 0);
+ i--) {
+ MR_module_infos[i+1] = MR_module_infos[i];
+ }
+
+ MR_module_info_next++;
+ MR_module_infos[i + 1].MR_module_name = name;
+ MR_module_infos[i + 1].MR_module_procs = NULL;
+ return &MR_module_infos[i + 1];
+}
+
+static MR_Module_Info *
+MR_ensure_module_info_is_present(const char *name)
+{
+ MR_Module_Info *module;
+
+ module = MR_search_module_info(name);
+ if (module != NULL) {
+ return module;
+ } else {
+ return MR_insert_module_info(name);
+ }
+}
+
+void
+MR_dump_module_tables(FILE *fp)
+{
+ const MR_Proc_Node *cur;
+ int i;
+
+ for (i = 0; i < MR_module_info_next; i++) {
+ fprintf(fp, "====================\n");
+ fprintf(fp, "module %s\n", MR_module_infos[i].MR_module_name);
+ fprintf(fp, "====================\n");
+ for (cur = MR_module_infos[i].MR_module_procs; cur != NULL;
+ cur = cur->MR_proc_next) {
+ MR_print_proc_id(fp, cur->MR_proc_layout, NULL);
+ }
+ }
+}
+
+const MR_Stack_Layout_Entry *
+MR_search_for_module_proc(const char *module_name, const char *pred_name,
+ bool *unique)
+{
+ MR_Module_Info *module;
+ MR_Proc_Node *cur;
+ const MR_Stack_Layout_Entry *entry;
+ const MR_Stack_Layout_Entry *cur_entry;
+
+ module = MR_search_module_info(module_name);
+ if (module == NULL) {
+ return NULL;
+ }
+
+ entry = NULL;
+ *unique = TRUE;
+
+ for (cur = module->MR_module_procs; cur != NULL;
+ cur = cur->MR_proc_next) {
+ cur_entry = cur->MR_proc_layout;
+ if (streq(pred_name, cur_entry->MR_sle_name)) {
+ if (entry == NULL) {
+ entry = cur_entry;
+ } else {
+ *unique = FALSE;
+ }
+ }
+ }
+
+ return entry;
+}
+
+const MR_Stack_Layout_Entry *
+MR_search_for_module_proc_arity(const char *module_name, const char *pred_name,
+ int arity, bool *unique)
+{
+ MR_Module_Info *module;
+ MR_Proc_Node *cur;
+ const MR_Stack_Layout_Entry *entry;
+ const MR_Stack_Layout_Entry *cur_entry;
+
+ module = MR_search_module_info(module_name);
+ if (module == NULL) {
+ return NULL;
+ }
+
+ entry = NULL;
+ *unique = TRUE;
+
+ for (cur = module->MR_module_procs; cur != NULL;
+ cur = cur->MR_proc_next) {
+ cur_entry = cur->MR_proc_layout;
+ if (streq(pred_name, cur_entry->MR_sle_name) &&
+ arity == cur_entry->MR_sle_arity) {
+ if (entry == NULL) {
+ entry = cur_entry;
+ } else {
+ *unique = FALSE;
+ }
+ }
+ }
+
+ return entry;
+}
+
+const MR_Stack_Layout_Entry *
+MR_search_for_module_proc_arity_mode(const char *module_name,
+ const char *pred_name, int arity, int mode, bool *unique)
+{
+ MR_Module_Info *module;
+ MR_Proc_Node *cur;
+ const MR_Stack_Layout_Entry *entry;
+ const MR_Stack_Layout_Entry *cur_entry;
+
+ module = MR_search_module_info(module_name);
+ if (module == NULL) {
+ return NULL;
+ }
+
+ entry = NULL;
+ *unique = TRUE;
+
+ for (cur = module->MR_module_procs; cur != NULL;
+ cur = cur->MR_proc_next) {
+ cur_entry = cur->MR_proc_layout;
+ if (streq(pred_name, cur_entry->MR_sle_name) &&
+ arity == cur_entry->MR_sle_arity &&
+ mode == cur_entry->MR_sle_mode) {
+ if (entry == NULL) {
+ entry = cur_entry;
+ } else {
+ *unique = FALSE;
+ }
+ }
+ }
+
+ return entry;
+}
+
+const MR_Stack_Layout_Entry *
+MR_search_for_module_proc_arity_mode_pf(const char *module_name,
+ const char *pred_name, int arity, int mode, MR_PredFunc predfunc,
+ bool *unique)
+{
+ MR_Module_Info *module;
+ MR_Proc_Node *cur;
+ const MR_Stack_Layout_Entry *entry;
+ const MR_Stack_Layout_Entry *cur_entry;
+
+ module = MR_search_module_info(module_name);
+ if (module == NULL) {
+ return NULL;
+ }
+
+ entry = NULL;
+ *unique = TRUE;
+
+ for (cur = module->MR_module_procs; cur != NULL;
+ cur = cur->MR_proc_next) {
+ cur_entry = cur->MR_proc_layout;
+ if (streq(pred_name, cur_entry->MR_sle_name) &&
+ arity == cur_entry->MR_sle_arity &&
+ mode == cur_entry->MR_sle_mode &&
+ predfunc == cur_entry->MR_sle_pred_or_func) {
+ if (entry == NULL) {
+ entry = cur_entry;
+ } else {
+ *unique = FALSE;
+ }
+ }
+ }
+
+ return entry;
+}
+
+void
+MR_process_all_module_proc(void f(const MR_Stack_Layout_Entry *),
+ const char *module_name, const char *pred_name)
+{
+ MR_Module_Info *module;
+ MR_Proc_Node *cur;
+ const MR_Stack_Layout_Entry *entry;
+ const MR_Stack_Layout_Entry *cur_entry;
+
+ module = MR_search_module_info(module_name);
+ if (module == NULL) {
+ return;
+ }
+
+ entry = NULL;
+
+ for (cur = module->MR_module_procs; cur != NULL;
+ cur = cur->MR_proc_next) {
+ cur_entry = cur->MR_proc_layout;
+ if (streq(pred_name, cur_entry->MR_sle_name)) {
+ f(cur_entry);
+ }
+ }
+}
+
+void
+MR_process_all_module_proc_arity(void f(const MR_Stack_Layout_Entry *),
+ const char *module_name, const char *pred_name, int arity)
+{
+ MR_Module_Info *module;
+ MR_Proc_Node *cur;
+ const MR_Stack_Layout_Entry *entry;
+ const MR_Stack_Layout_Entry *cur_entry;
+
+ module = MR_search_module_info(module_name);
+ if (module == NULL) {
+ return;
+ }
+
+ entry = NULL;
+
+ for (cur = module->MR_module_procs; cur != NULL;
+ cur = cur->MR_proc_next) {
+ cur_entry = cur->MR_proc_layout;
+ if (streq(pred_name, cur_entry->MR_sle_name) &&
+ arity == cur_entry->MR_sle_arity) {
+ f(cur_entry);
+ }
+ }
+}
+
+void
+MR_process_all_module_proc_arity_mode(void f(const MR_Stack_Layout_Entry *),
+ const char *module_name, const char *pred_name, int arity, int mode)
+{
+ MR_Module_Info *module;
+ MR_Proc_Node *cur;
+ const MR_Stack_Layout_Entry *entry;
+ const MR_Stack_Layout_Entry *cur_entry;
+
+ module = MR_search_module_info(module_name);
+ if (module == NULL) {
+ return;
+ }
+
+ entry = NULL;
+
+ for (cur = module->MR_module_procs; cur != NULL;
+ cur = cur->MR_proc_next) {
+ cur_entry = cur->MR_proc_layout;
+ if (streq(pred_name, cur_entry->MR_sle_name) &&
+ arity == cur_entry->MR_sle_arity &&
+ mode == cur_entry->MR_sle_mode) {
+ f(cur_entry);
+ }
+ }
+}
+
+void
+MR_process_all_module_proc_arity_mode_pf(void f(const MR_Stack_Layout_Entry *),
+ const char *module_name, const char *pred_name, int arity, int mode,
+ MR_PredFunc predfunc)
+{
+ MR_Module_Info *module;
+ MR_Proc_Node *cur;
+ const MR_Stack_Layout_Entry *entry;
+ const MR_Stack_Layout_Entry *cur_entry;
+
+ module = MR_search_module_info(module_name);
+ if (module == NULL) {
+ return;
+ }
+
+ entry = NULL;
+
+ for (cur = module->MR_module_procs; cur != NULL;
+ cur = cur->MR_proc_next) {
+ cur_entry = cur->MR_proc_layout;
+ if (streq(pred_name, cur_entry->MR_sle_name) &&
+ arity == cur_entry->MR_sle_arity &&
+ mode == cur_entry->MR_sle_mode &&
+ predfunc == cur_entry->MR_sle_pred_or_func) {
+ f(cur_entry);
+ }
+ }
+}
Index: runtime/mercury_trace_tables.h
===================================================================
RCS file: mercury_trace_tables.h
diff -N mercury_trace_tables.h
--- /dev/null Wed May 28 10:49:58 1997
+++ mercury_trace_tables.h Mon Jul 6 14:47:30 1998
@@ -0,0 +1,67 @@
+/*
+** Copyright (C) 1998 The University of Melbourne.
+** This file may only be copied under the terms of the GNU Library General
+** Public License - see the file COPYING.LIB in the Mercury distribution.
+*/
+
+/*
+** This file contains the declarations of the tables that contain
+** the identities of the debuggable modules and their procedures.
+**
+** Main author: Zoltan Somogyi.
+*/
+
+#ifndef MERCURY_TRACE_TABLES_H
+#define MERCURY_TRACE_TABLES_H
+
+#include "mercury_stack_layout.h"
+#include <stdio.h>
+
+typedef struct struct_mr_proc_node MR_Proc_Node;
+
+struct struct_mr_proc_node {
+ const MR_Stack_Layout_Entry *MR_proc_layout;
+ MR_Proc_Node *MR_proc_next;
+};
+
+typedef struct {
+ const char *MR_module_name;
+ MR_Proc_Node *MR_module_procs;
+} MR_Module_Info;
+
+extern void MR_register_all_modules_and_procs(FILE *fp);
+extern void MR_dump_module_tables(FILE *fp);
+
+extern const MR_Stack_Layout_Entry
+ *MR_search_for_module_proc(const char *module_name,
+ const char *pred_name, bool *unique);
+extern const MR_Stack_Layout_Entry
+ *MR_search_for_module_proc_arity(const char
+ *module_name, const char *pred_name,
+ int arity, bool *unique);
+extern const MR_Stack_Layout_Entry
+ *MR_search_for_module_proc_arity_mode(const char
+ *module_name, const char *pred_name,
+ int arity, int mode, bool *unique);
+extern const MR_Stack_Layout_Entry
+ *MR_search_for_module_proc_arity_mode_pf(const char
+ *module_name, const char *pred_name,
+ int arity, int mode, MR_PredFunc predfunc,
+ bool *unique);
+extern void MR_process_all_module_proc(
+ void f(const MR_Stack_Layout_Entry *),
+ const char *module_name, const char *pred_name);
+extern void MR_process_all_module_proc_arity(
+ void f(const MR_Stack_Layout_Entry *),
+ const char *module_name, const char *pred_name,
+ int arity);
+extern void MR_process_all_module_proc_arity_mode(
+ void f(const MR_Stack_Layout_Entry *),
+ const char *module_name, const char *pred_name,
+ int arity, int mode);
+extern void MR_process_all_module_proc_arity_mode_pf(
+ void f(const MR_Stack_Layout_Entry *),
+ const char *module_name, const char *pred_name,
+ int arity, int mode, MR_PredFunc predfunc);
+
+#endif /* not MERCURY_TRACE_TABLES_H */
Index: runtime/mercury_trace_util.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_util.c,v
retrieving revision 1.6
diff -u -u -r1.6 mercury_trace_util.c
--- mercury_trace_util.c 1998/06/18 06:08:14 1.6
+++ mercury_trace_util.c 1998/07/05 06:31:46
@@ -184,6 +184,19 @@
return univ_list;
}
+int
+MR_trace_get_register_number(MR_Live_Lval locn)
+{
+ int locn_num;
+ Word value;
+
+ if (MR_LIVE_LVAL_TYPE(locn) == MR_LVAL_TYPE_R) {
+ return MR_LIVE_LVAL_NUMBER(locn);
+ } else {
+ return -1;
+ }
+}
+
/* if you want to debug this code, you may want to set this var to TRUE */
static bool MR_trace_print_locn = FALSE;
Index: runtime/mercury_trace_util.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_trace_util.h,v
retrieving revision 1.3
diff -u -u -r1.3 mercury_trace_util.h
--- mercury_trace_util.h 1998/06/18 06:08:16 1.3
+++ mercury_trace_util.h 1998/07/05 06:32:11
@@ -18,6 +18,7 @@
Word *base_sp, Word *base_curfr);
extern Word MR_trace_make_var_list(const MR_Stack_Layout_Label *layout);
+extern int MR_trace_get_register_number(MR_Live_Lval locn);
extern Word MR_trace_lookup_live_lval(MR_Live_Lval locn, bool *succeeded);
extern Word MR_trace_lookup_live_lval_base(MR_Live_Lval locn,
bool saved_regs_valid, Word *base_sp, Word *base_curfr,
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.15
diff -u -u -r1.15 mercury_wrapper.c
--- mercury_wrapper.c 1998/07/03 02:35:41 1.15
+++ mercury_wrapper.c 1998/07/03 12:18:52
@@ -710,9 +710,11 @@
#ifndef CONSERVATIVE_GC
heap_zone->max = heap_zone->min;
#endif
+#if 0
detstack_zone->max = detstack_zone->min;
nondetstack_zone->max = nondetstack_zone->min;
#endif
+#endif
time_at_start = MR_get_user_cpu_miliseconds();
time_at_last_stat = time_at_start;
@@ -747,10 +749,12 @@
printf("max heap used: %6ld words\n",
(long) (heap_zone->max - heap_zone->min));
#endif
+ #if 0
printf("max detstack used: %6ld words\n",
(long)(detstack_zone->max - detstack_zone->min));
printf("max nondstack used: %6ld words\n",
(long) (nondetstack_zone->max - nondetstack_zone->min));
+ #endif
}
#endif
Index: runtime/mercury_wrapper.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_wrapper.h,v
retrieving revision 1.9
diff -u -u -r1.9 mercury_wrapper.h
--- mercury_wrapper.h 1998/07/03 05:51:26 1.9
+++ mercury_wrapper.h 1998/07/05 07:29:17
@@ -5,8 +5,8 @@
*/
/*
-** mercury_wrapper.h - defines the interface to wrapper.c.
-** See wrapper.c for documentation.
+** mercury_wrapper.h - defines the interface to mercury_wrapper.c.
+** See mercury_wrapper.c for documentation.
*/
#ifndef MERCURY_WRAPPER_H
@@ -40,7 +40,7 @@
** The address_of_foo pointers are set to the address of
** the corresponding foo.
*/
-extern Code * program_entry_point; /* normally mercury__main_2_0; */
+extern Code *program_entry_point; /* normally mercury__main_2_0; */
extern void (*MR_library_initializer)(void);
extern void (*MR_library_finalizer)(void);
@@ -69,9 +69,9 @@
extern void do_init_modules(void);
-extern const char * progname;
+extern const char *progname;
extern int mercury_argc;
-extern char ** mercury_argv;
+extern char **mercury_argv;
extern int mercury_exit_status;
/* sizes of the data areas, *including* the red zone size */
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
Index: tests/debugger/debugger_regs.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/debugger_regs.inp,v
retrieving revision 1.2
diff -u -u -r1.2 debugger_regs.inp
--- debugger_regs.inp 1998/06/18 06:08:29 1.2
+++ debugger_regs.inp 1998/07/04 12:16:09
@@ -1,4 +1,5 @@
+toggle_echo
-p *
-c
+print *
+continue
Index: tests/debugger/debugger_regs_lib.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/debugger_regs_lib.inp,v
retrieving revision 1.2
diff -u -u -r1.2 debugger_regs_lib.inp
--- debugger_regs_lib.inp 1998/07/03 02:35:58 1.2
+++ debugger_regs_lib.inp 1998/07/04 12:16:29
@@ -1,4 +1,5 @@
+toggle_echo
-p *
-c
+print *
+continue
Index: tests/debugger/interpreter.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/interpreter.inp,v
retrieving revision 1.2
diff -u -u -r1.2 interpreter.inp
--- interpreter.inp 1998/06/18 06:08:32 1.2
+++ interpreter.inp 1998/07/05 02:53:42
@@ -1,13 +1,13 @@
-h
-10s
-v
-p *
-30 g
-p *
-F
-p *
+toggle_echo
+10 step
+vars
+print *
+goto 30
+print *
+finish -a
+print *
-f
+finish
-c
+continue
Index: tests/debugger/interpreter_lib.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/interpreter_lib.inp,v
retrieving revision 1.2
diff -u -u -r1.2 interpreter_lib.inp
--- interpreter_lib.inp 1998/07/03 02:36:01 1.2
+++ interpreter_lib.inp 1998/07/05 02:53:45
@@ -1,14 +1,14 @@
-h
-45s
-v
-p *
-b interpreter_lib database_assert_clause
-c
-p *
-F
-p *
+toggle_echo
+45step
+vars
+print *
+break interpreter_lib database_assert_clause
+continue
+print *
+finish -a
+print *
-f
+finish
-c
+continue -S
Index: tests/debugger/queens.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/queens.inp,v
retrieving revision 1.2
diff -u -u -r1.2 queens.inp
--- queens.inp 1998/06/18 06:08:35 1.2
+++ queens.inp 1998/07/04 12:19:19
@@ -1,87 +1,88 @@
-p *
+toggle_echo
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
-l 1
-p *
-l 2
-v
-p *
+print *
+level 1
+print *
+up 1
+vars
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
-C
+print *
+continue -a -N
Index: tests/debugger/queens_lib.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/queens_lib.inp,v
retrieving revision 1.2
diff -u -u -r1.2 queens_lib.inp
--- queens_lib.inp 1998/06/18 06:08:37 1.2
+++ queens_lib.inp 1998/07/04 12:19:30
@@ -1,87 +1,88 @@
-p *
+toggle_echo
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
-l 1
-p *
-l 2
-v
-p *
+print *
+level 1
+print *
+up 1
+vars
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
+print *
-p *
-C
+print *
+continue -a -N
cvs diff: Diffing tests/general
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trial
cvs diff: Diffing util
More information about the developers
mailing list