MR_Next MR_trace_cmd_hold(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { char *event_var_name; char *held_var_name; MR_TypeInfo type_info; MR_Word value; const char *ignored_name; const char *problem; MR_bool bad_subterm; if (word_count == 2) { event_var_name = words[1]; held_var_name = words[1]; } else if (word_count == 3) { event_var_name = words[1]; held_var_name = words[2]; } else { MR_trace_usage_cur_cmd(); return KEEP_INTERACTING; } if (strpbrk(held_var_name, "^/") != NULL) { /* Don't allow path separators in variable names. */ MR_trace_usage_cur_cmd(); return KEEP_INTERACTING; } if (held_var_name[0] == '$') { /* Ignore any unneeded initial $ signs. */ held_var_name = &held_var_name[1]; } problem = MR_trace_parse_lookup_var_path(event_var_name, &type_info, &value, &bad_subterm); if (problem != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: %s%s.\n", (bad_subterm? "there is no path " : ""), problem); return KEEP_INTERACTING; } if (! MR_add_hold_var(held_var_name, type_info, value)) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: there is already a held variable $%s\n", held_var_name); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_forward(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { cmd->MR_trace_strict = MR_TRUE; cmd->MR_trace_print_level_specified = MR_FALSE; cmd->MR_trace_print_level = MR_default_print_level; MR_init_trace_check_integrity(cmd); if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) { // The usage message has already been printed. ; } else if (word_count == 1) { MR_TracePort port; port = event_info->MR_trace_port; if (port == MR_PORT_FAIL || port == MR_PORT_REDO || port == MR_PORT_EXCEPTION) { cmd->MR_trace_cmd = MR_CMD_RESUME_FORWARD; return STOP_INTERACTING; } else { MR_trace_do_noop(); } } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_continue(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { cmd->MR_trace_strict = MR_FALSE; cmd->MR_trace_print_level_specified = MR_FALSE; cmd->MR_trace_print_level = MR_default_print_level; MR_init_trace_check_integrity(cmd); if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) { // The usage message has already been printed. ; } else if (word_count == 1) { cmd->MR_trace_cmd = MR_CMD_TO_END; if (! cmd->MR_trace_print_level_specified) { // 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; } } return STOP_INTERACTING; } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_maxdepth(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { MR_Unsigned newdepth; cmd->MR_trace_strict = MR_TRUE; cmd->MR_trace_print_level_specified = MR_FALSE; cmd->MR_trace_print_level = MR_default_print_level; MR_init_trace_check_integrity(cmd); if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) { // The usage message has already been printed. ; } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &newdepth)) { cmd->MR_trace_cmd = MR_CMD_MAX_DEPTH; cmd->MR_trace_stop_depth = newdepth; return STOP_INTERACTING; } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
static MR_bool MR_trace_options_movement_cmd(MR_TraceCmdInfo *cmd, char ***words, int *word_count) { int c; #ifdef MR_TRACE_CHECK_INTEGRITY #define MR_TRACE_MOVEMENT_OPTS "NSains" #else #define MR_TRACE_MOVEMENT_OPTS "NSans" #endif MR_optind = 0; while ((c = MR_getopt_long(*word_count, *words, MR_TRACE_MOVEMENT_OPTS, MR_trace_movement_cmd_opts, NULL)) != EOF) { switch (c) { case 'N': cmd->MR_trace_strict = MR_FALSE; break; case 'S': cmd->MR_trace_strict = MR_TRUE; break; case 'a': cmd->MR_trace_print_level_specified = MR_TRUE; cmd->MR_trace_print_level = MR_PRINT_LEVEL_ALL; break; case 'n': cmd->MR_trace_print_level_specified = MR_TRUE; cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE; break; case 's': cmd->MR_trace_print_level_specified = MR_TRUE; cmd->MR_trace_print_level = MR_PRINT_LEVEL_SOME; break; #ifdef MR_TRACE_CHECK_INTEGRITY case 'i': cmd->MR_trace_check_integrity = MR_TRUE; break; #endif default: MR_trace_usage_cur_cmd(); return MR_FALSE; } } *words = *words + MR_optind - 1; *word_count = *word_count - MR_optind + 1; return MR_TRUE; }
MR_Next MR_trace_cmd_fail(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { MR_Determinism detism; MR_Unsigned depth; MR_Unsigned stop_depth; MR_Unsigned n; detism = event_info->MR_event_sll->MR_sll_entry->MR_sle_detism; depth = event_info->MR_call_depth; cmd->MR_trace_strict = MR_TRUE; cmd->MR_trace_print_level_specified = MR_FALSE; cmd->MR_trace_print_level = MR_default_print_level; MR_init_trace_check_integrity(cmd); if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) { // The usage message has already been printed. return KEEP_INTERACTING; } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) { stop_depth = depth - n; } else if (word_count == 1) { stop_depth = depth; } else { MR_trace_usage_cur_cmd(); return KEEP_INTERACTING; } if (MR_DETISM_DET_STACK(detism)) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: cannot continue until failure: " "selected procedure has determinism %s.\n", MR_detism_names[detism]); return KEEP_INTERACTING; } // A procedure that lives on the nondet stack cannot have its stack frame // reused by tail recursive calls (at least not when any kind of debugging // is enabled). if (depth == stop_depth && event_info->MR_trace_port == MR_PORT_FAIL) { MR_trace_do_noop(); } else if (depth == stop_depth && event_info->MR_trace_port == MR_PORT_EXCEPTION) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: cannot continue until failure: " "the call has raised an exception.\n"); } else { cmd->MR_trace_cmd = MR_CMD_FAIL; cmd->MR_trace_stop_depth = stop_depth; return STOP_INTERACTING; } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_trusted(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { if (word_count == 1) { MR_decl_print_all_trusted(MR_mdb_out, MR_FALSE); } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_diff(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { MR_Unsigned start; MR_Unsigned max; char *name1; char *name2; MR_TypeInfo type_info1; MR_TypeInfo type_info2; MR_Word value1; MR_Word value2; MR_Word univ1; MR_Word univ2; const char *problem1; const char *problem2; MR_bool bad_subterm1; MR_bool bad_subterm2; start = 0; max = 20; if (! MR_trace_options_diff(&start, &max, &words, &word_count)) { /* the usage message has already been printed */ return KEEP_INTERACTING; } else if (word_count != 3) { MR_trace_usage_cur_cmd(); return KEEP_INTERACTING; } name1 = words[1]; name2 = words[2]; problem1 = MR_trace_parse_lookup_var_path(name1, &type_info1, &value1, &bad_subterm1); problem2 = MR_trace_parse_lookup_var_path(name2, &type_info2, &value2, &bad_subterm2); if (problem1 != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: %s%s.\n", (bad_subterm1? "arg1: there is no path " : ""), problem1); return KEEP_INTERACTING; } if (problem2 != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: %s%s.\n", (bad_subterm2? "arg2: there is no path " : ""), problem2); return KEEP_INTERACTING; } MR_TRACE_CALL_MERCURY( MR_new_univ_on_hp(univ1, type_info1, value1); MR_new_univ_on_hp(univ2, type_info2, value2); ML_report_diffs(start, max, univ1, univ2); );
MR_Next MR_trace_cmd_current(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { if (word_count == 1) { MR_trace_event_print_internal_report(event_info); } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_goto(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { MR_Unsigned n; const char *generator_name; cmd->MR_trace_strict = MR_TRUE; cmd->MR_trace_print_level_specified = MR_FALSE; cmd->MR_trace_print_level = MR_default_print_level; MR_init_trace_check_integrity(cmd); if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) { // The usage message has already been printed. ; } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) { generator_name = NULL; if (MR_trace_event_number < n || !MR_cur_generator_is_named(generator_name)) { cmd->MR_trace_cmd = MR_CMD_GOTO; cmd->MR_trace_stop_event = n; cmd->MR_trace_stop_generator = generator_name; return STOP_INTERACTING; } else { fflush(MR_mdb_out); // XXX This message is misleading. fprintf(MR_mdb_err, "The debugger cannot go to a past event.\n"); } #ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS } else if (word_count == 3 && MR_trace_is_natural_number(words[1], &n)) { generator_name = words[2]; if (MR_trace_event_number < n || !MR_cur_generator_is_named(generator_name)) { cmd->MR_trace_cmd = MR_CMD_GOTO; cmd->MR_trace_stop_event = n; // We don't ever deallocate the memory allocated here, // but this memory leak leaks only negligible amounts of memory. cmd->MR_trace_stop_generator = strdup(generator_name); return STOP_INTERACTING; } else { fflush(MR_mdb_out); // XXX This message is misleading. fprintf(MR_mdb_err, "The debugger cannot go to a past event.\n"); } #endif } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_held_vars(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { if (word_count == 1) { MR_trace_list_held_vars(MR_mdb_out); } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_untrust(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { MR_Unsigned i; if (word_count == 2 && MR_trace_is_natural_number(words[1], &i)) { if (!MR_decl_remove_trusted(i)) { fprintf(MR_mdb_err, "mdb: no such trusted object\n"); } } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_vars(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { if (word_count == 1) { const char *problem; problem = MR_trace_list_vars(MR_mdb_out); if (problem != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: %s.\n", problem); } } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_user(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { cmd->MR_trace_strict = MR_TRUE; cmd->MR_trace_print_level_specified = MR_FALSE; cmd->MR_trace_print_level = MR_default_print_level; MR_init_trace_check_integrity(cmd); if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) { // The usage message has already been printed. ; } else if (word_count == 1) { cmd->MR_trace_cmd = MR_CMD_USER; return STOP_INTERACTING; } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_down(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { MR_Unsigned n; MR_bool detailed; detailed = MR_FALSE; if (! MR_trace_options_detailed(&detailed, &words, &word_count)) { ; /* the usage message has already been printed */ } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) { MR_trace_set_level_and_report(MR_trace_current_level() - n, detailed, MR_print_optionals); } else if (word_count == 1) { MR_trace_set_level_and_report(MR_trace_current_level() - 1, detailed, MR_print_optionals); } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_level(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { MR_Unsigned n; MR_bool detailed; MR_Level selected_level; detailed = MR_FALSE; if (! MR_trace_options_detailed(&detailed, &words, &word_count)) { ; /* the usage message has already been printed */ } else if (word_count == 2 && ( MR_streq(words[1], "clique") || MR_streq(words[1], "clentry") )) { if (MR_find_clique_entry_mdb(event_info, MR_CLIQUE_ENTRY_FRAME, &selected_level)) { /* the error message has already been printed */ return KEEP_INTERACTING; } } else if (word_count == 2 && MR_streq(words[1], "clparent")) { if (MR_find_clique_entry_mdb(event_info, MR_CLIQUE_ENTRY_PARENT_FRAME, &selected_level)) { /* the error message has already been printed */ return KEEP_INTERACTING; } } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) { selected_level = n; } else { MR_trace_usage_cur_cmd(); return KEEP_INTERACTING; } MR_trace_set_level_and_report(selected_level, detailed, MR_print_optionals); return KEEP_INTERACTING; }
static MR_bool MR_trace_options_retry(MR_RetryAcrossIo *across_io, MR_bool *assume_all_io_is_tabled, char ***words, int *word_count) { int c; MR_optind = 0; while ((c = MR_getopt_long(*word_count, *words, "afio", MR_trace_retry_opts, NULL)) != EOF) { switch (c) { case 'a': *assume_all_io_is_tabled = MR_TRUE; break; case 'f': *across_io = MR_RETRY_IO_FORCE; break; case 'i': *across_io = MR_RETRY_IO_INTERACTIVE; break; case 'o': *across_io = MR_RETRY_IO_ONLY_IF_SAFE; break; default: MR_trace_usage_cur_cmd(); return MR_FALSE; } } *words = *words + MR_optind - 1; *word_count = *word_count - MR_optind + 1; return MR_TRUE; }
MR_Next MR_trace_cmd_view(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { const char *window_cmd = NULL; const char *server_cmd = NULL; const char *server_name = NULL; MR_Unsigned timeout = 8; /* seconds */ MR_bool force = MR_FALSE; MR_bool verbose = MR_FALSE; MR_bool split = MR_FALSE; MR_bool close_window = MR_FALSE; const char *msg; if (! MR_trace_options_view(&window_cmd, &server_cmd, &server_name, &timeout, &force, &verbose, &split, &close_window, &words, &word_count)) { ; /* the usage message has already been printed */ } else if (word_count != 1) { MR_trace_usage_cur_cmd(); } else if (close_window) { MR_trace_maybe_close_source_window(verbose); } else { msg = MR_trace_new_source_window(window_cmd, server_cmd, server_name, timeout, force, verbose, split); if (msg != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: %s.\n", msg); } MR_trace_maybe_sync_source_window(event_info, verbose); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_table_io(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { if (word_count == 1) { if (! MR_io_tabling_allowed) { fprintf(MR_mdb_err, "This executable wasn't prepared for I/O tabling.\n"); return KEEP_INTERACTING; } if (MR_io_tabling_phase == MR_IO_TABLING_BEFORE) { fprintf(MR_mdb_out, "I/O tabling has not yet started.\n"); } else if (MR_io_tabling_phase == MR_IO_TABLING_DURING) { fprintf(MR_mdb_out, "I/O tabling has started.\n"); } else if (MR_io_tabling_phase == MR_IO_TABLING_AFTER) { fprintf(MR_mdb_out, "I/O tabling has stopped.\n"); } else { MR_fatal_error("I/O tabling in impossible phase.\n"); } } else if (word_count == 2 && (MR_streq(words[1], "start") || MR_streq(words[1], "begin"))) { if (! MR_io_tabling_allowed) { fprintf(MR_mdb_err, "This executable wasn't prepared for I/O tabling.\n"); return KEEP_INTERACTING; } if (MR_io_tabling_phase == MR_IO_TABLING_BEFORE) { MR_io_tabling_phase = MR_IO_TABLING_DURING; MR_io_tabling_start = MR_io_tabling_counter; MR_io_tabling_end = MR_IO_ACTION_MAX; MR_io_tabling_start_event_num = event_info->MR_event_number; #ifdef MR_DEBUG_RETRY MR_io_tabling_debug = MR_TRUE; #endif fprintf(MR_mdb_out, "I/O tabling started.\n"); } else if (MR_io_tabling_phase == MR_IO_TABLING_DURING) { fprintf(MR_mdb_out, "I/O tabling has already started.\n"); } else if (MR_io_tabling_phase == MR_IO_TABLING_AFTER) { fprintf(MR_mdb_out, "I/O tabling has already stopped.\n"); } else { MR_fatal_error("I/O tabling in impossible phase.\n"); } } else if (word_count == 2 && (MR_streq(words[1], "stop") || MR_streq(words[1], "end"))) { if (! MR_io_tabling_allowed) { fprintf(MR_mdb_err, "This executable wasn't prepared for I/O tabling.\n"); return KEEP_INTERACTING; } if (MR_io_tabling_phase == MR_IO_TABLING_BEFORE) { fprintf(MR_mdb_out, "I/O tabling has not yet started.\n"); } else if (MR_io_tabling_phase == MR_IO_TABLING_DURING) { MR_io_tabling_phase = MR_IO_TABLING_AFTER; MR_io_tabling_end = MR_io_tabling_counter_hwm; MR_io_tabling_stop_event_num = event_info->MR_event_number; fprintf(MR_mdb_out, "I/O tabling stopped.\n"); } else if (MR_io_tabling_phase == MR_IO_TABLING_AFTER) { fprintf(MR_mdb_out, "I/O tabling has already stopped.\n"); } else { MR_fatal_error("I/O tabling in impossible phase.\n"); } } else if (word_count == 2 && MR_streq(words[1], "stats")) { if (! MR_io_tabling_allowed) { fprintf(MR_mdb_err, "This executable wasn't prepared for I/O tabling.\n"); return KEEP_INTERACTING; } fprintf(MR_mdb_out, "phase = %d\n", MR_io_tabling_phase); MR_print_unsigned_var(MR_mdb_out, "counter", MR_io_tabling_counter); MR_print_unsigned_var(MR_mdb_out, "hwm", MR_io_tabling_counter_hwm); MR_print_unsigned_var(MR_mdb_out, "start", MR_io_tabling_start); MR_print_unsigned_var(MR_mdb_out, "end", MR_io_tabling_end); } else if (word_count == 2 && MR_streq(words[1], "allow")) { /* ** The "table_io allow" command allows the programmer to give ** the command "table_io start" even in grades in which there ** is no guarantee that all I/O primitives are tabled. It is ** for developers only, because if it is used on programs in ** which some but not all I/O primitives are tabled, the ** results of turning on I/O tabling can be weird. */ MR_io_tabling_allowed = MR_TRUE; } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_trust(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { MR_ProcSpec spec; MR_MatchesInfo matches; if (word_count == 2) { spec.MR_proc_module = NULL; spec.MR_proc_name = NULL; spec.MR_proc_arity = -1; spec.MR_proc_mode = -1; spec.MR_proc_prefix = (MR_ProcPrefix) -1; MR_register_all_modules_and_procs(MR_mdb_out, MR_TRUE); /* First see if the argument is a module name */ spec.MR_proc_module = words[1]; matches = MR_search_for_matching_procedures(&spec); if (matches.match_proc_next > 0) { MR_decl_add_trusted_module(words[1]); fprintf(MR_mdb_out, "Trusting module %s\n", words[1]); } else if (MR_parse_proc_spec(words[1], &spec)) { /* Check to see if the argument is a pred/func */ matches = MR_search_for_matching_procedures(&spec); MR_filter_user_preds(&matches); if (matches.match_proc_next == 0) { fprintf(MR_mdb_err, "mdb: there is no such module, predicate or function.\n"); } else if (matches.match_proc_next == 1) { MR_decl_add_trusted_pred_or_func(matches.match_procs[0]); fprintf(MR_mdb_out, "Trusting "); MR_print_pred_id_and_nl(MR_mdb_out, matches.match_procs[0]); } else { MR_Unsigned i; char buf[80]; char *line2; fprintf(MR_mdb_out, "Ambiguous predicate or function" " specification. The matches are:\n"); for (i = 0; i < matches.match_proc_next; i++) { fprintf(MR_mdb_out, "%" MR_INTEGER_LENGTH_MODIFIER "u: ", i); MR_print_pred_id_and_nl(MR_mdb_out, matches.match_procs[i]); } sprintf(buf, "\nWhich predicate or function " "do you want to trust (0-%" MR_INTEGER_LENGTH_MODIFIER "u or *)? ", matches.match_proc_next - 1); line2 = MR_trace_getline(buf, MR_mdb_in, MR_mdb_out); if (line2 == NULL) { /* This means the user input EOF. */ fprintf(MR_mdb_out, "none of them\n"); } else if (MR_streq(line2, "*")) { for (i = 0; i < matches.match_proc_next; i++) { MR_decl_add_trusted_pred_or_func( matches.match_procs[i]); fprintf(MR_mdb_out, "Trusting "); MR_print_pred_id_and_nl(MR_mdb_out, matches.match_procs[i]); } MR_free(line2); } else if(MR_trace_is_natural_number(line2, &i)) { if (0 <= i && i < matches.match_proc_next) { MR_decl_add_trusted_pred_or_func( matches.match_procs[i]); fprintf(MR_mdb_out, "Trusting "); MR_print_pred_id_and_nl(MR_mdb_out, matches.match_procs[i]); } else { fprintf(MR_mdb_out, "no such match\n"); } MR_free(line2); } else { fprintf(MR_mdb_out, "none of them\n"); MR_free(line2); } } } } else if (word_count == 3 && ((MR_streq(words[1], "std") && MR_streq(words[2], "lib")) || (MR_streq(words[1], "standard") && MR_streq(words[2], "library")))) { MR_decl_trust_standard_library(); fprintf(MR_mdb_out, "Trusting the Mercury standard library\n"); } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_print(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { MR_BrowseFormat format; MR_bool xml; const char *problem; MR_Unsigned action; MR_Unsigned lo_action; MR_Unsigned hi_action; static MR_bool have_next_io_action = MR_FALSE; static MR_Unsigned next_io_action = 0; if (! MR_trace_options_format(&format, &xml, &words, &word_count)) { ; /* the usage message has already been printed */ } else if (xml) { /* the --xml option is not valid for print */ MR_trace_usage_cur_cmd(); } else if (word_count == 1) { problem = MR_trace_browse_one_goal(MR_mdb_out, MR_trace_browse_goal_internal, MR_BROWSE_CALLER_PRINT, format); if (problem != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: %s.\n", problem); } } else if (word_count == 2) { if (MR_streq(words[1], "*")) { problem = MR_trace_browse_all(MR_mdb_out, MR_trace_browse_internal, format); } else if (MR_streq(words[1], "goal")) { problem = MR_trace_browse_one_goal(MR_mdb_out, MR_trace_browse_goal_internal, MR_BROWSE_CALLER_PRINT, format); } else if (MR_streq(words[1], "exception")) { problem = MR_trace_browse_exception(event_info, MR_trace_browse_internal, MR_BROWSE_CALLER_PRINT, format); } else if (MR_streq(words[1], "proc_body")) { problem = MR_trace_browse_proc_body(event_info, MR_trace_browse_internal, MR_BROWSE_CALLER_PRINT, format); } else if ((MR_streq(words[1], "io") || MR_streq(words[1], "action"))) { MR_Unsigned num_printed_actions; if (MR_io_tabling_phase == MR_IO_TABLING_BEFORE) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: I/O tabling has not yet started.\n"); return KEEP_INTERACTING; } if (MR_io_tabling_counter_hwm == 0) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: There are no tabled I/O actions yet.\n"); return KEEP_INTERACTING; } if (have_next_io_action && (! (MR_io_tabling_start <= next_io_action && next_io_action < MR_io_tabling_counter_hwm))) { have_next_io_action = MR_FALSE; } if (have_next_io_action) { lo_action = next_io_action; } else { lo_action = MR_io_tabling_start; } hi_action = lo_action + MR_MAX_NUM_IO_ACTIONS_TO_PRINT; if (hi_action >= MR_io_tabling_counter_hwm) { hi_action = MR_io_tabling_counter_hwm - 1; } num_printed_actions = hi_action - lo_action + 1; if (num_printed_actions <= 0) { fprintf(MR_mdb_out, "There are no I/O actions to print\n"); have_next_io_action = MR_FALSE; } else { for (action = lo_action; action <= hi_action; action++) { fprintf(MR_mdb_out, "action %" MR_INTEGER_LENGTH_MODIFIER "u: ", action); problem = MR_trace_browse_action(MR_mdb_out, action, MR_trace_browse_goal_internal, MR_BROWSE_CALLER_PRINT, format); if (problem != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: %s.\n", problem); return KEEP_INTERACTING; } } if (hi_action == MR_io_tabling_counter_hwm - 1) { fprintf(MR_mdb_out, "there are no more actions (yet)\n"); } else { fprintf(MR_mdb_out, "there are more actions, up to action " "%" MR_INTEGER_LENGTH_MODIFIER "u\n", MR_io_tabling_counter_hwm - 1); } next_io_action = hi_action + 1; have_next_io_action = MR_TRUE; } } else { problem = MR_trace_parse_browse_one(MR_mdb_out, MR_TRUE, words[1], MR_trace_browse_internal, MR_BROWSE_CALLER_PRINT, format, MR_FALSE); } if (problem != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: %s.\n", problem); } } else if (word_count == 3 && (MR_streq(words[1], "io") || MR_streq(words[1], "action"))) { if (MR_io_tabling_phase == MR_IO_TABLING_BEFORE) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: I/O tabling has not yet started.\n"); return KEEP_INTERACTING; } if (MR_io_tabling_counter_hwm == 0) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: There are no tabled I/O actions yet.\n"); return KEEP_INTERACTING; } if (MR_streq(words[2], "limits")) { fprintf(MR_mdb_out, "I/O tabling has recorded actions " "%" MR_INTEGER_LENGTH_MODIFIER "u to " "%" MR_INTEGER_LENGTH_MODIFIER "u.\n", MR_io_tabling_start, MR_io_tabling_counter_hwm - 1); fflush(MR_mdb_out); } else if (MR_trace_is_natural_number(words[2], &action)) { problem = MR_trace_browse_action(MR_mdb_out, action, MR_trace_browse_goal_internal, MR_BROWSE_CALLER_PRINT, format); if (problem != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: %s.\n", problem); have_next_io_action = MR_FALSE; } next_io_action = action + 1; have_next_io_action = MR_TRUE; } else if (MR_trace_is_natural_number_pair(words[2], &lo_action, &hi_action)) { if (lo_action >= hi_action) { /* swap lo_action and hi_action */ MR_Unsigned tmp; tmp = lo_action; lo_action = hi_action; hi_action = tmp; } if (! (MR_io_tabling_start <= lo_action && hi_action < MR_io_tabling_counter_hwm)) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "I/O tabling has only recorded actions " "%" MR_INTEGER_LENGTH_MODIFIER "u to " "%" MR_INTEGER_LENGTH_MODIFIER "u.\n", MR_io_tabling_start, MR_io_tabling_counter_hwm - 1); have_next_io_action = MR_FALSE; return KEEP_INTERACTING; } for (action = lo_action; action <= hi_action; action++) { fprintf(MR_mdb_out, "action %" MR_INTEGER_LENGTH_MODIFIER "u: ", action); problem = MR_trace_browse_action(MR_mdb_out, action, MR_trace_browse_goal_internal, MR_BROWSE_CALLER_PRINT, format); if (problem != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: %s.\n", problem); return KEEP_INTERACTING; } } next_io_action = hi_action + 1; have_next_io_action = MR_TRUE; } else { MR_trace_usage_cur_cmd(); } } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_browse(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { MR_BrowseFormat format; MR_bool xml; MR_IoActionNum action; MR_GoalBrowser goal_browser; MR_Browser browser; const char *problem; if (! MR_trace_options_format(&format, &xml, &words, &word_count)) { ; /* the usage message has already been printed */ } else { if (xml) { goal_browser = MR_trace_browse_goal_xml; browser = MR_trace_browse_xml; } else { goal_browser = MR_trace_browse_goal_internal; browser = MR_trace_browse_internal; } if (word_count == 1) { problem = MR_trace_browse_one_goal(MR_mdb_out, goal_browser, MR_BROWSE_CALLER_BROWSE, format); if (problem != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: %s.\n", problem); } } else if (word_count == 2) { if (MR_streq(words[1], "goal")) { problem = MR_trace_browse_one_goal(MR_mdb_out, goal_browser, MR_BROWSE_CALLER_BROWSE, format); } else if (MR_streq(words[1], "exception")) { problem = MR_trace_browse_exception(event_info, browser, MR_BROWSE_CALLER_BROWSE, format); } else if (MR_streq(words[1], "proc_body")) { problem = MR_trace_browse_proc_body(event_info, browser, MR_BROWSE_CALLER_BROWSE, format); } else { problem = MR_trace_parse_browse_one(MR_mdb_out, MR_FALSE, words[1], browser, MR_BROWSE_CALLER_BROWSE, format, MR_TRUE); } if (problem != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: %s.\n", problem); } } else if (word_count == 3 && (MR_streq(words[1], "io") || MR_streq(words[1], "action")) && MR_trace_is_natural_number(words[2], &action)) { problem = MR_trace_browse_action(MR_mdb_out, action, goal_browser, MR_BROWSE_CALLER_BROWSE, format); if (problem != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: %s.\n", problem); } } else { MR_trace_usage_cur_cmd(); } } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_stack(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { MR_bool print_all; MR_bool detailed; MR_FrameLimit frame_limit; MR_SpecLineLimit clique_line_limit; MR_SpecLineLimit line_limit; MR_SpecLineLimit spec_line_limit; const MR_LabelLayout *layout; MR_Word *saved_regs; const char *msg; detailed = MR_FALSE; print_all = MR_FALSE; frame_limit = 0; clique_line_limit = 10; line_limit = 100; if (! MR_trace_options_stack_trace(&print_all, &detailed, &line_limit, &clique_line_limit, &frame_limit, &words, &word_count)) { /* the usage message has already been printed */ return KEEP_INTERACTING; } else if (word_count == 1) { line_limit = MR_stack_default_line_limit; } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &spec_line_limit)) { line_limit = spec_line_limit; } else { MR_trace_usage_cur_cmd(); return KEEP_INTERACTING; } layout = event_info->MR_event_sll; saved_regs = event_info->MR_saved_regs; #ifdef MR_DEBUG_STACK_DUMP_CLIQUE MR_trace_init_modules(); fprintf(MR_mdb_out, "OLD STACK DUMP:\n"); msg = MR_dump_stack_from_layout(MR_mdb_out, layout, MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs), detailed, MR_context_position != MR_CONTEXT_NOWHERE, frame_limit, line_limit, &MR_dump_stack_record_print); if (msg != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "%s.\n", msg); } fprintf(MR_mdb_out, "\nNEW STACK DUMP:\n"); #endif msg = MR_dump_stack_from_layout_clique(MR_mdb_out, layout, MR_saved_sp(saved_regs), MR_saved_curfr(saved_regs), detailed, MR_context_position != MR_CONTEXT_NOWHERE, !print_all, clique_line_limit, frame_limit, line_limit, &MR_dump_stack_record_print); if (msg != NULL) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "%s.\n", msg); } return KEEP_INTERACTING; }
static MR_bool MR_trace_options_dd(MR_bool *assume_all_io_is_tabled, MR_Unsigned *default_depth, MR_Unsigned *num_nodes, MR_DeclSearchMode *search_mode, MR_bool *search_mode_was_set, MR_bool *search_mode_requires_trace_counts, char **pass_trace_counts_file, char **fail_trace_counts_file, MR_bool *new_session, MR_bool *reset_kb, MR_bool *testing, MR_bool *debug, char ***words, int *word_count) { int c; MR_optind = 0; while ((c = MR_getopt_long(*word_count, *words, "ad:f:n:p:rRs:tz", MR_trace_dd_opts, NULL)) != EOF) { switch (c) { case 'a': *assume_all_io_is_tabled = MR_TRUE; break; case 'd': if (! MR_trace_is_natural_number(MR_optarg, default_depth)) { MR_trace_usage_cur_cmd(); return MR_FALSE; } break; case 'f': *fail_trace_counts_file = MR_copy_string(MR_optarg); break; case 'n': if (! MR_trace_is_natural_number(MR_optarg, num_nodes)) { MR_trace_usage_cur_cmd(); return MR_FALSE; } break; case 'p': *pass_trace_counts_file = MR_copy_string(MR_optarg); break; case 'r': *new_session = MR_FALSE; break; case 'R': *reset_kb = MR_TRUE; break; case 's': if (MR_trace_is_valid_search_mode_string(MR_optarg, search_mode, search_mode_requires_trace_counts)) { *search_mode_was_set = MR_TRUE; } else { MR_trace_usage_cur_cmd(); return MR_FALSE; } break; case 't': *testing = MR_TRUE; break; case 'z': *debug = MR_TRUE; break; default: MR_trace_usage_cur_cmd(); return MR_FALSE; } } *words = *words + MR_optind - 1; *word_count = *word_count - MR_optind + 1; return MR_TRUE; }
MR_Next MR_trace_cmd_retry(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { MR_Level n; MR_Level ancestor_level; MR_RetryAcrossIo across_io; const char *problem; MR_RetryResult result; MR_bool assume_all_io_is_tabled; MR_bool unsafe_retry; ancestor_level = 0; across_io = MR_RETRY_IO_INTERACTIVE; assume_all_io_is_tabled = MR_FALSE; if (! MR_trace_options_retry(&across_io, &assume_all_io_is_tabled, &words, &word_count)) { ; /* the usage message has already been printed */ } else if (word_count == 2 && ( MR_streq(words[1], "clique") || MR_streq(words[1], "clentry"))) { if (MR_find_clique_entry_mdb(event_info, MR_CLIQUE_ENTRY_FRAME, &ancestor_level)) { /* the error message has already been printed */ return KEEP_INTERACTING; } } else if (word_count == 2 && MR_streq(words[1], "clparent")) { if (MR_find_clique_entry_mdb(event_info, MR_CLIQUE_ENTRY_PARENT_FRAME, &ancestor_level)) { /* the error message has already been printed */ return KEEP_INTERACTING; } } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) { ancestor_level = n; } else if (word_count == 1) { ancestor_level = 0; } else { MR_trace_usage_cur_cmd(); return KEEP_INTERACTING; } if (ancestor_level == 0 && MR_port_is_entry(event_info->MR_trace_port)) { MR_trace_do_noop(); return KEEP_INTERACTING; } result = MR_trace_retry(event_info, ancestor_level, across_io, assume_all_io_is_tabled, MR_UNTABLED_IO_RETRY_MESSAGE, &unsafe_retry, &problem, MR_mdb_in, MR_mdb_out, jumpaddr); switch (result) { case MR_RETRY_OK_DIRECT: cmd->MR_trace_cmd = MR_CMD_GOTO; cmd->MR_trace_stop_event = MR_trace_event_number + 1; cmd->MR_trace_strict = MR_FALSE; cmd->MR_trace_print_level = MR_default_print_level; return STOP_INTERACTING; case MR_RETRY_OK_FINISH_FIRST: cmd->MR_trace_cmd = MR_CMD_FINISH; cmd->MR_trace_stop_depth = event_info->MR_call_depth - ancestor_level; cmd->MR_trace_strict = MR_TRUE; cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE; /* Arrange to retry the call once it is finished. */ /* XXX we should use the same options as the original retry */ MR_insert_command_line_at_head("retry -o"); return STOP_INTERACTING; case MR_RETRY_OK_FAIL_FIRST: cmd->MR_trace_cmd = MR_CMD_FAIL; cmd->MR_trace_stop_depth = event_info->MR_call_depth - ancestor_level; cmd->MR_trace_strict = MR_TRUE; cmd->MR_trace_print_level = MR_PRINT_LEVEL_NONE; /* Arrange to retry the call once it is finished. */ /* XXX we should use the same options as the original retry */ MR_insert_command_line_at_head("retry -o"); return STOP_INTERACTING; case MR_RETRY_ERROR: fflush(MR_mdb_out); fprintf(MR_mdb_err, "%s\n", problem); return KEEP_INTERACTING; } MR_fatal_error("unrecognized retry result"); }
MR_Next MR_trace_cmd_finish(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { const MR_ProcLayout *proc_layout; const MR_LabelLayout *ancestor_layout; MR_Unsigned depth; MR_Unsigned stop_depth; MR_Unsigned n; MR_Level ancestor_level; MR_TracePort port; MR_Word *base_sp; MR_Word *base_curfr; MR_Unsigned reused_frames; MR_Level actual_level; const char *problem; // Not used. depth = event_info->MR_call_depth; cmd->MR_trace_strict = MR_TRUE; cmd->MR_trace_print_level_specified = MR_FALSE; cmd->MR_trace_print_level = MR_default_print_level; MR_init_trace_check_integrity(cmd); if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) { // The usage message has already been printed. ; return KEEP_INTERACTING; } else if (word_count == 2 && ( MR_streq(words[1], "entry") || MR_streq(words[1], "clentry"))) { if (MR_find_clique_entry_mdb(event_info, MR_CLIQUE_ENTRY_FRAME, &ancestor_level)) { // The error message has already been printed. return KEEP_INTERACTING; } } else if (word_count == 2 && MR_streq(words[1], "clparent")) { if (MR_find_clique_entry_mdb(event_info, MR_CLIQUE_ENTRY_PARENT_FRAME, &ancestor_level)) { // The error message has already been printed. return KEEP_INTERACTING; } } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) { ancestor_level = n; } else if (word_count == 1) { ancestor_level = 0; } else { MR_trace_usage_cur_cmd(); return KEEP_INTERACTING; } base_sp = MR_saved_sp(event_info->MR_saved_regs); base_curfr = MR_saved_curfr(event_info->MR_saved_regs); proc_layout = event_info->MR_event_sll->MR_sll_entry; MR_trace_find_reused_frames(proc_layout, base_sp, reused_frames); port = event_info->MR_trace_port; stop_depth = depth - ancestor_level; if (MR_port_is_final(port) && depth == stop_depth) { MR_trace_do_noop(); } else if (MR_port_is_final(port) && depth - reused_frames <= stop_depth && stop_depth < depth) { MR_trace_do_noop_tail_rec(); } else { ancestor_layout = MR_find_nth_ancestor(event_info->MR_event_sll, ancestor_level, &base_sp, &base_curfr, &actual_level, &problem); if (ancestor_layout == NULL) { fflush(MR_mdb_out); if (problem != NULL) { fprintf(MR_mdb_err, "mdb: %s\n", problem); } else { fprintf(MR_mdb_err, "mdb: not that many ancestors.\n"); } return KEEP_INTERACTING; } else if (actual_level != ancestor_level) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "%d %d\n", (int) ancestor_level, (int) actual_level); fprintf(MR_mdb_err, "mdb: that stack frame has been reused, " "will stop at finish of reusing call.\n"); } else { cmd->MR_trace_cmd = MR_CMD_FINISH; cmd->MR_trace_stop_depth = stop_depth; return STOP_INTERACTING; } } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_dd(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { MR_DeclSearchMode search_mode; MR_bool search_mode_was_set = MR_FALSE; MR_bool new_session = MR_TRUE; MR_bool reset_kb = MR_FALSE; MR_bool search_mode_requires_trace_counts = MR_FALSE; char *pass_trace_counts_file; char *fail_trace_counts_file; MR_String problem; MR_bool testing = MR_FALSE; const char *filename; MR_DeclMode decl_mode; MR_trace_decl_assume_all_io_is_tabled = MR_FALSE; MR_edt_default_depth_limit = MR_TRACE_DECL_INITIAL_DEPTH; search_mode = MR_trace_get_default_search_mode(); pass_trace_counts_file = MR_dice_pass_trace_counts_file; fail_trace_counts_file = MR_dice_fail_trace_counts_file; MR_trace_decl_debug_debugger_mode = MR_FALSE; if (! MR_trace_options_dd(&MR_trace_decl_assume_all_io_is_tabled, &MR_edt_default_depth_limit, &MR_edt_desired_nodes_in_subtree, &search_mode, &search_mode_was_set, &search_mode_requires_trace_counts, &pass_trace_counts_file, &fail_trace_counts_file, &new_session, &reset_kb, &testing, &MR_trace_decl_debug_debugger_mode, &words, &word_count)) { ; /* the usage message has already been printed */ } else if (word_count <= 2) { if (word_count == 2 && MR_trace_decl_debug_debugger_mode) { decl_mode = MR_DECL_DUMP; filename = (const char *) words[1]; } else { decl_mode = MR_DECL_NODUMP; filename = (const char *) NULL; } if (MR_trace_have_unhid_events) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: dd doesn't work after `unhide_events on'.\n"); return KEEP_INTERACTING; } if (search_mode_requires_trace_counts && ( pass_trace_counts_file == NULL || fail_trace_counts_file == NULL)) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: you need to supply passing and failing trace count " "files\nbefore using the specified search mode.\n"); return KEEP_INTERACTING; } if (pass_trace_counts_file != NULL && fail_trace_counts_file != NULL) { if (! MR_trace_decl_init_suspicion_table(pass_trace_counts_file, fail_trace_counts_file, &problem)) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: %s\n", problem); return KEEP_INTERACTING; } } MR_trace_decl_set_testing_flag(testing); if (new_session) { MR_trace_decl_session_init(); } if (search_mode_was_set || new_session) { MR_trace_decl_set_fallback_search_mode(search_mode); } if (reset_kb) { MR_trace_decl_reset_knowledge_base(); } if (MR_trace_start_decl_debug(decl_mode, filename, new_session, cmd, event_info, jumpaddr)) { return STOP_INTERACTING; } } else { MR_trace_usage_cur_cmd(); } return KEEP_INTERACTING; }
MR_Next MR_trace_cmd_next(char **words, int word_count, MR_TraceCmdInfo *cmd, MR_EventInfo *event_info, MR_Code **jumpaddr) { const MR_ProcLayout *proc_layout; const MR_LabelLayout *ancestor_layout; MR_Unsigned depth; MR_Unsigned stop_depth; MR_Unsigned n; MR_TracePort port; MR_Word *base_sp; MR_Word *base_curfr; MR_Unsigned reused_frames; MR_Level actual_level; const char *problem; // Not used. depth = event_info->MR_call_depth; cmd->MR_trace_strict = MR_TRUE; cmd->MR_trace_print_level_specified = MR_FALSE; cmd->MR_trace_print_level = MR_default_print_level; MR_init_trace_check_integrity(cmd); if (! MR_trace_options_movement_cmd(cmd, &words, &word_count)) { // The usage message has already been printed. ; return KEEP_INTERACTING; } else if (word_count == 2 && MR_trace_is_natural_number(words[1], &n)) { stop_depth = depth - n; } else if (word_count == 1) { n = 0; stop_depth = depth; } else { MR_trace_usage_cur_cmd(); return KEEP_INTERACTING; } base_sp = MR_saved_sp(event_info->MR_saved_regs); base_curfr = MR_saved_curfr(event_info->MR_saved_regs); proc_layout = event_info->MR_event_sll->MR_sll_entry; MR_trace_find_reused_frames(proc_layout, base_sp, reused_frames); port = event_info->MR_trace_port; if (depth == stop_depth && (MR_port_is_final(port) || port == MR_PORT_TAILREC_CALL)) { MR_trace_do_noop(); } else if (depth - reused_frames <= stop_depth && stop_depth < depth) { MR_trace_do_noop_tail_rec(); } else { ancestor_layout = MR_find_nth_ancestor(event_info->MR_event_sll, n, &base_sp, &base_curfr, &actual_level, &problem); if (ancestor_layout == NULL) { fflush(MR_mdb_out); if (problem != NULL) { fprintf(MR_mdb_err, "mdb: %s\n", problem); } else { fprintf(MR_mdb_err, "mdb: not that many ancestors.\n"); } return KEEP_INTERACTING; } else if (actual_level != n) { fflush(MR_mdb_out); fprintf(MR_mdb_err, "mdb: that stack frame has been reused, " "will stop in reusing call.\n"); } else { cmd->MR_trace_cmd = MR_CMD_NEXT; cmd->MR_trace_stop_depth = stop_depth; return STOP_INTERACTING; } } return KEEP_INTERACTING; }