+static void
+edit_command (char *arg, int from_tty)
+{
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ struct symbol *sym;
+ char *arg1;
+ char *editor;
+ char *p, *fn;
+
+ /* Pull in the current default source line if necessary. */
+ if (arg == 0)
+ {
+ set_default_source_symtab_and_line ();
+ sal = get_current_source_symtab_and_line ();
+ }
+
+ /* bare "edit" edits file with present line. */
+
+ if (arg == 0)
+ {
+ if (sal.symtab == 0)
+ error (_("No default source file yet."));
+ sal.line += get_lines_to_list () / 2;
+ }
+ else
+ {
+ /* Now should only be one argument -- decode it in SAL. */
+
+ arg1 = arg;
+ sals = decode_line_1 (&arg1, 0, 0, 0, 0, 0);
+
+ if (! sals.nelts)
+ {
+ /* C++ */
+ return;
+ }
+ if (sals.nelts > 1)
+ {
+ ambiguous_line_spec (&sals);
+ xfree (sals.sals);
+ return;
+ }
+
+ sal = sals.sals[0];
+ xfree (sals.sals);
+
+ if (*arg1)
+ error (_("Junk at end of line specification."));
+
+ /* If line was specified by address,
+ first print exactly which line, and which file.
+ In this case, sal.symtab == 0 means address is outside
+ of all known source files, not that user failed to give a filename. */
+ if (*arg == '*')
+ {
+ struct gdbarch *gdbarch;
+
+ if (sal.symtab == 0)
+ /* FIXME-32x64--assumes sal.pc fits in long. */
+ error (_("No source file for address %s."),
+ hex_string ((unsigned long) sal.pc));
+
+ gdbarch = get_objfile_arch (sal.symtab->objfile);
+ sym = find_pc_function (sal.pc);
+ if (sym)
+ printf_filtered ("%s is in %s (%s:%d).\n",
+ paddress (gdbarch, sal.pc),
+ SYMBOL_PRINT_NAME (sym),
+ sal.symtab->filename, sal.line);
+ else
+ printf_filtered ("%s is at %s:%d.\n",
+ paddress (gdbarch, sal.pc),
+ sal.symtab->filename, sal.line);
+ }
+
+ /* If what was given does not imply a symtab, it must be an undebuggable
+ symbol which means no source code. */
+
+ if (sal.symtab == 0)
+ error (_("No line number known for %s."), arg);
+ }
+
+ if ((editor = (char *) getenv ("EDITOR")) == NULL)
+ editor = "/bin/ex";
+
+ /* If we don't already know the full absolute file name of the
+ source file, find it now. */
+ if (!sal.symtab->fullname)
+ {
+ fn = symtab_to_fullname (sal.symtab);
+ if (!fn)
+ fn = "unknown";
+ }
+ else
+ fn = sal.symtab->fullname;
+
+ /* Quote the file name, in case it has whitespace or other special
+ characters. */
+ p = xstrprintf ("%s +%d \"%s\"", editor, sal.line, fn);
+ shell_escape (p, from_tty);
+ xfree (p);
+}
+
+static void
+list_command (char *arg, int from_tty)
+{
+ struct symtabs_and_lines sals, sals_end;
+ struct symtab_and_line sal = { 0 };
+ struct symtab_and_line sal_end = { 0 };
+ struct symtab_and_line cursal = { 0 };
+ struct symbol *sym;
+ char *arg1;
+ int no_end = 1;
+ int dummy_end = 0;
+ int dummy_beg = 0;
+ int linenum_beg = 0;
+ char *p;
+
+ /* Pull in the current default source line if necessary */
+ if (arg == 0 || arg[0] == '+' || arg[0] == '-')
+ {
+ set_default_source_symtab_and_line ();
+ cursal = get_current_source_symtab_and_line ();
+ }
+
+ /* "l" or "l +" lists next ten lines. */
+
+ if (arg == 0 || strcmp (arg, "+") == 0)
+ {
+ print_source_lines (cursal.symtab, cursal.line,
+ cursal.line + get_lines_to_list (), 0);
+ return;
+ }
+
+ /* "l -" lists previous ten lines, the ones before the ten just listed. */
+ if (strcmp (arg, "-") == 0)
+ {
+ print_source_lines (cursal.symtab,
+ max (get_first_line_listed () - get_lines_to_list (), 1),
+ get_first_line_listed (), 0);
+ return;
+ }
+
+ /* Now if there is only one argument, decode it in SAL
+ and set NO_END.
+ If there are two arguments, decode them in SAL and SAL_END
+ and clear NO_END; however, if one of the arguments is blank,
+ set DUMMY_BEG or DUMMY_END to record that fact. */
+
+ if (!have_full_symbols () && !have_partial_symbols ())
+ error (_("No symbol table is loaded. Use the \"file\" command."));
+
+ arg1 = arg;
+ if (*arg1 == ',')
+ dummy_beg = 1;
+ else
+ {
+ sals = decode_line_1 (&arg1, 0, 0, 0, 0, 0);
+
+ if (!sals.nelts)
+ return; /* C++ */
+ if (sals.nelts > 1)
+ {
+ ambiguous_line_spec (&sals);
+ xfree (sals.sals);
+ return;
+ }
+
+ sal = sals.sals[0];
+ xfree (sals.sals);
+ }
+
+ /* Record whether the BEG arg is all digits. */
+
+ for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++);
+ linenum_beg = (p == arg1);
+
+ while (*arg1 == ' ' || *arg1 == '\t')
+ arg1++;
+ if (*arg1 == ',')
+ {
+ no_end = 0;
+ arg1++;
+ while (*arg1 == ' ' || *arg1 == '\t')
+ arg1++;
+ if (*arg1 == 0)
+ dummy_end = 1;
+ else
+ {
+ if (dummy_beg)
+ sals_end = decode_line_1 (&arg1, 0, 0, 0, 0, 0);
+ else
+ sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0, 0);
+ if (sals_end.nelts == 0)
+ return;
+ if (sals_end.nelts > 1)
+ {
+ ambiguous_line_spec (&sals_end);
+ xfree (sals_end.sals);
+ return;
+ }
+ sal_end = sals_end.sals[0];
+ xfree (sals_end.sals);
+ }
+ }
+
+ if (*arg1)
+ error (_("Junk at end of line specification."));
+
+ if (!no_end && !dummy_beg && !dummy_end
+ && sal.symtab != sal_end.symtab)
+ error (_("Specified start and end are in different files."));
+ if (dummy_beg && dummy_end)
+ error (_("Two empty args do not say what lines to list."));
+
+ /* if line was specified by address,
+ first print exactly which line, and which file.
+ In this case, sal.symtab == 0 means address is outside
+ of all known source files, not that user failed to give a filename. */
+ if (*arg == '*')
+ {
+ struct gdbarch *gdbarch;
+
+ if (sal.symtab == 0)
+ /* FIXME-32x64--assumes sal.pc fits in long. */
+ error (_("No source file for address %s."),
+ hex_string ((unsigned long) sal.pc));
+
+ gdbarch = get_objfile_arch (sal.symtab->objfile);
+ sym = find_pc_function (sal.pc);
+ if (sym)
+ printf_filtered ("%s is in %s (%s:%d).\n",
+ paddress (gdbarch, sal.pc),
+ SYMBOL_PRINT_NAME (sym),
+ sal.symtab->filename, sal.line);
+ else
+ printf_filtered ("%s is at %s:%d.\n",
+ paddress (gdbarch, sal.pc),
+ sal.symtab->filename, sal.line);
+ }
+
+ /* If line was not specified by just a line number,
+ and it does not imply a symtab, it must be an undebuggable symbol
+ which means no source code. */
+
+ if (!linenum_beg && sal.symtab == 0)
+ error (_("No line number known for %s."), arg);
+
+ /* If this command is repeated with RET,
+ turn it into the no-arg variant. */
+
+ if (from_tty)
+ *arg = 0;
+
+ if (dummy_beg && sal_end.symtab == 0)
+ error (_("No default source file yet. Do \"help list\"."));
+ if (dummy_beg)
+ print_source_lines (sal_end.symtab,
+ max (sal_end.line - (get_lines_to_list () - 1), 1),
+ sal_end.line + 1, 0);
+ else if (sal.symtab == 0)
+ error (_("No default source file yet. Do \"help list\"."));
+ else if (no_end)
+ {
+ int first_line = sal.line - get_lines_to_list () / 2;
+
+ if (first_line < 1) first_line = 1;
+
+ print_source_lines (sal.symtab,
+ first_line,
+ first_line + get_lines_to_list (),
+ 0);
+ }
+ else
+ print_source_lines (sal.symtab, sal.line,
+ (dummy_end
+ ? sal.line + get_lines_to_list ()
+ : sal_end.line + 1),
+ 0);
+}
+
+/* Subroutine of disassemble_command to simplify it.
+ Perform the disassembly.
+ NAME is the name of the function if known, or NULL.
+ [LOW,HIGH) are the range of addresses to disassemble.
+ MIXED is non-zero to print source with the assembler. */
+
+static void
+print_disassembly (struct gdbarch *gdbarch, const char *name,
+ CORE_ADDR low, CORE_ADDR high, int flags)
+{
+#if defined(TUI)
+ if (!tui_is_window_visible (DISASSEM_WIN))
+#endif
+ {
+ printf_filtered ("Dump of assembler code ");
+ if (name != NULL)
+ printf_filtered ("for function %s:\n", name);
+ else
+ printf_filtered ("from %s to %s:\n",
+ paddress (gdbarch, low), paddress (gdbarch, high));
+
+ /* Dump the specified range. */
+ gdb_disassembly (gdbarch, uiout, 0, flags, -1, low, high);
+
+ printf_filtered ("End of assembler dump.\n");
+ gdb_flush (gdb_stdout);
+ }
+#if defined(TUI)
+ else
+ {
+ tui_show_assembly (gdbarch, low);
+ }
+#endif
+}
+
+/* Subroutine of disassemble_command to simplify it.
+ Print a disassembly of the current function according to FLAGS. */
+
+static void
+disassemble_current_function (int flags)
+{
+ struct frame_info *frame;
+ struct gdbarch *gdbarch;
+ CORE_ADDR low, high, pc;
+ char *name;
+
+ frame = get_selected_frame (_("No frame selected."));
+ gdbarch = get_frame_arch (frame);
+ pc = get_frame_pc (frame);
+ if (find_pc_partial_function (pc, &name, &low, &high) == 0)
+ error (_("No function contains program counter for selected frame."));
+#if defined(TUI)
+ /* NOTE: cagney/2003-02-13 The `tui_active' was previously
+ `tui_version'. */
+ if (tui_active)
+ /* FIXME: cagney/2004-02-07: This should be an observer. */
+ low = tui_get_low_disassembly_address (gdbarch, low, pc);
+#endif
+ low += gdbarch_deprecated_function_start_offset (gdbarch);
+
+ print_disassembly (gdbarch, name, low, high, flags);
+}
+
+/* Dump a specified section of assembly code.
+
+ Usage:
+ disassemble [/mr]
+ - dump the assembly code for the function of the current pc
+ disassemble [/mr] addr
+ - dump the assembly code for the function at ADDR
+ disassemble [/mr] low,high
+ disassemble [/mr] low,+length
+ - dump the assembly code in the range [LOW,HIGH), or [LOW,LOW+length)
+
+ A /m modifier will include source code with the assembly.
+ A /r modifier will include raw instructions in hex with the assembly. */
+
+static void
+disassemble_command (char *arg, int from_tty)
+{
+ struct gdbarch *gdbarch = get_current_arch ();
+ CORE_ADDR low, high;
+ char *name;
+ CORE_ADDR pc;
+ int flags;
+
+ name = NULL;
+ flags = 0;
+
+ if (arg && *arg == '/')
+ {
+ ++arg;
+
+ if (*arg == '\0')
+ error (_("Missing modifier."));
+
+ while (*arg && ! isspace (*arg))
+ {
+ switch (*arg++)
+ {
+ case 'm':
+ flags |= DISASSEMBLY_SOURCE;
+ break;
+ case 'r':
+ flags |= DISASSEMBLY_RAW_INSN;
+ break;
+ default:
+ error (_("Invalid disassembly modifier."));
+ }
+ }
+
+ while (isspace (*arg))
+ ++arg;
+ }
+
+ if (! arg || ! *arg)
+ {
+ flags |= DISASSEMBLY_OMIT_FNAME;
+ disassemble_current_function (flags);
+ return;
+ }
+
+ pc = value_as_address (parse_to_comma_and_eval (&arg));
+ if (arg[0] == ',')
+ ++arg;
+ if (arg[0] == '\0')
+ {
+ /* One argument. */
+ if (find_pc_partial_function (pc, &name, &low, &high) == 0)
+ error (_("No function contains specified address."));
+#if defined(TUI)
+ /* NOTE: cagney/2003-02-13 The `tui_active' was previously
+ `tui_version'. */
+ if (tui_active)
+ /* FIXME: cagney/2004-02-07: This should be an observer. */
+ low = tui_get_low_disassembly_address (gdbarch, low, pc);
+#endif
+ low += gdbarch_deprecated_function_start_offset (gdbarch);
+ flags |= DISASSEMBLY_OMIT_FNAME;
+ }
+ else
+ {
+ /* Two arguments. */
+ int incl_flag = 0;
+ low = pc;
+ while (isspace (*arg))
+ arg++;
+ if (arg[0] == '+')
+ {
+ ++arg;
+ incl_flag = 1;
+ }
+ high = parse_and_eval_address (arg);
+ if (incl_flag)
+ high += low;
+ }
+
+ print_disassembly (gdbarch, name, low, high, flags);
+}
+