diff options
author | Fernando Nasser <fnasser@redhat.com> | 2002-09-20 14:58:59 +0000 |
---|---|---|
committer | Fernando Nasser <fnasser@redhat.com> | 2002-09-20 14:58:59 +0000 |
commit | 0378c3323148fbb291d1035d9959de9d9c3a0f7b (patch) | |
tree | 7a24175361aea3a17223b0a3cea75e08f2c97eb4 /gdb/cli | |
parent | 7cf108933bd1b2e94d4bd531583060262abd543c (diff) | |
download | gdb-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.c | 342 |
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'' |