Index: breakpoint.c =================================================================== RCS file: /cvs/src/src/gdb/breakpoint.c,v retrieving revision 1.86 diff -c -p -r1.86 breakpoint.c *** breakpoint.c 5 Sep 2002 01:28:14 -0000 1.86 --- breakpoint.c 13 Sep 2002 19:23:35 -0000 *************** *** 41,46 **** --- 41,47 ---- #include "annotate.h" #include "symfile.h" #include "objfiles.h" + #include "source.h" #include "linespec.h" #include "completer.h" #include "gdb.h" *************** parse_breakpoint_sals (char **address, *** 4618,4625 **** 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. */ if (default_breakpoint_valid ! && (!current_source_symtab || (strchr ("+-", (*address)[0]) != NULL))) *sals = decode_line_1 (address, 1, default_breakpoint_symtab, default_breakpoint_line, addr_string); --- 4619,4630 ---- 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 ! && (!cursal.symtab || (strchr ("+-", (*address)[0]) != NULL))) *sals = decode_line_1 (address, 1, default_breakpoint_symtab, default_breakpoint_line, addr_string); Index: linespec.c =================================================================== RCS file: /cvs/src/src/gdb/linespec.c,v retrieving revision 1.21 diff -c -p -r1.21 linespec.c *** linespec.c 11 May 2002 22:46:19 -0000 1.21 --- linespec.c 13 Sep 2002 19:23:36 -0000 *************** *** 26,31 **** --- 26,32 ---- #include "command.h" #include "symfile.h" #include "objfiles.h" + #include "source.h" #include "demangle.h" #include "value.h" #include "completer.h" *************** decode_line_1 (char **argptr, int funfir *** 545,552 **** if (default_symtab == 0) { ! default_symtab = current_source_symtab; ! default_line = current_source_line; } /* See if arg is *PC */ --- 546,559 ---- if (default_symtab == 0) { ! /* 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 */ *************** decode_line_1 (char **argptr, int funfir *** 1020,1032 **** /* 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 */ if (s == 0 && default_symtab == 0) { ! select_source_symtab (0); ! default_symtab = current_source_symtab; ! default_line = current_source_line; } if (**argptr == '+') --- 1027,1042 ---- /* 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 ! 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) { ! struct symtab_and_line cursal = ! get_current_or_default_source_symtab_and_line (); ! ! default_symtab = cursal.symtab; ! default_line = cursal.line; } if (**argptr == '+') Index: macroscope.c =================================================================== RCS file: /cvs/src/src/gdb/macroscope.c,v retrieving revision 1.3 diff -c -p -r1.3 macroscope.c *** macroscope.c 30 May 2002 00:02:03 -0000 1.3 --- macroscope.c 13 Sep 2002 19:23:36 -0000 *************** *** 23,28 **** --- 23,29 ---- #include "macroscope.h" #include "symtab.h" + #include "source.h" #include "target.h" #include "frame.h" #include "inferior.h" *************** default_macro_scope (void) *** 84,94 **** 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 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; } return sal_macro_scope (sal); --- 85,98 ---- 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 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. */ ! struct symtab_and_line cursal = ! get_current_source_symtab_and_line (); ! ! sal.symtab = cursal.symtab; ! sal.line = cursal.line; } return sal_macro_scope (sal); Index: scm-lang.c =================================================================== RCS file: /cvs/src/src/gdb/scm-lang.c,v retrieving revision 1.9 diff -c -p -r1.9 scm-lang.c *** scm-lang.c 23 Mar 2002 17:38:13 -0000 1.9 --- scm-lang.c 13 Sep 2002 19:23:36 -0000 *************** *** 29,34 **** --- 29,35 ---- #include "c-lang.h" #include "scm-lang.h" #include "scm-tags.h" + #include "source.h" #include "gdb_string.h" #include "gdbcore.h" *************** scm_unpack (struct type *type, char *val *** 133,141 **** static int in_eval_c (void) { ! if (current_source_symtab && current_source_symtab->filename) { ! char *filename = current_source_symtab->filename; int len = strlen (filename); if (len >= 6 && strcmp (filename + len - 6, "eval.c") == 0) return 1; --- 134,145 ---- static int in_eval_c (void) { ! struct symtab_and_line cursal = ! get_current_or_default_source_symtab_and_line (); ! ! if (cursal.symtab && cursal.symtab->filename) { ! char *filename = cursal.symtab->filename; int len = strlen (filename); if (len >= 6 && strcmp (filename + len - 6, "eval.c") == 0) return 1; Index: source.c =================================================================== RCS file: /cvs/src/src/gdb/source.c,v retrieving revision 1.29 diff -c -p -r1.29 source.c *** source.c 11 Jun 2002 20:36:51 -0000 1.29 --- source.c 13 Sep 2002 19:23:37 -0000 *************** static void forward_search_command (char *** 79,86 **** 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); --- 79,84 ---- *************** char *source_path; *** 94,104 **** /* Symtab of default file for listing lines of. */ ! struct symtab *current_source_symtab; /* Default next line to list. */ ! 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 --- 92,102 ---- /* Symtab of default file for listing lines of. */ ! static struct symtab *current_source_symtab; /* Default next line to list. */ ! 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 int first_line_listed; *** 123,128 **** --- 121,214 ---- static struct symtab *last_source_visited = NULL; static int last_source_error = 0; + /* 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 (struct symtab *s, in *** 1110,1117 **** print_source_lines_base (s, line, stopline, noerror); } - - /* 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 --- 1196,1201 ---- *************** ambiguous_line_spec (struct symtabs_and_ *** 1126,1307 **** 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); - } /* Print info on range of pc's in a specified line. */ --- 1210,1215 ---- *************** The matching line number is also stored *** 1661,1689 **** add_com_alias ("/", "forward-search", class_files, 0); 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, --- 1569,1574 ---- Index: source.h =================================================================== RCS file: /cvs/src/src/gdb/source.h,v retrieving revision 1.1.1.1 diff -c -p -r1.1.1.1 source.h *** source.h 22 Sep 1999 03:25:04 -0000 1.1.1.1 --- source.h 13 Sep 2002 19:23:37 -0000 *************** extern int open_source_file (struct symt *** 31,34 **** --- 31,66 ---- 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 Index: stack.c =================================================================== RCS file: /cvs/src/src/gdb/stack.c,v retrieving revision 1.42 diff -c -p -r1.42 stack.c *** stack.c 29 Aug 2002 19:59:35 -0000 1.42 --- stack.c 13 Sep 2002 19:23:37 -0000 *************** *** 33,38 **** --- 33,39 ---- #include "gdbcmd.h" #include "gdbcore.h" #include "target.h" + #include "source.h" #include "breakpoint.h" #include "demangle.h" #include "inferior.h" *************** struct frame_info *parse_frame_specifica *** 108,114 **** 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. */ --- 109,114 ---- *************** print_frame_info_base (struct frame_info *** 398,411 **** 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; ! } if (source_print && sal.symtab) { int done = 0; int mid_statement = (source == SRC_LINE) && (fi->pc != sal.pc); --- 398,410 ---- print_frame (fi, level, source, args, sal); source_print = (source == SRC_LINE || source == SRC_AND_LOC); + if (sal.symtab) ! 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_frame_info_base (struct frame_info *** 435,441 **** print_source_lines (sal.symtab, sal.line, sal.line + 1, 0); } } ! current_source_line = max (sal.line - lines_to_list / 2, 1); } if (source != 0) --- 434,442 ---- print_source_lines (sal.symtab, sal.line, sal.line + 1, 0); } } ! 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) Index: symfile.c =================================================================== RCS file: /cvs/src/src/gdb/symfile.c,v retrieving revision 1.65 diff -c -p -r1.65 symfile.c *** symfile.c 1 Aug 2002 17:18:32 -0000 1.65 --- symfile.c 13 Sep 2002 19:23:37 -0000 *************** *** 31,36 **** --- 31,37 ---- #include "value.h" #include "symfile.h" #include "objfiles.h" + #include "source.h" #include "gdbcmd.h" #include "breakpoint.h" #include "language.h" *************** clear_symtab_users (void) *** 2118,2125 **** clear_internalvars (); breakpoint_re_set (); set_default_breakpoint (0, 0, 0, 0); ! current_source_symtab = 0; ! current_source_line = 0; clear_pc_function_cache (); if (target_new_objfile_hook) target_new_objfile_hook (NULL); --- 2119,2125 ---- clear_internalvars (); breakpoint_re_set (); set_default_breakpoint (0, 0, 0, 0); ! clear_current_source_symtab_and_line (); clear_pc_function_cache (); if (target_new_objfile_hook) target_new_objfile_hook (NULL); Index: symtab.c =================================================================== RCS file: /cvs/src/src/gdb/symtab.c,v retrieving revision 1.69 diff -c -p -r1.69 symtab.c *** symtab.c 30 Aug 2002 03:24:00 -0000 1.69 --- symtab.c 13 Sep 2002 19:23:38 -0000 *************** *** 38,43 **** --- 38,44 ---- #include "demangle.h" #include "inferior.h" #include "linespec.h" + #include "source.h" #include "filenames.h" /* for FILENAME_CMP */ #include "gdb_obstack.h" *************** struct symtabs_and_lines *** 3967,3977 **** decode_line_spec (char *string, int funfirstline) { struct symtabs_and_lines sals; if (string == 0) error ("Empty line specification."); sals = decode_line_1 (&string, funfirstline, ! current_source_symtab, current_source_line, (char ***) NULL); if (*string) error ("Junk at end of line specification: %s", string); return sals; --- 3968,3986 ---- 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, ! cursal.symtab, cursal.line, (char ***) NULL); + if (*string) error ("Junk at end of line specification: %s", string); return sals; Index: symtab.h =================================================================== RCS file: /cvs/src/src/gdb/symtab.h,v retrieving revision 1.39 diff -c -p -r1.39 symtab.h *** symtab.h 12 Sep 2002 19:19:37 -0000 1.39 --- symtab.h 13 Sep 2002 19:23:38 -0000 *************** struct partial_symtab *** 1035,1048 **** /* 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; --- 1035,1040 ---- Index: cli/cli-cmds.c =================================================================== RCS file: /cvs/src/src/gdb/cli/cli-cmds.c,v retrieving revision 1.20 diff -c -p -r1.20 cli-cmds.c *** cli/cli-cmds.c 30 Jul 2002 13:45:14 -0000 1.20 --- cli/cli-cmds.c 13 Sep 2002 19:23:38 -0000 *************** *** 25,31 **** --- 25,36 ---- #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 set_history (char *, int); *** 51,57 **** extern void show_commands (char *, int); ! /* Prototypes for local functions */ static void complete_command (char *, int); --- 56,62 ---- extern void show_commands (char *, int); ! /* Prototypes for local command functions */ static void complete_command (char *, int); *************** static void make_command (char *, int); *** 79,85 **** --- 84,98 ---- 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; *************** shell_escape (char *arg, int from_tty) *** 526,531 **** --- 539,819 ---- } 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; *************** apropos_command (char *searchstr, int fr *** 594,599 **** --- 882,902 ---- 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) { *************** from the target.", &setlist), *** 811,816 **** --- 1114,1156 ---- "Execute the rest of the line as a shell command.\n\ 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