+/* record_goto_insn -- rewind the record log (forward or backward,
+ depending on DIR) to the given entry, changing the program state
+ correspondingly. */
+
+static void
+record_goto_insn (struct record_entry *entry,
+ enum exec_direction_kind dir)
+{
+ struct cleanup *set_cleanups = record_gdb_operation_disable_set ();
+ struct regcache *regcache = get_current_regcache ();
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+
+ /* Assume everything is valid: we will hit the entry,
+ and we will not hit the end of the recording. */
+
+ if (dir == EXEC_FORWARD)
+ record_list = record_list->next;
+
+ do
+ {
+ record_exec_insn (regcache, gdbarch, record_list);
+ if (dir == EXEC_REVERSE)
+ record_list = record_list->prev;
+ else
+ record_list = record_list->next;
+ } while (record_list != entry);
+ do_cleanups (set_cleanups);
+}
+
+/* "record goto" command. Argument is an instruction number,
+ as given by "info record".
+
+ Rewinds the recording (forward or backward) to the given instruction. */
+
+static void
+cmd_record_goto (char *arg, int from_tty)
+{
+ struct record_entry *p = NULL;
+ ULONGEST target_insn = 0;
+
+ if (arg == NULL || *arg == '\0')
+ error (_("Command requires an argument (insn number to go to)."));
+
+ if (strncmp (arg, "start", strlen ("start")) == 0
+ || strncmp (arg, "begin", strlen ("begin")) == 0)
+ {
+ /* Special case. Find first insn. */
+ for (p = &record_first; p != NULL; p = p->next)
+ if (p->type == record_end)
+ break;
+ if (p)
+ target_insn = p->u.end.insn_num;
+ }
+ else if (strncmp (arg, "end", strlen ("end")) == 0)
+ {
+ /* Special case. Find last insn. */
+ for (p = record_list; p->next != NULL; p = p->next)
+ ;
+ for (; p!= NULL; p = p->prev)
+ if (p->type == record_end)
+ break;
+ if (p)
+ target_insn = p->u.end.insn_num;
+ }
+ else
+ {
+ /* General case. Find designated insn. */
+ target_insn = parse_and_eval_long (arg);
+
+ for (p = &record_first; p != NULL; p = p->next)
+ if (p->type == record_end && p->u.end.insn_num == target_insn)
+ break;
+ }
+
+ if (p == NULL)
+ error (_("Target insn '%s' not found."), arg);
+ else if (p == record_list)
+ error (_("Already at insn '%s'."), arg);
+ else if (p->u.end.insn_num > record_list->u.end.insn_num)
+ {
+ printf_filtered (_("Go forward to insn number %s\n"),
+ pulongest (target_insn));
+ record_goto_insn (p, EXEC_FORWARD);
+ }
+ else
+ {
+ printf_filtered (_("Go backward to insn number %s\n"),
+ pulongest (target_insn));
+ record_goto_insn (p, EXEC_REVERSE);
+ }
+ registers_changed ();
+ reinit_frame_cache ();
+ print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern initialize_file_ftype _initialize_record;
+