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_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; }
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_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_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; }
void MR_trace_expand_aliases(char ***words, int *word_max, int *word_count) { const char *alias_key; char **alias_words; int alias_word_count; int alias_copy_start; int i; MR_Unsigned n; if (*word_count == 0) { alias_key = "EMPTY"; alias_copy_start = 0; } else if (MR_trace_is_natural_number(*words[0], &n)) { alias_key = "NUMBER"; alias_copy_start = 0; } else { alias_key = *words[0]; alias_copy_start = 1; } if (MR_trace_lookup_alias(alias_key, &alias_words, &alias_word_count)) { MR_ensure_big_enough(*word_count + alias_word_count, *word, char *, MR_INIT_WORD_COUNT); // Move the original words (except the alias key) up. for (i = *word_count - 1; i >= alias_copy_start; i--) { (*words)[i + alias_word_count - alias_copy_start] = (*words)[i]; } // Move the alias body to the words array. for (i = 0; i < alias_word_count; i++) { (*words)[i] = alias_words[i]; } *word_count += alias_word_count - alias_copy_start; }
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_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_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_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; }
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; }
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_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_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"); }