+static void
+edit_command (char *arg, int from_tty)
+{
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ struct symbol *sym;
+ char *arg1;
+ int cmdlen, log10;
+ unsigned m;
+ 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) return; /* C++ */
+ 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 == '*')
+ {
+ 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));
+ sym = find_pc_function (sal.pc);
+ if (sym)
+ {
+ deprecated_print_address_numeric (sal.pc, 1, gdb_stdout);
+ printf_filtered (" is in ");
+ fputs_filtered (SYMBOL_PRINT_NAME (sym), gdb_stdout);
+ printf_filtered (" (%s:%d).\n", sal.symtab->filename, sal.line);
+ }
+ else
+ {
+ deprecated_print_address_numeric (sal.pc, 1, gdb_stdout);
+ printf_filtered (" is at %s:%d.\n",
+ 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";
+
+ /* Approximate base-10 log of line to 1 unit for digit count */
+ for(log10=32, m=0x80000000; !(sal.line & m) && log10>0; log10--, m=m>>1);
+ log10 = 1 + (int)((log10 + (0 == ((m-1) & sal.line)))/3.32192809);
+
+ /* 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 == '*')
+ {
+ 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));
+ sym = find_pc_function (sal.pc);
+ if (sym)
+ {
+ deprecated_print_address_numeric (sal.pc, 1, gdb_stdout);
+ printf_filtered (" is in ");
+ fputs_filtered (SYMBOL_PRINT_NAME (sym), gdb_stdout);
+ printf_filtered (" (%s:%d).\n", sal.symtab->filename, sal.line);
+ }
+ else
+ {
+ deprecated_print_address_numeric (sal.pc, 1, gdb_stdout);
+ printf_filtered (" is at %s:%d.\n",
+ 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);
+}
+
+/* Dump a specified section of assembly code. With no command line
+ arguments, this command will dump the assembly code for the
+ function surrounding the pc value in the selected frame. With one
+ argument, it will dump the assembly code surrounding that pc value.
+ Two arguments are interpeted as bounds within which to dump
+ assembly. */
+
+static void
+disassemble_command (char *arg, int from_tty)
+{
+ CORE_ADDR low, high;
+ char *name;
+ CORE_ADDR pc, pc_masked;
+ char *space_index;
+#if 0
+ asection *section;
+#endif
+
+ name = NULL;
+ if (!arg)
+ {
+ pc = get_frame_pc (get_selected_frame (_("No frame selected.")));
+ 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 (low, pc);
+#endif
+ low += gdbarch_deprecated_function_start_offset (current_gdbarch);
+ }
+ else if (!(space_index = (char *) strchr (arg, ' ')))
+ {
+ /* One argument. */
+ pc = parse_and_eval_address (arg);
+ 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 (low, pc);
+#endif
+ low += gdbarch_deprecated_function_start_offset (current_gdbarch);
+ }
+ else
+ {
+ /* Two arguments. */
+ *space_index = '\0';
+ low = parse_and_eval_address (arg);
+ high = parse_and_eval_address (space_index + 1);
+ }
+
+#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 ");
+ deprecated_print_address_numeric (low, 1, gdb_stdout);
+ printf_filtered (" to ");
+ deprecated_print_address_numeric (high, 1, gdb_stdout);
+ printf_filtered (":\n");
+ }
+
+ /* Dump the specified range. */
+ gdb_disassembly (uiout, 0, 0, 0, -1, low, high);
+
+ printf_filtered ("End of assembler dump.\n");
+ gdb_flush (gdb_stdout);
+ }
+#if defined(TUI)
+ else
+ {
+ tui_show_assembly (low);
+ }
+#endif
+}
+