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_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_bool MR_event_matches_spy_point(const MR_LabelLayout *layout, MR_TracePort port, MR_SpyAction *action_ptr, MR_SpyPrintList *print_list_ptr) { int slot; MR_bool enabled; MR_SpyPoint *point; MR_SpyAction action; MR_SpyPrintList print_list; const MR_LabelLayout *parent; const MR_UserEvent *user_event; const MR_UserEventSpec *user_event_spec; const char *user_event_set; const char *user_event_name; const char *problem; MR_Word *base_sp; MR_Word *base_curfr; MR_Level actual_level; enabled = MR_FALSE; action = MR_SPY_PRINT; print_list = NULL; if (MR_spied_label_next > 0) { slot = MR_search_spy_table_for_label(layout); if (slot >= 0) { point = MR_spy_points[MR_spied_labels[slot].MR_sl_point_num]; if (point->MR_spy_when != MR_SPY_LINENO) { MR_fatal_error("non-lineno spy point in spied labels array"); } MR_update_enabled_action(point, layout, port, &enabled, &action, &print_list); } if (MR_port_is_interface(port)) { MR_restore_transient_registers(); base_sp = MR_sp; base_curfr = MR_curfr; parent = MR_find_nth_ancestor(layout, 1, &base_sp, &base_curfr, &actual_level, &problem); if (parent != NULL && actual_level == 1 && 0 <= (slot = MR_search_spy_table_for_label(parent))) { point = MR_spy_points[MR_spied_labels[slot].MR_sl_point_num]; if (point->MR_spy_when != MR_SPY_LINENO) { MR_fatal_error("non-lineno spy point in " "spied labels array"); } MR_update_enabled_action(point, layout, port, &enabled, &action, &print_list); } } } user_event = layout->MR_sll_user_event; if (user_event != NULL) { user_event_spec = &MR_user_event_spec(layout); user_event_name = user_event_spec->MR_ues_event_name; user_event_set = MR_user_event_set_name(layout); /* ** Check for breakpoints that specify an event name, and possibly ** and event set. */ slot = MR_search_spy_table_for_user_event_name(user_event_name); if (slot >= 0) { for (point = MR_spied_user_events[slot].MR_sue_points; point != NULL; point = point->MR_spy_next) { if (point->MR_spy_when != MR_SPY_USER_EVENT) { MR_fatal_error("non-named-user-event spy point " "in named user event array"); } if (point->MR_spy_user_event_set == NULL || MR_streq(user_event_set, point->MR_spy_user_event_set)) { MR_update_enabled_action(point, layout, port, &enabled, &action, &print_list); } } } /* ** Check for breakpoints that specify just an event set. */ slot = MR_search_spy_table_for_user_event_set(user_event_set); if (slot >= 0) { for (point = MR_spied_user_event_sets[slot].MR_sues_points; point != NULL; point = point->MR_spy_next) { if (point->MR_spy_when != MR_SPY_USER_EVENT_SET) { MR_fatal_error("non-named-user-event spy point " "in named user event array"); } MR_update_enabled_action(point, layout, port, &enabled, &action, &print_list); } } /* ** Check for breakpoints that specify neither event name nor event set. */ for (point = MR_spied_universal_user_events; point != NULL; point = point->MR_spy_next) { if (point->MR_spy_when != MR_SPY_USER_EVENT_SET) { MR_fatal_error("non-unnamed-user-event spy point " "in unnamed user event list"); } MR_update_enabled_action(point, layout, port, &enabled, &action, &print_list); } } slot = MR_search_spy_table_for_proc(layout->MR_sll_entry); if (slot >= 0) { for (point = MR_spied_procs[slot].MR_sp_points; point != NULL; point = point->MR_spy_next) { switch (point->MR_spy_when) { case MR_SPY_ALL: MR_update_enabled_action(point, layout, port, &enabled, &action, &print_list); break; case MR_SPY_ENTRY: if (MR_port_is_entry(port)) { MR_update_enabled_action(point, layout, port, &enabled, &action, &print_list); } else { continue; } break; case MR_SPY_INTERFACE: if (MR_port_is_interface(port)) { MR_update_enabled_action(point, layout, port, &enabled, &action, &print_list); } else { continue; } break; case MR_SPY_SPECIFIC: if (layout == point->MR_spy_label) { MR_update_enabled_action(point, layout, port, &enabled, &action, &print_list); } else { continue; } break; case MR_SPY_LINENO: MR_fatal_error("lineno spy point in spied procs array"); break; case MR_SPY_USER_EVENT: MR_fatal_error("user_event spy point " "in spied procs array"); break; case MR_SPY_USER_EVENT_SET: MR_fatal_error("user_event_set spy point " "in spied procs array"); break; default: MR_fatal_error("bad spy point when in " "MR_event_matches_spy_point"); } } } if (enabled) { *action_ptr = action; *print_list_ptr = print_list; return MR_TRUE; } else { return MR_FALSE; } }