aboutsummaryrefslogtreecommitdiff
path: root/gdb/cli
diff options
context:
space:
mode:
authorFernando Nasser <fnasser@redhat.com>2002-09-20 14:58:59 +0000
committerFernando Nasser <fnasser@redhat.com>2002-09-20 14:58:59 +0000
commit0378c3323148fbb291d1035d9959de9d9c3a0f7b (patch)
tree7a24175361aea3a17223b0a3cea75e08f2c97eb4 /gdb/cli
parent7cf108933bd1b2e94d4bd531583060262abd543c (diff)
downloadgdb-0378c3323148fbb291d1035d9959de9d9c3a0f7b.zip
gdb-0378c3323148fbb291d1035d9959de9d9c3a0f7b.tar.gz
gdb-0378c3323148fbb291d1035d9959de9d9c3a0f7b.tar.bz2
* 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.
Diffstat (limited to 'gdb/cli')
-rw-r--r--gdb/cli/cli-cmds.c342
1 files changed, 341 insertions, 1 deletions
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 799e1f4..0b5b857 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -25,7 +25,12 @@
#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"
@@ -51,7 +56,7 @@ extern void set_history (char *, int);
extern void show_commands (char *, int);
-/* Prototypes for local functions */
+/* Prototypes for local command functions */
static void complete_command (char *, int);
@@ -79,7 +84,15 @@ static void make_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 *);
/* Limit the call depth of user-defined commands */
int max_user_call_depth;
@@ -526,6 +539,281 @@ shell_escape (char *arg, int from_tty)
}
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)
{
char *p;
@@ -594,6 +882,21 @@ apropos_command (char *searchstr, int from_tty)
xfree (pattern_fastmap);
}
+/* 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)
{
@@ -812,6 +1115,43 @@ from the target.", &setlist),
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''