current_source_line static.
(list_command): Moved to cli/cli-cmds.c.
(ambiguous_line_spec): Moved to cli/cli-cmds.c.
(get_first_line_listed): New accessor function.
(get_lines_to_list): New accessor function.
(get_current_source_symtab_and_line): New function. Retrieves the
position in the source code that we consider current.
(get_current_or_default_source_symtab_and_line): New function.
Like the above but attempts to determine a default position if one
is not currently defined.
(set_current_source_symtab_and_line): New function. Sets the source
code position considered current and returns the previously set one.
(clear_current_source_symtab_and_line): Reset stored information about
a current source line.
(_initialize_source): Remove registration for the "list" command and
its alias.
* source.h: Add declarations for the new functions above.
* symtab.h: Remove declarations for the global variables mentioned
above.
* breakpoint.c (parse_breakpoint_sals): Use accessor functions to
obtain current source line.
* linespec.c (decode_line_1): Ditto.
* macroscope.c (default_macro_scope): Ditto.
* scm-lang.c (scm_unpac): Ditto.
* stack.c (print_frame_info_base): Ditto.
* symfile.c (clear_symtab_users): Ditto.
* symtab.c (decode_line_spec): Ditto.
* cli/cli-cmds.c (list_command): Moved here from source.c.
(ambiguous_line_spec): Moved here from source.c.
(_init_cli_cmds): Add definition for "list" and its alias.
* Makefile.in: Update dependencies.
+2002-09-13 Fernando Nasser <fnasser@redhat.com>
+
+ * source.c: Make global variables current_source_symtab and
+ current_source_line static.
+ (list_command): Moved to cli/cli-cmds.c.
+ (ambiguous_line_spec): Moved to cli/cli-cmds.c.
+ (get_first_line_listed): New accessor function.
+ (get_lines_to_list): New accessor function.
+ (get_current_source_symtab_and_line): New function. Retrieves the
+ position in the source code that we consider current.
+ (get_current_or_default_source_symtab_and_line): New function.
+ Like the above but attempts to determine a default position if one
+ is not currently defined.
+ (set_current_source_symtab_and_line): New function. Sets the source
+ code position considered current and returns the previously set one.
+ (clear_current_source_symtab_and_line): Reset stored information about
+ a current source line.
+ (_initialize_source): Remove registration for the "list" command and
+ its alias.
+ * source.h: Add declarations for the new functions above.
+ * symtab.h: Remove declarations for the global variables mentioned
+ above.
+ * breakpoint.c (parse_breakpoint_sals): Use accessor functions to
+ obtain current source line.
+ * linespec.c (decode_line_1): Ditto.
+ * macroscope.c (default_macro_scope): Ditto.
+ * scm-lang.c (scm_unpac): Ditto.
+ * stack.c (print_frame_info_base): Ditto.
+ * symfile.c (clear_symtab_users): Ditto.
+ * symtab.c (decode_line_spec): Ditto.
+ * cli/cli-cmds.c (list_command): Moved here from source.c.
+ (ambiguous_line_spec): Moved here from source.c.
+ (_init_cli_cmds): Add definition for "list" and its alias.
+ * Makefile.in: Update dependencies.
+
2002-09-20 Corinna Vinschen <vinschen@redhat.com>
* h8300-tdep.c (h8300_examine_prologue): Match saved regs location
$(command_h) $(inferior_h) $(gdbthread_h) $(target_h) $(language_h) \
$(gdb_string_h) $(demangle_h) $(annotate_h) $(symfile_h) \
$(objfiles_h) $(linespec_h) $(completer_h) $(gdb_h) $(ui_out_h) \
- $(cli_script_h) $(gdb_events_h)
+ $(cli_script_h) $(gdb_events_h) $(source_h)
buildsym.o: buildsym.c $(defs_h) $(bfd_h) $(gdb_obstack_h) $(symtab_h) \
$(symfile_h) $(objfiles_h) $(gdbtypes_h) $(complaints_h) \
$(gdb_string_h) $(expression_h) $(language_h) $(bcache_h) \
$(gdbthread_h) $(inferior_h) $(target_h) $(regcache_h) $(gdbcmd_h)
linespec.o: linespec.c $(defs_h) $(symtab_h) $(frame_h) $(command_h) \
$(symfile_h) $(objfiles_h) $(demangle_h) $(value_h) $(completer_h) \
- $(cp_abi_h)
+ $(cp_abi_h) $(source_h)
linux-proc.o: linux-proc.c $(defs_h) $(inferior_h) $(regcache_h) \
$(gregset_h) $(gdbcore_h) $(gdbthread_h) $(elf_bfd_h) \
$(cli_decode_h) $(gdb_string_h)
macroexp.o: macroexp.c $(defs_h) $(gdb_obstack_h) $(bcache_h) $(macrotab_h) \
$(macroexp_h) $(gdb_assert_h)
macroscope.o: macroscope.c $(defs_h) $(macroscope_h) $(symtab_h) $(target_h) \
- $(frame_h) $(inferior_h)
+ $(frame_h) $(inferior_h) $(source_h)
macrotab.o: macrotab.c $(defs_h) $(gdb_obstack_h) $(splay_tree_h) \
$(symtab_h) $(symfile_h) $(objfiles_h) $(macrotab_h) $(gdb_assert_h) \
$(bcache_h) $(complaints_h)
$(scm_tags_h)
scm-lang.o: scm-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
$(parser_defs_h) $(language_h) $(value_h) $(c_lang_h) $(scm_lang_h) \
- $(scm_tags_h) $(gdb_string_h) $(gdbcore_h)
+ $(scm_tags_h) $(gdb_string_h) $(gdbcore_h) $(source_h)
scm-valprint.o: scm-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \
$(expression_h) $(parser_defs_h) $(language_h) $(value_h) \
$(scm_lang_h) $(valprint_h) $(gdbcore_h)
stack.o: stack.c $(defs_h) $(gdb_string_h) $(value_h) $(symtab_h) \
$(gdbtypes_h) $(expression_h) $(language_h) $(frame_h) $(gdbcmd_h) \
$(gdbcore_h) $(target_h) $(breakpoint_h) $(demangle_h) $(inferior_h) \
- $(annotate_h) $(ui_out_h)
+ $(annotate_h) $(ui_out_h) $(source_h)
standalone.o: standalone.c $(gdb_stat_h) $(defs_h) $(symtab_h) $(frame_h) \
$(inferior_h) $(gdb_wait_h)
std-regs.o: std-regs.c $(defs_h) $(builtin_regs_h) $(frame_h) $(gdbtypes_h) \
$(frame_h) $(target_h) $(value_h) $(symfile_h) $(objfiles_h) \
$(gdbcmd_h) $(breakpoint_h) $(language_h) $(complaints_h) \
$(demangle_h) $(inferior_h) $(gdb_stabs_h) $(gdb_obstack_h) \
- $(completer_h) $(bcache_h) $(gdb_string_h) $(gdb_stat_h)
+ $(completer_h) $(bcache_h) $(gdb_string_h) $(gdb_stat_h) $(source_h)
symm-nat.o: symm-nat.c $(defs_h) $(frame_h) $(inferior_h) $(symtab_h) \
$(target_h) $(regcache_h) $(gdb_stat_h) $(gdbcore_h) $(gdbcore_h)
symm-tdep.o: symm-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(symtab_h) \
$(gdbcmd_h) $(call_cmds_h) $(gdb_regex_h) $(expression_h) \
$(language_h) $(demangle_h) $(inferior_h) $(linespec_h) \
$(filenames_h) $(gdb_obstack_h) $(gdb_string_h) $(gdb_stat_h) \
- $(cp_abi_h)
+ $(cp_abi_h) $(source_h)
target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \
$(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \
$(gdb_wait_h) $(dcache_h) $(regcache_h)
cli-cmds.o: $(srcdir)/cli/cli-cmds.c $(defs_h) $(completer_h) $(target_h) \
$(gdb_wait_h) $(gdb_regex_h) $(gdb_string_h) $(filenames_h) \
$(ui_out_h) $(top_h) $(cli_decode_h) $(cli_script_h) \
- $(cli_setshow_h) $(cli_cmds_h)
+ $(cli_setshow_h) $(cli_cmds_h) $(source_h) $(linespec_h) \
+ $(expression_h) $(language_h) $(objfiles_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-cmds.c
cli-decode.o: $(srcdir)/cli/cli-decode.c $(defs_h) $(symtab_h) \
$(gdb_regex_h) $(gdb_string_h) $(ui_out_h) $(cli_cmds_h) \
#include "annotate.h"
#include "symfile.h"
#include "objfiles.h"
+#include "source.h"
#include "linespec.h"
#include "completer.h"
#include "gdb.h"
current_source_symtab (which is decode_line_1's default). This
should produce the results we want almost all of the time while
leaving default_breakpoint_* alone. */
+
+ struct symtab_and_line cursal =
+ get_current_or_default_source_symtab_and_line ();
+
if (default_breakpoint_valid
- && (!current_source_symtab
+ && (!cursal.symtab
|| (strchr ("+-", (*address)[0]) != NULL)))
*sals = decode_line_1 (address, 1, default_breakpoint_symtab,
default_breakpoint_line, addr_string);
#include "gdb_wait.h" /* For shell escape implementation */
#include "gdb_regex.h" /* Used by apropos_command */
#include "gdb_string.h"
+#include "linespec.h"
+#include "expression.h"
+#include "language.h"
#include "filenames.h" /* for DOSish file names */
+#include "objfiles.h"
+#include "source.h"
#include "ui-out.h"
extern void show_commands (char *, int);
-/* Prototypes for local functions */
+/* Prototypes for local command functions */
static void complete_command (char *, int);
static void shell_escape (char *, int);
+static void edit_command (char *, int);
+
+static void list_command (char *, int);
+
void apropos_command (char *, int);
+
+/* Prototypes for local utility functions */
+
+static void ambiguous_line_spec (struct symtabs_and_lines *);
\f
/* Limit the call depth of user-defined commands */
int max_user_call_depth;
#endif /* Can fork. */
}
+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;
+
+ /* Pull in the current default source line if necessary */
+ if (arg == 0)
+ sal = get_current_or_default_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);
+
+ 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.",
+ local_hex_string((unsigned long) sal.pc));
+ sym = find_pc_function (sal.pc);
+ if (sym)
+ {
+ print_address_numeric (sal.pc, 1, gdb_stdout);
+ printf_filtered (" is in ");
+ fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
+ printf_filtered (" (%s:%d).\n", sal.symtab->filename, sal.line);
+ }
+ else
+ {
+ 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);
+
+ cmdlen = strlen(editor) + 1
+ + (NULL == sal.symtab->dirname ? 0 : strlen(sal.symtab->dirname) + 1)
+ + (NULL == sal.symtab->filename? 0 : strlen(sal.symtab->filename)+ 1)
+ + log10 + 2;
+
+ p = xmalloc(cmdlen);
+ sprintf(p,"%s +%d %s%s",editor,sal.line,
+ (NULL == sal.symtab->dirname ? "./" :
+ (NULL != sal.symtab->filename && *(sal.symtab->filename) != '/') ?
+ sal.symtab->dirname : ""),
+ (NULL == sal.symtab->filename ? "unknown" : sal.symtab->filename)
+ );
+ 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, sal_end, cursal;
+ 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] == '-')
+ cursal = get_current_or_default_source_symtab_and_line ();
+
+ /* "l" or "l +" lists next ten lines. */
+
+ if (arg == 0 || STREQ (arg, "+"))
+ {
+ 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 (STREQ (arg, "-"))
+ {
+ 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);
+
+ 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);
+ else
+ sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 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.",
+ local_hex_string ((unsigned long) sal.pc));
+ sym = find_pc_function (sal.pc);
+ if (sym)
+ {
+ print_address_numeric (sal.pc, 1, gdb_stdout);
+ printf_filtered (" is in ");
+ fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
+ printf_filtered (" (%s:%d).\n", sal.symtab->filename, sal.line);
+ }
+ else
+ {
+ 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);
+}
+
static void
make_command (char *arg, int from_tty)
{
xfree (pattern_fastmap);
}
\f
+/* Print a list of files and line numbers which a user may choose from
+ in order to list a function which was specified ambiguously (as with
+ `list classname::overloadedfuncname', for example). The vector in
+ SALS provides the filenames and line numbers. */
+
+static void
+ambiguous_line_spec (struct symtabs_and_lines *sals)
+{
+ int i;
+
+ for (i = 0; i < sals->nelts; ++i)
+ printf_filtered ("file: \"%s\", line number: %d\n",
+ sals->sals[i].symtab->filename, sals->sals[i].line);
+}
+
static void
set_debug (char *arg, int from_tty)
{
With no arguments, run an inferior shell.");
set_cmd_completer (c, filename_completer);
+ c = add_com ("edit", class_files, edit_command,
+ concat ("Edit specified file or function.\n\
+With no argument, edits file containing most recent line listed.\n\
+", "\
+Editing targets can be specified in these ways:\n\
+ FILE:LINENUM, to edit at that line in that file,\n\
+ FUNCTION, to edit at the beginning of that function,\n\
+ FILE:FUNCTION, to distinguish among like-named static functions.\n\
+ *ADDRESS, to edit at the line containing that address.\n\
+Uses EDITOR environment variable contents as editor (or ex as default).",NULL));
+
+ c->completer = location_completer;
+
+ add_com ("list", class_files, list_command,
+ concat ("List specified function or line.\n\
+With no argument, lists ten more lines after or around previous listing.\n\
+\"list -\" lists the ten lines before a previous ten-line listing.\n\
+One argument specifies a line, and ten lines are listed around that line.\n\
+Two arguments with comma between specify starting and ending lines to list.\n\
+", "\
+Lines can be specified in these ways:\n\
+ LINENUM, to list around that line in current file,\n\
+ FILE:LINENUM, to list around that line in that file,\n\
+ FUNCTION, to list around beginning of that function,\n\
+ FILE:FUNCTION, to distinguish among like-named static functions.\n\
+ *ADDRESS, to list around the line containing that address.\n\
+With two args if one is empty it stands for ten lines away from the other arg.", NULL));
+
+ if (!xdb_commands)
+ add_com_alias ("l", "list", class_files, 1);
+ else
+ add_com_alias ("v", "list", class_files, 1);
+
+ if (dbx_commands)
+ add_com_alias ("file", "list", class_files, 1);
+
+
/* NOTE: cagney/2000-03-20: Being able to enter ``(gdb) !ls'' would
be a really useful feature. Unfortunately, the below wont do
this. Instead it adds support for the form ``(gdb) ! ls''
#include "command.h"
#include "symfile.h"
#include "objfiles.h"
+#include "source.h"
#include "demangle.h"
#include "value.h"
#include "completer.h"
if (default_symtab == 0)
{
- default_symtab = current_source_symtab;
- default_line = current_source_line;
+ /* Use whatever we have for the default source line. We don't use
+ get_current_or_default_symtab_and_line as it can recurse and call
+ us back! */
+ struct symtab_and_line cursal =
+ get_current_source_symtab_and_line ();
+
+ default_symtab = cursal.symtab;
+ default_line = cursal.line;
}
/* See if arg is *PC */
/* This is where we need to make sure that we have good defaults.
We must guarantee that this section of code is never executed
when we are called with just a function name, since
- select_source_symtab calls us with such an argument */
+ get_current_or_default_source_symtab_and_line uses
+ select_source_symtab that calls us with such an argument */
if (s == 0 && default_symtab == 0)
{
- select_source_symtab (0);
- default_symtab = current_source_symtab;
- default_line = current_source_line;
+ struct symtab_and_line cursal =
+ get_current_or_default_source_symtab_and_line ();
+
+ default_symtab = cursal.symtab;
+ default_line = cursal.line;
}
if (**argptr == '+')
#include "macroscope.h"
#include "symtab.h"
+#include "source.h"
#include "target.h"
#include "frame.h"
#include "inferior.h"
evaluator to evaluate their numeric arguments. If the
current language is C, then that may call this function to
choose a scope for macro expansion. If you don't have any
- symbol files loaded, then select_source_symtab will raise an
+ symbol files loaded, then get_current_or_default would raise an
error. But `set width' shouldn't raise an error just because
it can't decide which scope to macro-expand its argument in. */
- sal.symtab = current_source_symtab;
- sal.line = current_source_line;
+ struct symtab_and_line cursal =
+ get_current_source_symtab_and_line ();
+
+ sal.symtab = cursal.symtab;
+ sal.line = cursal.line;
}
return sal_macro_scope (sal);
#include "c-lang.h"
#include "scm-lang.h"
#include "scm-tags.h"
+#include "source.h"
#include "gdb_string.h"
#include "gdbcore.h"
static int
in_eval_c (void)
{
- if (current_source_symtab && current_source_symtab->filename)
+ struct symtab_and_line cursal =
+ get_current_or_default_source_symtab_and_line ();
+
+ if (cursal.symtab && cursal.symtab->filename)
{
- char *filename = current_source_symtab->filename;
+ char *filename = cursal.symtab->filename;
int len = strlen (filename);
if (len >= 6 && strcmp (filename + len - 6, "eval.c") == 0)
return 1;
static void line_info (char *, int);
-static void list_command (char *, int);
-
static void ambiguous_line_spec (struct symtabs_and_lines *);
static void source_info (char *, int);
/* Symtab of default file for listing lines of. */
-struct symtab *current_source_symtab;
+static struct symtab *current_source_symtab;
/* Default next line to list. */
-int current_source_line;
+static int current_source_line;
/* Default number of lines to print with commands like "list".
This is based on guessing how many long (i.e. more than chars_per_line
static struct symtab *last_source_visited = NULL;
static int last_source_error = 0;
\f
+/* Return the first line listed by print_source_lines.
+ Used by command interpreters to request listing from
+ a previous point. */
+
+int
+get_first_line_listed (void)
+{
+ return first_line_listed;
+}
+
+/* Return the default number of lines to print with commands like the
+ cli "list". The caller of print_source_lines must use this to
+ calculate the end line and use it in the call to print_source_lines
+ as it does not automatically use this value. */
+
+int
+get_lines_to_list (void)
+{
+ return lines_to_list;
+}
+
+/* Return the current source file for listing and next line to list.
+ NOTE: The returned sal pc and end fields are not valid. */
+
+struct symtab_and_line
+get_current_source_symtab_and_line (void)
+{
+ struct symtab_and_line cursal;
+
+ cursal.symtab = current_source_symtab;
+ cursal.line = current_source_line;
+
+ return cursal;
+}
+
+/* Return the current source file for listing and next line to list.
+ If a file is not set, try and get a default.
+ It may err out if a default cannot be determined.
+ Depending on where it is called, it can recurse as the process of
+ determining a new default may call the caler!
+ Use get_current_source_symtab_and_line instead to get whatever
+ we have without erroring out or trying to get a default.
+ NOTE: The returned sal pc and end fields are not valid. */
+
+struct symtab_and_line
+get_current_or_default_source_symtab_and_line (void)
+{
+ struct symtab_and_line cursal;
+
+ if (!have_full_symbols () && !have_partial_symbols ())
+ error ("No symbol table is loaded. Use the \"file\" command.");
+
+ /* Pull in a current source symtab if necessary */
+ if (current_source_symtab == 0)
+ select_source_symtab (0);
+
+ cursal.symtab = current_source_symtab;
+ cursal.line = current_source_line;
+
+ return cursal;
+}
+
+/* Return the current default file for listing and next line to list
+ (the returned sal pc and end fields are not valid.)
+ and set the surrent default to whatever is in SAL */
+
+struct symtab_and_line
+set_current_source_symtab_and_line (struct symtab_and_line *sal)
+{
+ struct symtab_and_line cursal;
+
+ cursal.symtab = current_source_symtab;
+ cursal.line = current_source_line;
+
+ current_source_symtab = sal->symtab;
+ current_source_line = sal->line;
+
+ return cursal;
+}
+
+/* Reset any information stored about a default file and line to print. */
+
+void
+clear_current_source_symtab_and_line (void)
+{
+ current_source_symtab = 0;
+ current_source_line = 0;
+}
/* Set the source file default for the "list" command to be S.
print_source_lines_base (s, line, stopline, noerror);
}
\f
-
-
/* Print a list of files and line numbers which a user may choose from
in order to list a function which was specified ambiguously (as with
`list classname::overloadedfuncname', for example). The vector in
printf_filtered ("file: \"%s\", line number: %d\n",
sals->sals[i].symtab->filename, sals->sals[i].line);
}
-
-static void
-list_command (char *arg, int from_tty)
-{
- struct symtabs_and_lines sals, sals_end;
- struct symtab_and_line sal, sal_end;
- struct symbol *sym;
- char *arg1;
- int no_end = 1;
- int dummy_end = 0;
- int dummy_beg = 0;
- int linenum_beg = 0;
- char *p;
-
- if (!have_full_symbols () && !have_partial_symbols ())
- error ("No symbol table is loaded. Use the \"file\" command.");
-
- /* Pull in a current source symtab if necessary */
- if (current_source_symtab == 0 &&
- (arg == 0 || arg[0] == '+' || arg[0] == '-'))
- select_source_symtab (0);
-
- /* "l" or "l +" lists next ten lines. */
-
- if (arg == 0 || STREQ (arg, "+"))
- {
- if (current_source_symtab == 0)
- error ("No default source file yet. Do \"help list\".");
- print_source_lines (current_source_symtab, current_source_line,
- current_source_line + lines_to_list, 0);
- return;
- }
-
- /* "l -" lists previous ten lines, the ones before the ten just listed. */
- if (STREQ (arg, "-"))
- {
- if (current_source_symtab == 0)
- error ("No default source file yet. Do \"help list\".");
- print_source_lines (current_source_symtab,
- max (first_line_listed - lines_to_list, 1),
- 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. */
-
- arg1 = arg;
- if (*arg1 == ',')
- dummy_beg = 1;
- else
- {
- sals = decode_line_1 (&arg1, 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);
- else
- sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 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.",
- local_hex_string ((unsigned long) sal.pc));
- sym = find_pc_function (sal.pc);
- if (sym)
- {
- print_address_numeric (sal.pc, 1, gdb_stdout);
- printf_filtered (" is in ");
- fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
- printf_filtered (" (%s:%d).\n", sal.symtab->filename, sal.line);
- }
- else
- {
- 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 - (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 - lines_to_list / 2;
-
- if (first_line < 1) first_line = 1;
-
- print_source_lines (sal.symtab, first_line, first_line + lines_to_list,
- 0);
- }
- else
- print_source_lines (sal.symtab, sal.line,
- (dummy_end
- ? sal.line + lines_to_list
- : sal_end.line + 1),
- 0);
-}
\f
/* Print info on range of pc's in a specified line. */
add_com_alias ("?", "reverse-search", class_files, 0);
}
- add_com ("list", class_files, list_command,
- concat ("List specified function or line.\n\
-With no argument, lists ten more lines after or around previous listing.\n\
-\"list -\" lists the ten lines before a previous ten-line listing.\n\
-One argument specifies a line, and ten lines are listed around that line.\n\
-Two arguments with comma between specify starting and ending lines to list.\n\
-", "\
-Lines can be specified in these ways:\n\
- LINENUM, to list around that line in current file,\n\
- FILE:LINENUM, to list around that line in that file,\n\
- FUNCTION, to list around beginning of that function,\n\
- FILE:FUNCTION, to distinguish among like-named static functions.\n\
- *ADDRESS, to list around the line containing that address.\n\
-With two args if one is empty it stands for ten lines away from the other arg.", NULL));
-
- if (!xdb_commands)
- add_com_alias ("l", "list", class_files, 1);
- else
- add_com_alias ("v", "list", class_files, 1);
-
- if (dbx_commands)
- add_com_alias ("file", "list", class_files, 1);
-
add_show_from_set
(add_set_cmd ("listsize", class_support, var_uinteger,
(char *) &lines_to_list,
lines. */
extern void find_source_lines (struct symtab *s, int desc);
+/* Return the first line listed by print_source_lines.
+ Used by command interpreters to request listing from
+ a previous point. */
+extern int get_first_line_listed (void);
+
+/* Return the default number of lines to print with commands like the
+ cli "list". The caller of print_source_lines must use this to
+ calculate the end line and use it in the call to print_source_lines
+ as it does not automatically use this value. */
+extern int get_lines_to_list (void);
+
+/* Return the current source file for listing and next line to list.
+ NOTE: The returned sal pc and end fields are not valid. */
+extern void clear_current_source_symtab_and_line (void);
+
+/* Return the current source file for listing and next line to list.
+ If a file is not set, try and get a default.
+ It may err out if a default cannot be determined.
+ Depending on where it is called, it can recurse as the process of
+ determining a new default may call the caler!
+ Use get_current_source_symtab_and_line instead to get whatever
+ we have without erroring out or trying to get a default.
+ NOTE: The returned sal pc and end fields are not valid. */
+extern struct symtab_and_line get_current_source_symtab_and_line (void);
+
+/* Return the current default file for listing and next line to list
+ (the returned sal pc and end fields are not valid.)
+ and set the surrent default to whatever is in SAL */
+extern struct symtab_and_line get_current_or_default_source_symtab_and_line (void);
+
+/* Reset any information stored about a default file and line to print. */
+extern struct symtab_and_line set_current_source_symtab_and_line (struct symtab_and_line *);
#endif
#include "gdbcmd.h"
#include "gdbcore.h"
#include "target.h"
+#include "source.h"
#include "breakpoint.h"
#include "demangle.h"
#include "inferior.h"
static void frame_info (char *, int);
extern int addressprint; /* Print addresses, or stay symbolic only? */
-extern int lines_to_list; /* # of lines "list" command shows by default */
/* The "selected" stack frame is used by default for local and arg access.
May be zero, for no selected frame. */
print_frame (fi, level, source, args, sal);
source_print = (source == SRC_LINE || source == SRC_AND_LOC);
+
if (sal.symtab)
- {
- current_source_symtab = sal.symtab;
- current_source_line = sal.line;
- }
+ set_current_source_symtab_and_line (&sal);
if (source_print && sal.symtab)
{
+ struct symtab_and_line cursal;
int done = 0;
int mid_statement = (source == SRC_LINE) && (fi->pc != sal.pc);
print_source_lines (sal.symtab, sal.line, sal.line + 1, 0);
}
}
- current_source_line = max (sal.line - lines_to_list / 2, 1);
+ cursal = get_current_or_default_source_symtab_and_line ();
+ cursal.line = max (sal.line - get_lines_to_list () / 2, 1);
+ set_current_source_symtab_and_line (&cursal);
}
if (source != 0)
#include "value.h"
#include "symfile.h"
#include "objfiles.h"
+#include "source.h"
#include "gdbcmd.h"
#include "breakpoint.h"
#include "language.h"
clear_internalvars ();
breakpoint_re_set ();
set_default_breakpoint (0, 0, 0, 0);
- current_source_symtab = 0;
- current_source_line = 0;
+ clear_current_source_symtab_and_line ();
clear_pc_function_cache ();
if (target_new_objfile_hook)
target_new_objfile_hook (NULL);
#include "demangle.h"
#include "inferior.h"
#include "linespec.h"
+#include "source.h"
#include "filenames.h" /* for FILENAME_CMP */
#include "gdb_obstack.h"
decode_line_spec (char *string, int funfirstline)
{
struct symtabs_and_lines sals;
+ struct symtab_and_line cursal;
+
if (string == 0)
error ("Empty line specification.");
+
+ /* We use whatever is set as the current source line. We do not try
+ and get a default or it will recursively call us! */
+ cursal = get_current_source_symtab_and_line ();
+
sals = decode_line_1 (&string, funfirstline,
- current_source_symtab, current_source_line,
+ cursal.symtab, cursal.line,
(char ***) NULL);
+
if (*string)
error ("Junk at end of line specification: %s", string);
return sals;
/* External variables and functions for the objects described above. */
-/* This symtab variable specifies the current file for printing source lines */
-
-extern struct symtab *current_source_symtab;
-
-/* This is the next line to print for listing source lines. */
-
-extern int current_source_line;
-
/* See the comment in symfile.c about how current_objfile is used. */
extern struct objfile *current_objfile;