119370Spst/* List lines of source files for GDB, the GNU debugger. 298944Sobrien Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 3130803Smarcel 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 419370Spst Free Software Foundation, Inc. 519370Spst 698944Sobrien This file is part of GDB. 719370Spst 898944Sobrien This program is free software; you can redistribute it and/or modify 998944Sobrien it under the terms of the GNU General Public License as published by 1098944Sobrien the Free Software Foundation; either version 2 of the License, or 1198944Sobrien (at your option) any later version. 1219370Spst 1398944Sobrien This program is distributed in the hope that it will be useful, 1498944Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1598944Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1698944Sobrien GNU General Public License for more details. 1719370Spst 1898944Sobrien You should have received a copy of the GNU General Public License 1998944Sobrien along with this program; if not, write to the Free Software 2098944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 2198944Sobrien Boston, MA 02111-1307, USA. */ 2219370Spst 2319370Spst#include "defs.h" 2419370Spst#include "symtab.h" 2519370Spst#include "expression.h" 2619370Spst#include "language.h" 2719370Spst#include "command.h" 2898944Sobrien#include "source.h" 2919370Spst#include "gdbcmd.h" 3019370Spst#include "frame.h" 3119370Spst#include "value.h" 3219370Spst 3319370Spst#include <sys/types.h> 3419370Spst#include "gdb_string.h" 3519370Spst#include "gdb_stat.h" 3619370Spst#include <fcntl.h> 3719370Spst#include "gdbcore.h" 3898944Sobrien#include "gdb_regex.h" 3919370Spst#include "symfile.h" 4019370Spst#include "objfiles.h" 4119370Spst#include "annotate.h" 4219370Spst#include "gdbtypes.h" 4398944Sobrien#include "linespec.h" 4498944Sobrien#include "filenames.h" /* for DOSish file names */ 4598944Sobrien#include "completer.h" 4698944Sobrien#include "ui-out.h" 47130803Smarcel#include "readline/readline.h" 4819370Spst 4946283Sdfr#ifdef CRLF_SOURCE_FILES 5046283Sdfr 5146283Sdfr/* Define CRLF_SOURCE_FILES in an xm-*.h file if source files on the 5246283Sdfr host use \r\n rather than just \n. Defining CRLF_SOURCE_FILES is 5346283Sdfr much faster than defining LSEEK_NOT_LINEAR. */ 5446283Sdfr 5546283Sdfr#ifndef O_BINARY 5646283Sdfr#define O_BINARY 0 5746283Sdfr#endif 5846283Sdfr 5946283Sdfr#define OPEN_MODE (O_RDONLY | O_BINARY) 6046283Sdfr#define FDOPEN_MODE FOPEN_RB 6146283Sdfr 6246283Sdfr#else /* ! defined (CRLF_SOURCE_FILES) */ 6346283Sdfr 6446283Sdfr#define OPEN_MODE O_RDONLY 6546283Sdfr#define FDOPEN_MODE FOPEN_RT 6646283Sdfr 6746283Sdfr#endif /* ! defined (CRLF_SOURCE_FILES) */ 6846283Sdfr 6946283Sdfr/* Prototypes for exported functions. */ 7046283Sdfr 7198944Sobrienvoid _initialize_source (void); 7246283Sdfr 7319370Spst/* Prototypes for local functions. */ 7419370Spst 7598944Sobrienstatic int get_filename_and_charpos (struct symtab *, char **); 7619370Spst 7798944Sobrienstatic void reverse_search_command (char *, int); 7819370Spst 7998944Sobrienstatic void forward_search_command (char *, int); 8019370Spst 8198944Sobrienstatic void line_info (char *, int); 8219370Spst 8398944Sobrienstatic void source_info (char *, int); 8419370Spst 8598944Sobrienstatic void show_directories (char *, int); 8619370Spst 8719370Spst/* Path of directories to search for source files. 8819370Spst Same format as the PATH environment variable's value. */ 8919370Spst 9019370Spstchar *source_path; 9119370Spst 9219370Spst/* Symtab of default file for listing lines of. */ 9319370Spst 94130803Smarcelstatic struct symtab *current_source_symtab; 9519370Spst 9619370Spst/* Default next line to list. */ 9719370Spst 98130803Smarcelstatic int current_source_line; 9919370Spst 10019370Spst/* Default number of lines to print with commands like "list". 10119370Spst This is based on guessing how many long (i.e. more than chars_per_line 10219370Spst characters) lines there will be. To be completely correct, "list" 10319370Spst and friends should be rewritten to count characters and see where 10419370Spst things are wrapping, but that would be a fair amount of work. */ 10519370Spst 10619370Spstint lines_to_list = 10; 10719370Spst 10819370Spst/* Line number of last line printed. Default for various commands. 10919370Spst current_source_line is usually, but not always, the same as this. */ 11019370Spst 11119370Spststatic int last_line_listed; 11219370Spst 11319370Spst/* First line number listed by last listing command. */ 11419370Spst 11519370Spststatic int first_line_listed; 11619370Spst 11746283Sdfr/* Saves the name of the last source file visited and a possible error code. 11846283Sdfr Used to prevent repeating annoying "No such file or directories" msgs */ 11946283Sdfr 12046283Sdfrstatic struct symtab *last_source_visited = NULL; 12146283Sdfrstatic int last_source_error = 0; 12298944Sobrien 123130803Smarcel/* Return the first line listed by print_source_lines. 124130803Smarcel Used by command interpreters to request listing from 125130803Smarcel a previous point. */ 12646283Sdfr 127130803Smarcelint 128130803Smarcelget_first_line_listed (void) 129130803Smarcel{ 130130803Smarcel return first_line_listed; 131130803Smarcel} 132130803Smarcel 133130803Smarcel/* Return the default number of lines to print with commands like the 134130803Smarcel cli "list". The caller of print_source_lines must use this to 135130803Smarcel calculate the end line and use it in the call to print_source_lines 136130803Smarcel as it does not automatically use this value. */ 137130803Smarcel 138130803Smarcelint 139130803Smarcelget_lines_to_list (void) 140130803Smarcel{ 141130803Smarcel return lines_to_list; 142130803Smarcel} 143130803Smarcel 144130803Smarcel/* Return the current source file for listing and next line to list. 145130803Smarcel NOTE: The returned sal pc and end fields are not valid. */ 146130803Smarcel 147130803Smarcelstruct symtab_and_line 148130803Smarcelget_current_source_symtab_and_line (void) 149130803Smarcel{ 150130803Smarcel struct symtab_and_line cursal; 151130803Smarcel 152130803Smarcel cursal.symtab = current_source_symtab; 153130803Smarcel cursal.line = current_source_line; 154130803Smarcel cursal.pc = 0; 155130803Smarcel cursal.end = 0; 156130803Smarcel 157130803Smarcel return cursal; 158130803Smarcel} 159130803Smarcel 160130803Smarcel/* If the current source file for listing is not set, try and get a default. 161130803Smarcel Usually called before get_current_source_symtab_and_line() is called. 162130803Smarcel It may err out if a default cannot be determined. 163130803Smarcel We must be cautious about where it is called, as it can recurse as the 164130803Smarcel process of determining a new default may call the caller! 165130803Smarcel Use get_current_source_symtab_and_line only to get whatever 166130803Smarcel we have without erroring out or trying to get a default. */ 167130803Smarcel 168130803Smarcelvoid 169130803Smarcelset_default_source_symtab_and_line (void) 170130803Smarcel{ 171130803Smarcel struct symtab_and_line cursal; 172130803Smarcel 173130803Smarcel if (!have_full_symbols () && !have_partial_symbols ()) 174130803Smarcel error ("No symbol table is loaded. Use the \"file\" command."); 175130803Smarcel 176130803Smarcel /* Pull in a current source symtab if necessary */ 177130803Smarcel if (current_source_symtab == 0) 178130803Smarcel select_source_symtab (0); 179130803Smarcel} 180130803Smarcel 181130803Smarcel/* Return the current default file for listing and next line to list 182130803Smarcel (the returned sal pc and end fields are not valid.) 183130803Smarcel and set the current default to whatever is in SAL. 184130803Smarcel NOTE: The returned sal pc and end fields are not valid. */ 185130803Smarcel 186130803Smarcelstruct symtab_and_line 187130803Smarcelset_current_source_symtab_and_line (const struct symtab_and_line *sal) 188130803Smarcel{ 189130803Smarcel struct symtab_and_line cursal; 190130803Smarcel 191130803Smarcel cursal.symtab = current_source_symtab; 192130803Smarcel cursal.line = current_source_line; 193130803Smarcel 194130803Smarcel current_source_symtab = sal->symtab; 195130803Smarcel current_source_line = sal->line; 196130803Smarcel cursal.pc = 0; 197130803Smarcel cursal.end = 0; 198130803Smarcel 199130803Smarcel return cursal; 200130803Smarcel} 201130803Smarcel 202130803Smarcel/* Reset any information stored about a default file and line to print. */ 203130803Smarcel 204130803Smarcelvoid 205130803Smarcelclear_current_source_symtab_and_line (void) 206130803Smarcel{ 207130803Smarcel current_source_symtab = 0; 208130803Smarcel current_source_line = 0; 209130803Smarcel} 210130803Smarcel 21119370Spst/* Set the source file default for the "list" command to be S. 21219370Spst 21319370Spst If S is NULL, and we don't have a default, find one. This 21419370Spst should only be called when the user actually tries to use the 21519370Spst default, since we produce an error if we can't find a reasonable 21619370Spst default. Also, since this can cause symbols to be read, doing it 21719370Spst before we need to would make things slower than necessary. */ 21819370Spst 21919370Spstvoid 220130803Smarcelselect_source_symtab (struct symtab *s) 22119370Spst{ 22219370Spst struct symtabs_and_lines sals; 22319370Spst struct symtab_and_line sal; 22419370Spst struct partial_symtab *ps; 22519370Spst struct partial_symtab *cs_pst = 0; 22619370Spst struct objfile *ofp; 22798944Sobrien 22819370Spst if (s) 22919370Spst { 23019370Spst current_source_symtab = s; 23119370Spst current_source_line = 1; 23219370Spst return; 23319370Spst } 23419370Spst 23519370Spst if (current_source_symtab) 23619370Spst return; 23719370Spst 23819370Spst /* Make the default place to list be the function `main' 23919370Spst if one exists. */ 240130803Smarcel if (lookup_symbol (main_name (), 0, VAR_DOMAIN, 0, NULL)) 24119370Spst { 24298944Sobrien sals = decode_line_spec (main_name (), 1); 24319370Spst sal = sals.sals[0]; 24498944Sobrien xfree (sals.sals); 24519370Spst current_source_symtab = sal.symtab; 24619370Spst current_source_line = max (sal.line - (lines_to_list - 1), 1); 24719370Spst if (current_source_symtab) 24898944Sobrien return; 24919370Spst } 25098944Sobrien 25119370Spst /* All right; find the last file in the symtab list (ignoring .h's). */ 25219370Spst 25319370Spst current_source_line = 1; 25419370Spst 25598944Sobrien for (ofp = object_files; ofp != NULL; ofp = ofp->next) 25619370Spst { 25798944Sobrien for (s = ofp->symtabs; s; s = s->next) 25819370Spst { 25998944Sobrien char *name = s->filename; 26019370Spst int len = strlen (name); 261130803Smarcel if (!(len > 2 && (DEPRECATED_STREQ (&name[len - 2], ".h")))) 26219370Spst { 26319370Spst current_source_symtab = s; 26419370Spst } 26519370Spst } 26619370Spst } 26719370Spst if (current_source_symtab) 26819370Spst return; 26919370Spst 27019370Spst /* Howabout the partial symbol tables? */ 27119370Spst 27298944Sobrien for (ofp = object_files; ofp != NULL; ofp = ofp->next) 27319370Spst { 27498944Sobrien for (ps = ofp->psymtabs; ps != NULL; ps = ps->next) 27519370Spst { 27698944Sobrien char *name = ps->filename; 27719370Spst int len = strlen (name); 278130803Smarcel if (!(len > 2 && (DEPRECATED_STREQ (&name[len - 2], ".h")))) 27919370Spst { 28019370Spst cs_pst = ps; 28119370Spst } 28219370Spst } 28319370Spst } 28419370Spst if (cs_pst) 28519370Spst { 28698944Sobrien if (cs_pst->readin) 28719370Spst { 28898944Sobrien internal_error (__FILE__, __LINE__, 28998944Sobrien "select_source_symtab: " 29098944Sobrien "readin pst found and no symtabs."); 29119370Spst } 29219370Spst else 29319370Spst { 29419370Spst current_source_symtab = PSYMTAB_TO_SYMTAB (cs_pst); 29519370Spst } 29619370Spst } 29746283Sdfr if (current_source_symtab) 29846283Sdfr return; 29919370Spst 30019370Spst error ("Can't find a default source file"); 30119370Spst} 30219370Spst 30319370Spststatic void 30498944Sobrienshow_directories (char *ignore, int from_tty) 30519370Spst{ 30619370Spst puts_filtered ("Source directories searched: "); 30719370Spst puts_filtered (source_path); 30819370Spst puts_filtered ("\n"); 30919370Spst} 31019370Spst 31119370Spst/* Forget what we learned about line positions in source files, and 31219370Spst which directories contain them; must check again now since files 31319370Spst may be found in a different directory now. */ 31419370Spst 31519370Spstvoid 31698944Sobrienforget_cached_source_info (void) 31719370Spst{ 318130803Smarcel struct symtab *s; 319130803Smarcel struct objfile *objfile; 32098944Sobrien struct partial_symtab *pst; 32119370Spst 32298944Sobrien for (objfile = object_files; objfile != NULL; objfile = objfile->next) 32319370Spst { 32498944Sobrien for (s = objfile->symtabs; s != NULL; s = s->next) 32519370Spst { 32698944Sobrien if (s->line_charpos != NULL) 32719370Spst { 32898944Sobrien xmfree (objfile->md, s->line_charpos); 32998944Sobrien s->line_charpos = NULL; 33019370Spst } 33198944Sobrien if (s->fullname != NULL) 33219370Spst { 33398944Sobrien xmfree (objfile->md, s->fullname); 33498944Sobrien s->fullname = NULL; 33519370Spst } 33619370Spst } 33798944Sobrien 33898944Sobrien ALL_OBJFILE_PSYMTABS (objfile, pst) 33998944Sobrien { 34098944Sobrien if (pst->fullname != NULL) 34198944Sobrien { 34298944Sobrien xfree (pst->fullname); 34398944Sobrien pst->fullname = NULL; 34498944Sobrien } 34598944Sobrien } 34619370Spst } 34719370Spst} 34819370Spst 34919370Spstvoid 35098944Sobrieninit_source_path (void) 35119370Spst{ 35219370Spst char buf[20]; 35319370Spst 35419370Spst sprintf (buf, "$cdir%c$cwd", DIRNAME_SEPARATOR); 35598944Sobrien source_path = xstrdup (buf); 35619370Spst forget_cached_source_info (); 35719370Spst} 35819370Spst 359130803Smarcelvoid 360130803Smarcelinit_last_source_visited (void) 361130803Smarcel{ 362130803Smarcel last_source_visited = NULL; 363130803Smarcel} 364130803Smarcel 36519370Spst/* Add zero or more directories to the front of the source path. */ 36698944Sobrien 36719370Spstvoid 36898944Sobriendirectory_command (char *dirname, int from_tty) 36919370Spst{ 37019370Spst dont_repeat (); 37119370Spst /* FIXME, this goes to "delete dir"... */ 37219370Spst if (dirname == 0) 37319370Spst { 37498944Sobrien if (from_tty && query ("Reinitialize source path to empty? ")) 37519370Spst { 37698944Sobrien xfree (source_path); 37719370Spst init_source_path (); 37819370Spst } 37919370Spst } 38019370Spst else 38146283Sdfr { 38246283Sdfr mod_path (dirname, &source_path); 38346283Sdfr last_source_visited = NULL; 38446283Sdfr } 38519370Spst if (from_tty) 38698944Sobrien show_directories ((char *) 0, from_tty); 38719370Spst forget_cached_source_info (); 38819370Spst} 38919370Spst 39019370Spst/* Add zero or more directories to the front of an arbitrary path. */ 39119370Spst 39219370Spstvoid 39398944Sobrienmod_path (char *dirname, char **which_path) 39419370Spst{ 395130803Smarcel add_path (dirname, which_path, 1); 396130803Smarcel} 397130803Smarcel 398130803Smarcel/* Workhorse of mod_path. Takes an extra argument to determine 399130803Smarcel if dirname should be parsed for separators that indicate multiple 400130803Smarcel directories. This allows for interfaces that pre-parse the dirname 401130803Smarcel and allow specification of traditional separator characters such 402130803Smarcel as space or tab. */ 403130803Smarcel 404130803Smarcelvoid 405130803Smarceladd_path (char *dirname, char **which_path, int parse_separators) 406130803Smarcel{ 40719370Spst char *old = *which_path; 40819370Spst int prefix = 0; 40919370Spst 41019370Spst if (dirname == 0) 41119370Spst return; 41219370Spst 41398944Sobrien dirname = xstrdup (dirname); 41498944Sobrien make_cleanup (xfree, dirname); 41519370Spst 41619370Spst do 41719370Spst { 41819370Spst char *name = dirname; 419130803Smarcel char *p; 42019370Spst struct stat st; 42119370Spst 42219370Spst { 423130803Smarcel char *separator = NULL; 424130803Smarcel char *space = NULL; 425130803Smarcel char *tab = NULL; 42619370Spst 427130803Smarcel if (parse_separators) 428130803Smarcel { 429130803Smarcel separator = strchr (name, DIRNAME_SEPARATOR); 430130803Smarcel space = strchr (name, ' '); 431130803Smarcel tab = strchr (name, '\t'); 432130803Smarcel } 433130803Smarcel 43498944Sobrien if (separator == 0 && space == 0 && tab == 0) 43519370Spst p = dirname = name + strlen (name); 43619370Spst else 43719370Spst { 43819370Spst p = 0; 43919370Spst if (separator != 0 && (p == 0 || separator < p)) 44019370Spst p = separator; 44119370Spst if (space != 0 && (p == 0 || space < p)) 44219370Spst p = space; 44319370Spst if (tab != 0 && (p == 0 || tab < p)) 44419370Spst p = tab; 44519370Spst dirname = p + 1; 44619370Spst while (*dirname == DIRNAME_SEPARATOR 44719370Spst || *dirname == ' ' 44819370Spst || *dirname == '\t') 44919370Spst ++dirname; 45019370Spst } 45119370Spst } 45219370Spst 45398944Sobrien if (!(IS_DIR_SEPARATOR (*name) && p <= name + 1) /* "/" */ 45498944Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 45598944Sobrien /* On MS-DOS and MS-Windows, h:\ is different from h: */ 45698944Sobrien && !(p == name + 3 && name[1] == ':') /* "d:/" */ 45798944Sobrien#endif 45898944Sobrien && IS_DIR_SEPARATOR (p[-1])) 45919370Spst /* Sigh. "foo/" => "foo" */ 46019370Spst --p; 46119370Spst *p = '\0'; 46219370Spst 46398944Sobrien while (p > name && p[-1] == '.') 46419370Spst { 46519370Spst if (p - name == 1) 46619370Spst { 46719370Spst /* "." => getwd (). */ 46819370Spst name = current_directory; 46919370Spst goto append; 47019370Spst } 47198944Sobrien else if (p > name + 1 && IS_DIR_SEPARATOR (p[-2])) 47219370Spst { 47319370Spst if (p - name == 2) 47419370Spst { 47519370Spst /* "/." => "/". */ 47619370Spst *--p = '\0'; 47719370Spst goto append; 47819370Spst } 47919370Spst else 48019370Spst { 48119370Spst /* "...foo/." => "...foo". */ 48219370Spst p -= 2; 48319370Spst *p = '\0'; 48419370Spst continue; 48519370Spst } 48619370Spst } 48719370Spst else 48819370Spst break; 48919370Spst } 49019370Spst 49119370Spst if (name[0] == '~') 49219370Spst name = tilde_expand (name); 49398944Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM 49498944Sobrien else if (IS_ABSOLUTE_PATH (name) && p == name + 2) /* "d:" => "d:." */ 49598944Sobrien name = concat (name, ".", NULL); 49698944Sobrien#endif 49798944Sobrien else if (!IS_ABSOLUTE_PATH (name) && name[0] != '$') 49898944Sobrien name = concat (current_directory, SLASH_STRING, name, NULL); 49919370Spst else 50019370Spst name = savestring (name, p - name); 50198944Sobrien make_cleanup (xfree, name); 50219370Spst 50319370Spst /* Unless it's a variable, check existence. */ 50498944Sobrien if (name[0] != '$') 50598944Sobrien { 50698944Sobrien /* These are warnings, not errors, since we don't want a 50798944Sobrien non-existent directory in a .gdbinit file to stop processing 50898944Sobrien of the .gdbinit file. 50919370Spst 51098944Sobrien Whether they get added to the path is more debatable. Current 51198944Sobrien answer is yes, in case the user wants to go make the directory 51298944Sobrien or whatever. If the directory continues to not exist/not be 51398944Sobrien a directory/etc, then having them in the path should be 51498944Sobrien harmless. */ 51598944Sobrien if (stat (name, &st) < 0) 51698944Sobrien { 51798944Sobrien int save_errno = errno; 51898944Sobrien fprintf_unfiltered (gdb_stderr, "Warning: "); 51998944Sobrien print_sys_errmsg (name, save_errno); 52098944Sobrien } 52198944Sobrien else if ((st.st_mode & S_IFMT) != S_IFDIR) 52298944Sobrien warning ("%s is not a directory.", name); 52398944Sobrien } 52419370Spst 52519370Spst append: 52619370Spst { 527130803Smarcel unsigned int len = strlen (name); 52819370Spst 52919370Spst p = *which_path; 53019370Spst while (1) 53119370Spst { 53298944Sobrien /* FIXME: strncmp loses in interesting ways on MS-DOS and 53398944Sobrien MS-Windows because of case-insensitivity and two different 53498944Sobrien but functionally identical slash characters. We need a 53598944Sobrien special filesystem-dependent file-name comparison function. 53698944Sobrien 53798944Sobrien Actually, even on Unix I would use realpath() or its work- 53898944Sobrien alike before comparing. Then all the code above which 53998944Sobrien removes excess slashes and dots could simply go away. */ 54019370Spst if (!strncmp (p, name, len) 54119370Spst && (p[len] == '\0' || p[len] == DIRNAME_SEPARATOR)) 54219370Spst { 54319370Spst /* Found it in the search path, remove old copy */ 54419370Spst if (p > *which_path) 54598944Sobrien p--; /* Back over leading separator */ 54619370Spst if (prefix > p - *which_path) 54719370Spst goto skip_dup; /* Same dir twice in one cmd */ 54898944Sobrien strcpy (p, &p[len + 1]); /* Copy from next \0 or : */ 54919370Spst } 55019370Spst p = strchr (p, DIRNAME_SEPARATOR); 55119370Spst if (p != 0) 55219370Spst ++p; 55319370Spst else 55419370Spst break; 55519370Spst } 55619370Spst if (p == 0) 55719370Spst { 55819370Spst char tinybuf[2]; 55919370Spst 56019370Spst tinybuf[0] = DIRNAME_SEPARATOR; 56119370Spst tinybuf[1] = '\0'; 56219370Spst 563130803Smarcel /* If we have already tacked on a name(s) in this command, be sure they stay 564130803Smarcel on the front as we tack on some more. */ 56519370Spst if (prefix) 56619370Spst { 56719370Spst char *temp, c; 56819370Spst 56919370Spst c = old[prefix]; 57019370Spst old[prefix] = '\0'; 57119370Spst temp = concat (old, tinybuf, name, NULL); 57219370Spst old[prefix] = c; 57319370Spst *which_path = concat (temp, "", &old[prefix], NULL); 57419370Spst prefix = strlen (temp); 57598944Sobrien xfree (temp); 57619370Spst } 57719370Spst else 57819370Spst { 57919370Spst *which_path = concat (name, (old[0] ? tinybuf : old), old, NULL); 58019370Spst prefix = strlen (name); 58119370Spst } 58298944Sobrien xfree (old); 58319370Spst old = *which_path; 58419370Spst } 58519370Spst } 58698944Sobrien skip_dup:; 58798944Sobrien } 58898944Sobrien while (*dirname != '\0'); 58919370Spst} 59019370Spst 59119370Spst 59219370Spststatic void 59398944Sobriensource_info (char *ignore, int from_tty) 59419370Spst{ 595130803Smarcel struct symtab *s = current_source_symtab; 59619370Spst 59719370Spst if (!s) 59819370Spst { 59998944Sobrien printf_filtered ("No current source file.\n"); 60019370Spst return; 60119370Spst } 60219370Spst printf_filtered ("Current source file is %s\n", s->filename); 60319370Spst if (s->dirname) 60419370Spst printf_filtered ("Compilation directory is %s\n", s->dirname); 60519370Spst if (s->fullname) 60619370Spst printf_filtered ("Located in %s\n", s->fullname); 60719370Spst if (s->nlines) 60819370Spst printf_filtered ("Contains %d line%s.\n", s->nlines, 60919370Spst s->nlines == 1 ? "" : "s"); 61019370Spst 61146283Sdfr printf_filtered ("Source language is %s.\n", language_str (s->language)); 61246283Sdfr printf_filtered ("Compiled with %s debugging format.\n", s->debugformat); 613130803Smarcel printf_filtered ("%s preprocessor macro info.\n", 614130803Smarcel s->macro_table ? "Includes" : "Does not include"); 61519370Spst} 61698944Sobrien 61719370Spst 618130803Smarcel/* Return True if the file NAME exists and is a regular file */ 619130803Smarcelstatic int 620130803Smarcelis_regular_file (const char *name) 621130803Smarcel{ 622130803Smarcel struct stat st; 623130803Smarcel const int status = stat (name, &st); 62419370Spst 625130803Smarcel /* Stat should never fail except when the file does not exist. 626130803Smarcel If stat fails, analyze the source of error and return True 627130803Smarcel unless the file does not exist, to avoid returning false results 628130803Smarcel on obscure systems where stat does not work as expected. 629130803Smarcel */ 630130803Smarcel if (status != 0) 631130803Smarcel return (errno != ENOENT); 632130803Smarcel 633130803Smarcel return S_ISREG (st.st_mode); 634130803Smarcel} 635130803Smarcel 63619370Spst/* Open a file named STRING, searching path PATH (dir names sep by some char) 63719370Spst using mode MODE and protection bits PROT in the calls to open. 63819370Spst 63919370Spst If TRY_CWD_FIRST, try to open ./STRING before searching PATH. 64019370Spst (ie pretend the first element of PATH is "."). This also indicates 64119370Spst that a slash in STRING disables searching of the path (this is 64219370Spst so that "exec-file ./foo" or "symbol-file ./foo" insures that you 64319370Spst get that particular version of foo or an error message). 64419370Spst 64598944Sobrien If FILENAME_OPENED is non-null, set it to a newly allocated string naming 646130803Smarcel the actual file opened (this string will always start with a "/"). We 64719370Spst have to take special pains to avoid doubling the "/" between the directory 64819370Spst and the file, sigh! Emacs gets confuzzed by this when we print the 64919370Spst source file name!!! 65019370Spst 65119370Spst If a file is found, return the descriptor. 65219370Spst Otherwise, return -1, with errno set for the last name we tried to open. */ 65319370Spst 65419370Spst/* >>>> This should only allow files of certain types, 655130803Smarcel >>>> eg executable, non-directory */ 65619370Spstint 65798944Sobrienopenp (const char *path, int try_cwd_first, const char *string, 65898944Sobrien int mode, int prot, 65998944Sobrien char **filename_opened) 66019370Spst{ 661130803Smarcel int fd; 662130803Smarcel char *filename; 66398944Sobrien const char *p; 66498944Sobrien const char *p1; 665130803Smarcel int len; 66619370Spst int alloclen; 66719370Spst 66819370Spst if (!path) 66919370Spst path = "."; 67019370Spst 67198944Sobrien#if defined(_WIN32) || defined(__CYGWIN__) 67219370Spst mode |= O_BINARY; 67319370Spst#endif 67419370Spst 67598944Sobrien if (try_cwd_first || IS_ABSOLUTE_PATH (string)) 67619370Spst { 67719370Spst int i; 678130803Smarcel 679130803Smarcel if (is_regular_file (string)) 680130803Smarcel { 681130803Smarcel filename = alloca (strlen (string) + 1); 682130803Smarcel strcpy (filename, string); 683130803Smarcel fd = open (filename, mode, prot); 684130803Smarcel if (fd >= 0) 685130803Smarcel goto done; 686130803Smarcel } 687130803Smarcel else 688130803Smarcel { 689130803Smarcel filename = NULL; 690130803Smarcel fd = -1; 691130803Smarcel } 692130803Smarcel 69319370Spst for (i = 0; string[i]; i++) 69498944Sobrien if (IS_DIR_SEPARATOR (string[i])) 69519370Spst goto done; 69619370Spst } 69719370Spst 69819370Spst /* ./foo => foo */ 69998944Sobrien while (string[0] == '.' && IS_DIR_SEPARATOR (string[1])) 70019370Spst string += 2; 70119370Spst 70219370Spst alloclen = strlen (path) + strlen (string) + 2; 70398944Sobrien filename = alloca (alloclen); 70419370Spst fd = -1; 70519370Spst for (p = path; p; p = p1 ? p1 + 1 : 0) 70619370Spst { 70798944Sobrien p1 = strchr (p, DIRNAME_SEPARATOR); 70819370Spst if (p1) 70919370Spst len = p1 - p; 71019370Spst else 71119370Spst len = strlen (p); 71219370Spst 71319370Spst if (len == 4 && p[0] == '$' && p[1] == 'c' 71498944Sobrien && p[2] == 'w' && p[3] == 'd') 71598944Sobrien { 71698944Sobrien /* Name is $cwd -- insert current directory name instead. */ 71798944Sobrien int newlen; 71819370Spst 71998944Sobrien /* First, realloc the filename buffer if too short. */ 72098944Sobrien len = strlen (current_directory); 72198944Sobrien newlen = len + strlen (string) + 2; 72298944Sobrien if (newlen > alloclen) 72398944Sobrien { 72498944Sobrien alloclen = newlen; 72598944Sobrien filename = alloca (alloclen); 72698944Sobrien } 72798944Sobrien strcpy (filename, current_directory); 72819370Spst } 72998944Sobrien else 73098944Sobrien { 73198944Sobrien /* Normal file name in path -- just use it. */ 73298944Sobrien strncpy (filename, p, len); 73398944Sobrien filename[len] = 0; 73498944Sobrien } 73519370Spst 73619370Spst /* Remove trailing slashes */ 73798944Sobrien while (len > 0 && IS_DIR_SEPARATOR (filename[len - 1])) 73819370Spst filename[--len] = 0; 73919370Spst 74098944Sobrien strcat (filename + len, SLASH_STRING); 74119370Spst strcat (filename, string); 74219370Spst 743130803Smarcel if (is_regular_file (filename)) 744130803Smarcel { 745130803Smarcel fd = open (filename, mode); 746130803Smarcel if (fd >= 0) 747130803Smarcel break; 748130803Smarcel } 74919370Spst } 75019370Spst 75198944Sobriendone: 75219370Spst if (filename_opened) 75319370Spst { 754130803Smarcel /* If a file was opened, canonicalize its filename. Use xfullpath 755130803Smarcel rather than gdb_realpath to avoid resolving the basename part 756130803Smarcel of filenames when the associated file is a symbolic link. This 757130803Smarcel fixes a potential inconsistency between the filenames known to 758130803Smarcel GDB and the filenames it prints in the annotations. */ 75919370Spst if (fd < 0) 76098944Sobrien *filename_opened = NULL; 76198944Sobrien else if (IS_ABSOLUTE_PATH (filename)) 762130803Smarcel *filename_opened = xfullpath (filename); 76319370Spst else 76419370Spst { 76519370Spst /* Beware the // my son, the Emacs barfs, the botch that catch... */ 76698944Sobrien 76798944Sobrien char *f = concat (current_directory, 76898944Sobrien IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1]) 76998944Sobrien ? "" : SLASH_STRING, 77019370Spst filename, NULL); 771130803Smarcel *filename_opened = xfullpath (f); 77298944Sobrien xfree (f); 77398944Sobrien } 77419370Spst } 77519370Spst 77619370Spst return fd; 77719370Spst} 77819370Spst 77998944Sobrien 78046283Sdfr/* This is essentially a convenience, for clients that want the behaviour 78146283Sdfr of openp, using source_path, but that really don't want the file to be 78246283Sdfr opened but want instead just to know what the full pathname is (as 78346283Sdfr qualified against source_path). 78446283Sdfr 78546283Sdfr The current working directory is searched first. 78646283Sdfr 78746283Sdfr If the file was found, this function returns 1, and FULL_PATHNAME is 78846283Sdfr set to the fully-qualified pathname. 78946283Sdfr 79046283Sdfr Else, this functions returns 0, and FULL_PATHNAME is set to NULL. 79198944Sobrien */ 79246283Sdfrint 79398944Sobriensource_full_path_of (char *filename, char **full_pathname) 79446283Sdfr{ 79598944Sobrien int fd; 79646283Sdfr 79746283Sdfr fd = openp (source_path, 1, filename, O_RDONLY, 0, full_pathname); 79846283Sdfr if (fd < 0) 79946283Sdfr { 80046283Sdfr *full_pathname = NULL; 80146283Sdfr return 0; 80246283Sdfr } 80346283Sdfr 80446283Sdfr close (fd); 80546283Sdfr return 1; 80646283Sdfr} 80746283Sdfr 80846283Sdfr 80919370Spst/* Open a source file given a symtab S. Returns a file descriptor or 81019370Spst negative number for error. */ 81119370Spst 81246283Sdfrint 81398944Sobrienopen_source_file (struct symtab *s) 81419370Spst{ 81519370Spst char *path = source_path; 81698944Sobrien const char *p; 81719370Spst int result; 81819370Spst char *fullname; 81919370Spst 82019370Spst /* Quick way out if we already know its full name */ 82198944Sobrien if (s->fullname) 82219370Spst { 82346283Sdfr result = open (s->fullname, OPEN_MODE); 82419370Spst if (result >= 0) 82598944Sobrien return result; 82619370Spst /* Didn't work -- free old one, try again. */ 82798944Sobrien xmfree (s->objfile->md, s->fullname); 82819370Spst s->fullname = NULL; 82919370Spst } 83019370Spst 83119370Spst if (s->dirname != NULL) 83219370Spst { 83319370Spst /* Replace a path entry of $cdir with the compilation directory name */ 83419370Spst#define cdir_len 5 83519370Spst /* We cast strstr's result in case an ANSIhole has made it const, 83698944Sobrien which produces a "required warning" when assigned to a nonconst. */ 83798944Sobrien p = (char *) strstr (source_path, "$cdir"); 83819370Spst if (p && (p == path || p[-1] == DIRNAME_SEPARATOR) 83998944Sobrien && (p[cdir_len] == DIRNAME_SEPARATOR || p[cdir_len] == '\0')) 84019370Spst { 84119370Spst int len; 84219370Spst 84319370Spst path = (char *) 84419370Spst alloca (strlen (source_path) + 1 + strlen (s->dirname) + 1); 84519370Spst len = p - source_path; 84698944Sobrien strncpy (path, source_path, len); /* Before $cdir */ 84798944Sobrien strcpy (path + len, s->dirname); /* new stuff */ 84898944Sobrien strcat (path + len, source_path + len + cdir_len); /* After $cdir */ 84919370Spst } 85019370Spst } 85119370Spst 85246283Sdfr result = openp (path, 0, s->filename, OPEN_MODE, 0, &s->fullname); 85319370Spst if (result < 0) 85419370Spst { 85519370Spst /* Didn't work. Try using just the basename. */ 85698944Sobrien p = lbasename (s->filename); 85719370Spst if (p != s->filename) 85846283Sdfr result = openp (path, 0, p, OPEN_MODE, 0, &s->fullname); 85919370Spst } 86019370Spst 86119370Spst if (result >= 0) 86219370Spst { 86319370Spst fullname = s->fullname; 86419370Spst s->fullname = mstrsave (s->objfile->md, s->fullname); 86598944Sobrien xfree (fullname); 86619370Spst } 86719370Spst return result; 86819370Spst} 86919370Spst 87019370Spst/* Return the path to the source file associated with symtab. Returns NULL 87119370Spst if no symtab. */ 87219370Spst 87319370Spstchar * 87498944Sobriensymtab_to_filename (struct symtab *s) 87519370Spst{ 87619370Spst int fd; 87719370Spst 87819370Spst if (!s) 87919370Spst return NULL; 88019370Spst 88119370Spst /* If we've seen the file before, just return fullname. */ 88219370Spst 88319370Spst if (s->fullname) 88419370Spst return s->fullname; 88519370Spst 88619370Spst /* Try opening the file to setup fullname */ 88719370Spst 88819370Spst fd = open_source_file (s); 88919370Spst if (fd < 0) 89019370Spst return s->filename; /* File not found. Just use short name */ 89119370Spst 89219370Spst /* Found the file. Cleanup and return the full name */ 89319370Spst 89419370Spst close (fd); 89519370Spst return s->fullname; 89619370Spst} 89798944Sobrien 89819370Spst 89919370Spst/* Create and initialize the table S->line_charpos that records 90019370Spst the positions of the lines in the source file, which is assumed 90119370Spst to be open on descriptor DESC. 90219370Spst All set S->nlines to the number of such lines. */ 90319370Spst 90446283Sdfrvoid 90598944Sobrienfind_source_lines (struct symtab *s, int desc) 90619370Spst{ 90719370Spst struct stat st; 908130803Smarcel char *data, *p, *end; 90919370Spst int nlines = 0; 91019370Spst int lines_allocated = 1000; 91119370Spst int *line_charpos; 91246283Sdfr long mtime = 0; 91319370Spst int size; 91419370Spst 91598944Sobrien line_charpos = (int *) xmmalloc (s->objfile->md, 91619370Spst lines_allocated * sizeof (int)); 91719370Spst if (fstat (desc, &st) < 0) 91819370Spst perror_with_name (s->filename); 91919370Spst 92046283Sdfr if (s && s->objfile && s->objfile->obfd) 92198944Sobrien mtime = bfd_get_mtime (s->objfile->obfd); 92246283Sdfr else if (exec_bfd) 92398944Sobrien mtime = bfd_get_mtime (exec_bfd); 92446283Sdfr 92546283Sdfr if (mtime && mtime < st.st_mtime) 92619370Spst { 92798944Sobrien warning ("Source file is more recent than executable.\n"); 92819370Spst } 92919370Spst 93019370Spst#ifdef LSEEK_NOT_LINEAR 93119370Spst { 93219370Spst char c; 93319370Spst 93419370Spst /* Have to read it byte by byte to find out where the chars live */ 93519370Spst 93619370Spst line_charpos[0] = lseek (desc, 0, SEEK_CUR); 93719370Spst nlines = 1; 93898944Sobrien while (myread (desc, &c, 1) > 0) 93919370Spst { 94098944Sobrien if (c == '\n') 94119370Spst { 94298944Sobrien if (nlines == lines_allocated) 94319370Spst { 94419370Spst lines_allocated *= 2; 94519370Spst line_charpos = 94698944Sobrien (int *) xmrealloc (s->objfile->md, (char *) line_charpos, 94719370Spst sizeof (int) * lines_allocated); 94819370Spst } 94919370Spst line_charpos[nlines++] = lseek (desc, 0, SEEK_CUR); 95019370Spst } 95119370Spst } 95219370Spst } 95319370Spst#else /* lseek linear. */ 95419370Spst { 95519370Spst struct cleanup *old_cleanups; 95619370Spst 95719370Spst /* st_size might be a large type, but we only support source files whose 95819370Spst size fits in an int. */ 95919370Spst size = (int) st.st_size; 96019370Spst 96119370Spst /* Use malloc, not alloca, because this may be pretty large, and we may 96219370Spst run into various kinds of limits on stack size. */ 96319370Spst data = (char *) xmalloc (size); 96498944Sobrien old_cleanups = make_cleanup (xfree, data); 96519370Spst 96646283Sdfr /* Reassign `size' to result of read for systems where \r\n -> \n. */ 96746283Sdfr size = myread (desc, data, size); 96846283Sdfr if (size < 0) 96919370Spst perror_with_name (s->filename); 97019370Spst end = data + size; 97119370Spst p = data; 97219370Spst line_charpos[0] = 0; 97319370Spst nlines = 1; 97419370Spst while (p != end) 97519370Spst { 97619370Spst if (*p++ == '\n' 97798944Sobrien /* A newline at the end does not start a new line. */ 97819370Spst && p != end) 97919370Spst { 98019370Spst if (nlines == lines_allocated) 98119370Spst { 98219370Spst lines_allocated *= 2; 98319370Spst line_charpos = 98498944Sobrien (int *) xmrealloc (s->objfile->md, (char *) line_charpos, 98519370Spst sizeof (int) * lines_allocated); 98619370Spst } 98719370Spst line_charpos[nlines++] = p - data; 98819370Spst } 98919370Spst } 99019370Spst do_cleanups (old_cleanups); 99119370Spst } 99219370Spst#endif /* lseek linear. */ 99319370Spst s->nlines = nlines; 99419370Spst s->line_charpos = 99598944Sobrien (int *) xmrealloc (s->objfile->md, (char *) line_charpos, 99698944Sobrien nlines * sizeof (int)); 99719370Spst 99819370Spst} 99919370Spst 100019370Spst/* Return the character position of a line LINE in symtab S. 100119370Spst Return 0 if anything is invalid. */ 100219370Spst 100398944Sobrien#if 0 /* Currently unused */ 100419370Spst 100519370Spstint 100698944Sobriensource_line_charpos (struct symtab *s, int line) 100719370Spst{ 100898944Sobrien if (!s) 100998944Sobrien return 0; 101098944Sobrien if (!s->line_charpos || line <= 0) 101198944Sobrien return 0; 101219370Spst if (line > s->nlines) 101319370Spst line = s->nlines; 101419370Spst return s->line_charpos[line - 1]; 101519370Spst} 101619370Spst 101719370Spst/* Return the line number of character position POS in symtab S. */ 101819370Spst 101919370Spstint 1020130803Smarcelsource_charpos_line (struct symtab *s, int chr) 102119370Spst{ 1022130803Smarcel int line = 0; 1023130803Smarcel int *lnp; 102498944Sobrien 102598944Sobrien if (s == 0 || s->line_charpos == 0) 102698944Sobrien return 0; 102719370Spst lnp = s->line_charpos; 102819370Spst /* Files are usually short, so sequential search is Ok */ 102998944Sobrien while (line < s->nlines && *lnp <= chr) 103019370Spst { 103119370Spst line++; 103219370Spst lnp++; 103319370Spst } 103419370Spst if (line >= s->nlines) 103519370Spst line = s->nlines; 103619370Spst return line; 103719370Spst} 103819370Spst 103998944Sobrien#endif /* 0 */ 104098944Sobrien 104119370Spst 104219370Spst/* Get full pathname and line number positions for a symtab. 104319370Spst Return nonzero if line numbers may have changed. 104419370Spst Set *FULLNAME to actual name of the file as found by `openp', 104519370Spst or to 0 if the file is not found. */ 104619370Spst 104719370Spststatic int 104898944Sobrienget_filename_and_charpos (struct symtab *s, char **fullname) 104919370Spst{ 1050130803Smarcel int desc, linenums_changed = 0; 105198944Sobrien 105219370Spst desc = open_source_file (s); 105319370Spst if (desc < 0) 105419370Spst { 105519370Spst if (fullname) 105619370Spst *fullname = NULL; 105719370Spst return 0; 105898944Sobrien } 105919370Spst if (fullname) 106019370Spst *fullname = s->fullname; 106198944Sobrien if (s->line_charpos == 0) 106298944Sobrien linenums_changed = 1; 106398944Sobrien if (linenums_changed) 106498944Sobrien find_source_lines (s, desc); 106519370Spst close (desc); 106619370Spst return linenums_changed; 106719370Spst} 106819370Spst 106919370Spst/* Print text describing the full name of the source file S 107019370Spst and the line number LINE and its corresponding character position. 107119370Spst The text starts with two Ctrl-z so that the Emacs-GDB interface 107219370Spst can easily find it. 107319370Spst 107419370Spst MID_STATEMENT is nonzero if the PC is not at the beginning of that line. 107519370Spst 107619370Spst Return 1 if successful, 0 if could not find the file. */ 107719370Spst 107819370Spstint 107998944Sobrienidentify_source_line (struct symtab *s, int line, int mid_statement, 108098944Sobrien CORE_ADDR pc) 108119370Spst{ 108219370Spst if (s->line_charpos == 0) 108398944Sobrien get_filename_and_charpos (s, (char **) NULL); 108419370Spst if (s->fullname == 0) 108519370Spst return 0; 108619370Spst if (line > s->nlines) 108719370Spst /* Don't index off the end of the line_charpos array. */ 108819370Spst return 0; 108919370Spst annotate_source (s->fullname, line, s->line_charpos[line - 1], 109019370Spst mid_statement, pc); 109119370Spst 109219370Spst current_source_line = line; 109319370Spst first_line_listed = line; 109419370Spst last_line_listed = line; 109519370Spst current_source_symtab = s; 109619370Spst return 1; 109719370Spst} 109898944Sobrien 109946283Sdfr 110019370Spst/* Print source lines from the file of symtab S, 110146283Sdfr starting with line number LINE and stopping before line number STOPLINE. */ 110219370Spst 110398944Sobrienstatic void print_source_lines_base (struct symtab *s, int line, int stopline, 110498944Sobrien int noerror); 110546283Sdfrstatic void 110698944Sobrienprint_source_lines_base (struct symtab *s, int line, int stopline, int noerror) 110719370Spst{ 1108130803Smarcel int c; 1109130803Smarcel int desc; 1110130803Smarcel FILE *stream; 111119370Spst int nlines = stopline - line; 111219370Spst 111319370Spst /* Regardless of whether we can open the file, set current_source_symtab. */ 111419370Spst current_source_symtab = s; 111519370Spst current_source_line = line; 111619370Spst first_line_listed = line; 111719370Spst 111898944Sobrien /* If printing of source lines is disabled, just print file and line number */ 111998944Sobrien if (ui_out_test_flags (uiout, ui_source_list)) 112046283Sdfr { 112198944Sobrien /* Only prints "No such file or directory" once */ 112298944Sobrien if ((s != last_source_visited) || (!last_source_error)) 112398944Sobrien { 112498944Sobrien last_source_visited = s; 112598944Sobrien desc = open_source_file (s); 112698944Sobrien } 112798944Sobrien else 112898944Sobrien { 112998944Sobrien desc = last_source_error; 113098944Sobrien noerror = 1; 113198944Sobrien } 113246283Sdfr } 113346283Sdfr else 113446283Sdfr { 113598944Sobrien desc = -1; 113646283Sdfr noerror = 1; 113746283Sdfr } 113846283Sdfr 113919370Spst if (desc < 0) 114019370Spst { 114146283Sdfr last_source_error = desc; 114246283Sdfr 114398944Sobrien if (!noerror) 114498944Sobrien { 114546283Sdfr char *name = alloca (strlen (s->filename) + 100); 114646283Sdfr sprintf (name, "%d\t%s", line, s->filename); 114746283Sdfr print_sys_errmsg (name, errno); 114846283Sdfr } 114946283Sdfr else 115098944Sobrien ui_out_field_int (uiout, "line", line); 115198944Sobrien ui_out_text (uiout, "\tin "); 115298944Sobrien ui_out_field_string (uiout, "file", s->filename); 115398944Sobrien ui_out_text (uiout, "\n"); 115446283Sdfr 115519370Spst return; 115619370Spst } 115719370Spst 115846283Sdfr last_source_error = 0; 115946283Sdfr 116019370Spst if (s->line_charpos == 0) 116119370Spst find_source_lines (s, desc); 116219370Spst 116319370Spst if (line < 1 || line > s->nlines) 116419370Spst { 116519370Spst close (desc); 116619370Spst error ("Line number %d out of range; %s has %d lines.", 116719370Spst line, s->filename, s->nlines); 116819370Spst } 116919370Spst 117019370Spst if (lseek (desc, s->line_charpos[line - 1], 0) < 0) 117119370Spst { 117219370Spst close (desc); 117319370Spst perror_with_name (s->filename); 117419370Spst } 117519370Spst 117646283Sdfr stream = fdopen (desc, FDOPEN_MODE); 117719370Spst clearerr (stream); 117819370Spst 117919370Spst while (nlines-- > 0) 118019370Spst { 118198944Sobrien char buf[20]; 118298944Sobrien 118319370Spst c = fgetc (stream); 118498944Sobrien if (c == EOF) 118598944Sobrien break; 118619370Spst last_line_listed = current_source_line; 118798944Sobrien sprintf (buf, "%d\t", current_source_line++); 118898944Sobrien ui_out_text (uiout, buf); 118919370Spst do 119019370Spst { 119119370Spst if (c < 040 && c != '\t' && c != '\n' && c != '\r') 119298944Sobrien { 119398944Sobrien sprintf (buf, "^%c", c + 0100); 119498944Sobrien ui_out_text (uiout, buf); 119598944Sobrien } 119619370Spst else if (c == 0177) 119798944Sobrien ui_out_text (uiout, "^?"); 119846283Sdfr#ifdef CRLF_SOURCE_FILES 119946283Sdfr else if (c == '\r') 120046283Sdfr { 120198944Sobrien /* Skip a \r character, but only before a \n. */ 120298944Sobrien int c1 = fgetc (stream); 120398944Sobrien 120498944Sobrien if (c1 != '\n') 120598944Sobrien printf_filtered ("^%c", c + 0100); 120698944Sobrien if (c1 != EOF) 120798944Sobrien ungetc (c1, stream); 120846283Sdfr } 120946283Sdfr#endif 121019370Spst else 121198944Sobrien { 121298944Sobrien sprintf (buf, "%c", c); 121398944Sobrien ui_out_text (uiout, buf); 121498944Sobrien } 121598944Sobrien } 121698944Sobrien while (c != '\n' && (c = fgetc (stream)) >= 0); 121719370Spst } 121819370Spst 121919370Spst fclose (stream); 122019370Spst} 122119370Spst 122246283Sdfr/* Show source lines from the file of symtab S, starting with line 122346283Sdfr number LINE and stopping before line number STOPLINE. If this is the 122446283Sdfr not the command line version, then the source is shown in the source 122546283Sdfr window otherwise it is simply printed */ 122619370Spst 122798944Sobrienvoid 122898944Sobrienprint_source_lines (struct symtab *s, int line, int stopline, int noerror) 122946283Sdfr{ 123098944Sobrien print_source_lines_base (s, line, stopline, noerror); 123146283Sdfr} 123246283Sdfr 123319370Spst/* Print info on range of pc's in a specified line. */ 123419370Spst 123519370Spststatic void 123698944Sobrienline_info (char *arg, int from_tty) 123719370Spst{ 123819370Spst struct symtabs_and_lines sals; 123919370Spst struct symtab_and_line sal; 124019370Spst CORE_ADDR start_pc, end_pc; 124119370Spst int i; 124219370Spst 1243130803Smarcel init_sal (&sal); /* initialize to zeroes */ 124446283Sdfr 124519370Spst if (arg == 0) 124619370Spst { 124719370Spst sal.symtab = current_source_symtab; 124819370Spst sal.line = last_line_listed; 124919370Spst sals.nelts = 1; 125019370Spst sals.sals = (struct symtab_and_line *) 125119370Spst xmalloc (sizeof (struct symtab_and_line)); 125219370Spst sals.sals[0] = sal; 125319370Spst } 125419370Spst else 125519370Spst { 125619370Spst sals = decode_line_spec_1 (arg, 0); 125798944Sobrien 125819370Spst dont_repeat (); 125919370Spst } 126019370Spst 126119370Spst /* C++ More than one line may have been specified, as when the user 126219370Spst specifies an overloaded function name. Print info on them all. */ 126319370Spst for (i = 0; i < sals.nelts; i++) 126419370Spst { 126519370Spst sal = sals.sals[i]; 126698944Sobrien 126719370Spst if (sal.symtab == 0) 126819370Spst { 126919370Spst printf_filtered ("No line number information available"); 127019370Spst if (sal.pc != 0) 127119370Spst { 127219370Spst /* This is useful for "info line *0x7f34". If we can't tell the 127398944Sobrien user about a source line, at least let them have the symbolic 127498944Sobrien address. */ 127519370Spst printf_filtered (" for address "); 127619370Spst wrap_here (" "); 127719370Spst print_address (sal.pc, gdb_stdout); 127819370Spst } 127919370Spst else 128019370Spst printf_filtered ("."); 128119370Spst printf_filtered ("\n"); 128219370Spst } 128319370Spst else if (sal.line > 0 128419370Spst && find_line_pc_range (sal, &start_pc, &end_pc)) 128519370Spst { 128619370Spst if (start_pc == end_pc) 128719370Spst { 128819370Spst printf_filtered ("Line %d of \"%s\"", 128919370Spst sal.line, sal.symtab->filename); 129019370Spst wrap_here (" "); 129119370Spst printf_filtered (" is at address "); 129219370Spst print_address (start_pc, gdb_stdout); 129319370Spst wrap_here (" "); 129419370Spst printf_filtered (" but contains no code.\n"); 129519370Spst } 129619370Spst else 129719370Spst { 129819370Spst printf_filtered ("Line %d of \"%s\"", 129919370Spst sal.line, sal.symtab->filename); 130019370Spst wrap_here (" "); 130119370Spst printf_filtered (" starts at address "); 130219370Spst print_address (start_pc, gdb_stdout); 130319370Spst wrap_here (" "); 130419370Spst printf_filtered (" and ends at "); 130519370Spst print_address (end_pc, gdb_stdout); 130619370Spst printf_filtered (".\n"); 130719370Spst } 130819370Spst 130919370Spst /* x/i should display this line's code. */ 131019370Spst set_next_address (start_pc); 131119370Spst 131219370Spst /* Repeating "info line" should do the following line. */ 131319370Spst last_line_listed = sal.line + 1; 131419370Spst 131519370Spst /* If this is the only line, show the source code. If it could 131619370Spst not find the file, don't do anything special. */ 131719370Spst if (annotation_level && sals.nelts == 1) 131819370Spst identify_source_line (sal.symtab, sal.line, 0, start_pc); 131919370Spst } 132019370Spst else 132119370Spst /* Is there any case in which we get here, and have an address 132219370Spst which the user would want to see? If we have debugging symbols 132319370Spst and no line numbers? */ 132419370Spst printf_filtered ("Line number %d is out of range for \"%s\".\n", 132519370Spst sal.line, sal.symtab->filename); 132619370Spst } 132798944Sobrien xfree (sals.sals); 132819370Spst} 132919370Spst 133019370Spst/* Commands to search the source file for a regexp. */ 133119370Spst 133219370Spststatic void 133398944Sobrienforward_search_command (char *regex, int from_tty) 133419370Spst{ 1335130803Smarcel int c; 1336130803Smarcel int desc; 1337130803Smarcel FILE *stream; 133846283Sdfr int line; 133919370Spst char *msg; 134019370Spst 134146283Sdfr line = last_line_listed + 1; 134246283Sdfr 134319370Spst msg = (char *) re_comp (regex); 134419370Spst if (msg) 1345130803Smarcel error ("%s", msg); 134619370Spst 134719370Spst if (current_source_symtab == 0) 134819370Spst select_source_symtab (0); 134919370Spst 135019370Spst desc = open_source_file (current_source_symtab); 135119370Spst if (desc < 0) 135219370Spst perror_with_name (current_source_symtab->filename); 135319370Spst 135419370Spst if (current_source_symtab->line_charpos == 0) 135519370Spst find_source_lines (current_source_symtab, desc); 135619370Spst 135719370Spst if (line < 1 || line > current_source_symtab->nlines) 135819370Spst { 135919370Spst close (desc); 136019370Spst error ("Expression not found"); 136119370Spst } 136219370Spst 136319370Spst if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0) 136419370Spst { 136519370Spst close (desc); 136619370Spst perror_with_name (current_source_symtab->filename); 136719370Spst } 136819370Spst 136946283Sdfr stream = fdopen (desc, FDOPEN_MODE); 137019370Spst clearerr (stream); 137198944Sobrien while (1) 137298944Sobrien { 137398944Sobrien static char *buf = NULL; 1374130803Smarcel char *p; 137598944Sobrien int cursize, newsize; 137619370Spst 137798944Sobrien cursize = 256; 137898944Sobrien buf = xmalloc (cursize); 137998944Sobrien p = buf; 138019370Spst 138198944Sobrien c = getc (stream); 138298944Sobrien if (c == EOF) 138398944Sobrien break; 138498944Sobrien do 138519370Spst { 138698944Sobrien *p++ = c; 138798944Sobrien if (p - buf == cursize) 138898944Sobrien { 138998944Sobrien newsize = cursize + cursize / 2; 139098944Sobrien buf = xrealloc (buf, newsize); 139198944Sobrien p = buf + cursize; 139298944Sobrien cursize = newsize; 139398944Sobrien } 139419370Spst } 139598944Sobrien while (c != '\n' && (c = getc (stream)) >= 0); 139619370Spst 139798944Sobrien#ifdef CRLF_SOURCE_FILES 139898944Sobrien /* Remove the \r, if any, at the end of the line, otherwise 139998944Sobrien regular expressions that end with $ or \n won't work. */ 140098944Sobrien if (p - buf > 1 && p[-2] == '\r') 140198944Sobrien { 140298944Sobrien p--; 140398944Sobrien p[-1] = '\n'; 140498944Sobrien } 140598944Sobrien#endif 140619370Spst 140798944Sobrien /* we now have a source line in buf, null terminate and match */ 140898944Sobrien *p = 0; 140998944Sobrien if (re_exec (buf) > 0) 141098944Sobrien { 141198944Sobrien /* Match! */ 141298944Sobrien fclose (stream); 141398944Sobrien print_source_lines (current_source_symtab, line, line + 1, 0); 141498944Sobrien set_internalvar (lookup_internalvar ("_"), 141598944Sobrien value_from_longest (builtin_type_int, 141698944Sobrien (LONGEST) line)); 141798944Sobrien current_source_line = max (line - lines_to_list / 2, 1); 141898944Sobrien return; 141998944Sobrien } 142098944Sobrien line++; 142198944Sobrien } 142298944Sobrien 142319370Spst printf_filtered ("Expression not found\n"); 142419370Spst fclose (stream); 142519370Spst} 142619370Spst 142719370Spststatic void 142898944Sobrienreverse_search_command (char *regex, int from_tty) 142919370Spst{ 1430130803Smarcel int c; 1431130803Smarcel int desc; 1432130803Smarcel FILE *stream; 143346283Sdfr int line; 143419370Spst char *msg; 143598944Sobrien 143646283Sdfr line = last_line_listed - 1; 143719370Spst 143819370Spst msg = (char *) re_comp (regex); 143919370Spst if (msg) 1440130803Smarcel error ("%s", msg); 144119370Spst 144219370Spst if (current_source_symtab == 0) 144319370Spst select_source_symtab (0); 144419370Spst 144519370Spst desc = open_source_file (current_source_symtab); 144619370Spst if (desc < 0) 144719370Spst perror_with_name (current_source_symtab->filename); 144819370Spst 144919370Spst if (current_source_symtab->line_charpos == 0) 145019370Spst find_source_lines (current_source_symtab, desc); 145119370Spst 145219370Spst if (line < 1 || line > current_source_symtab->nlines) 145319370Spst { 145419370Spst close (desc); 145519370Spst error ("Expression not found"); 145619370Spst } 145719370Spst 145819370Spst if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0) 145919370Spst { 146019370Spst close (desc); 146119370Spst perror_with_name (current_source_symtab->filename); 146219370Spst } 146319370Spst 146446283Sdfr stream = fdopen (desc, FDOPEN_MODE); 146519370Spst clearerr (stream); 146619370Spst while (line > 1) 146719370Spst { 146819370Spst/* FIXME!!! We walk right off the end of buf if we get a long line!!! */ 146919370Spst char buf[4096]; /* Should be reasonable??? */ 1470130803Smarcel char *p = buf; 147119370Spst 147219370Spst c = getc (stream); 147319370Spst if (c == EOF) 147419370Spst break; 147598944Sobrien do 147698944Sobrien { 147798944Sobrien *p++ = c; 147898944Sobrien } 147998944Sobrien while (c != '\n' && (c = getc (stream)) >= 0); 148019370Spst 148198944Sobrien#ifdef CRLF_SOURCE_FILES 148298944Sobrien /* Remove the \r, if any, at the end of the line, otherwise 148398944Sobrien regular expressions that end with $ or \n won't work. */ 148498944Sobrien if (p - buf > 1 && p[-2] == '\r') 148598944Sobrien { 148698944Sobrien p--; 148798944Sobrien p[-1] = '\n'; 148898944Sobrien } 148998944Sobrien#endif 149098944Sobrien 149119370Spst /* We now have a source line in buf; null terminate and match. */ 149219370Spst *p = 0; 149319370Spst if (re_exec (buf) > 0) 149419370Spst { 149519370Spst /* Match! */ 149619370Spst fclose (stream); 149798944Sobrien print_source_lines (current_source_symtab, line, line + 1, 0); 149819370Spst set_internalvar (lookup_internalvar ("_"), 149919370Spst value_from_longest (builtin_type_int, 150019370Spst (LONGEST) line)); 150119370Spst current_source_line = max (line - lines_to_list / 2, 1); 150219370Spst return; 150319370Spst } 150419370Spst line--; 150519370Spst if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0) 150619370Spst { 150719370Spst fclose (stream); 150819370Spst perror_with_name (current_source_symtab->filename); 150919370Spst } 151019370Spst } 151119370Spst 151219370Spst printf_filtered ("Expression not found\n"); 151319370Spst fclose (stream); 151419370Spst return; 151519370Spst} 151619370Spst 151719370Spstvoid 151898944Sobrien_initialize_source (void) 151919370Spst{ 152019370Spst struct cmd_list_element *c; 152119370Spst current_source_symtab = 0; 152219370Spst init_source_path (); 152319370Spst 152419370Spst /* The intention is to use POSIX Basic Regular Expressions. 152519370Spst Always use the GNU regex routine for consistency across all hosts. 152619370Spst Our current GNU regex.c does not have all the POSIX features, so this is 152719370Spst just an approximation. */ 152819370Spst re_set_syntax (RE_SYNTAX_GREP); 152919370Spst 153019370Spst c = add_cmd ("directory", class_files, directory_command, 153198944Sobrien "Add directory DIR to beginning of search path for source files.\n\ 153219370SpstForget cached info on source file locations and line positions.\n\ 153319370SpstDIR can also be $cwd for the current working directory, or $cdir for the\n\ 153419370Spstdirectory in which the source file was compiled into object code.\n\ 153519370SpstWith no argument, reset the search path to $cdir:$cwd, the default.", 153619370Spst &cmdlist); 153746283Sdfr 153846283Sdfr if (dbx_commands) 153998944Sobrien add_com_alias ("use", "directory", class_files, 0); 154046283Sdfr 1541130803Smarcel set_cmd_completer (c, filename_completer); 154219370Spst 154319370Spst add_cmd ("directories", no_class, show_directories, 154419370Spst "Current search path for finding source files.\n\ 154519370Spst$cwd in the path means the current working directory.\n\ 154619370Spst$cdir in the path means the compilation directory of the source file.", 154719370Spst &showlist); 154819370Spst 154946283Sdfr if (xdb_commands) 155046283Sdfr { 155198944Sobrien add_com_alias ("D", "directory", class_files, 0); 155246283Sdfr add_cmd ("ld", no_class, show_directories, 155398944Sobrien "Current search path for finding source files.\n\ 155446283Sdfr$cwd in the path means the current working directory.\n\ 155546283Sdfr$cdir in the path means the compilation directory of the source file.", 155698944Sobrien &cmdlist); 155746283Sdfr } 155846283Sdfr 155919370Spst add_info ("source", source_info, 156019370Spst "Information about the current source file."); 156119370Spst 156219370Spst add_info ("line", line_info, 156319370Spst concat ("Core addresses of the code for a source line.\n\ 156419370SpstLine can be specified as\n\ 156519370Spst LINENUM, to list around that line in current file,\n\ 156619370Spst FILE:LINENUM, to list around that line in that file,\n\ 156719370Spst FUNCTION, to list around beginning of that function,\n\ 156819370Spst FILE:FUNCTION, to distinguish among like-named static functions.\n\ 156919370Spst", "\ 157019370SpstDefault is to describe the last source line that was listed.\n\n\ 157119370SpstThis sets the default address for \"x\" to the line's first instruction\n\ 157219370Spstso that \"x/i\" suffices to start examining the machine code.\n\ 157319370SpstThe address is also stored as the value of \"$_\".", NULL)); 157419370Spst 157519370Spst add_com ("forward-search", class_files, forward_search_command, 157619370Spst "Search for regular expression (see regex(3)) from last line listed.\n\ 157719370SpstThe matching line number is also stored as the value of \"$_\"."); 157819370Spst add_com_alias ("search", "forward-search", class_files, 0); 157919370Spst 158019370Spst add_com ("reverse-search", class_files, reverse_search_command, 158119370Spst "Search backward for regular expression (see regex(3)) from last line listed.\n\ 158219370SpstThe matching line number is also stored as the value of \"$_\"."); 158319370Spst 158446283Sdfr if (xdb_commands) 158546283Sdfr { 158698944Sobrien add_com_alias ("/", "forward-search", class_files, 0); 158798944Sobrien add_com_alias ("?", "reverse-search", class_files, 0); 158846283Sdfr } 158946283Sdfr 159019370Spst add_show_from_set 159119370Spst (add_set_cmd ("listsize", class_support, var_uinteger, 159298944Sobrien (char *) &lines_to_list, 159398944Sobrien "Set number of source lines gdb will list by default.", 159419370Spst &setlist), 159519370Spst &showlist); 159619370Spst} 1597