/* List lines of source files for GDB, the GNU debugger.
- Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
+ 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+ Free Software Foundation, Inc.
This file is part of GDB.
#include "annotate.h"
#include "gdbtypes.h"
#include "linespec.h"
-#ifdef UI_OUT
+#include "filenames.h" /* for DOSish file names */
+#include "completer.h"
#include "ui-out.h"
-#endif
#ifdef CRLF_SOURCE_FILES
/* Make the default place to list be the function `main'
if one exists. */
- if (lookup_symbol ("main", 0, VAR_NAMESPACE, 0, NULL))
+ if (lookup_symbol (main_name (), 0, VAR_NAMESPACE, 0, NULL))
{
- sals = decode_line_spec ("main", 1);
+ sals = decode_line_spec (main_name (), 1);
sal = sals.sals[0];
xfree (sals.sals);
current_source_symtab = sal.symtab;
{
register struct symtab *s;
register struct objfile *objfile;
+ struct partial_symtab *pst;
for (objfile = object_files; objfile != NULL; objfile = objfile->next)
{
{
if (s->line_charpos != NULL)
{
- mfree (objfile->md, s->line_charpos);
+ xmfree (objfile->md, s->line_charpos);
s->line_charpos = NULL;
}
if (s->fullname != NULL)
{
- mfree (objfile->md, s->fullname);
+ xmfree (objfile->md, s->fullname);
s->fullname = NULL;
}
}
+
+ ALL_OBJFILE_PSYMTABS (objfile, pst)
+ {
+ if (pst->fullname != NULL)
+ {
+ xfree (pst->fullname);
+ pst->fullname = NULL;
+ }
+ }
}
}
}
}
- if (!(SLASH_P (*name) && p <= name + 1) /* "/" */
-#if defined(_WIN32) || defined(__MSDOS__) || defined(__CYGWIN__)
+ if (!(IS_DIR_SEPARATOR (*name) && p <= name + 1) /* "/" */
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
/* On MS-DOS and MS-Windows, h:\ is different from h: */
- && !(!SLASH_P (*name) && ROOTED_P (name) && p <= name + 3) /* d:/ */
+ && !(p == name + 3 && name[1] == ':') /* "d:/" */
#endif
- && SLASH_P (p[-1]))
+ && IS_DIR_SEPARATOR (p[-1]))
/* Sigh. "foo/" => "foo" */
--p;
*p = '\0';
name = current_directory;
goto append;
}
- else if (p > name + 1 && SLASH_P (p[-2]))
+ else if (p > name + 1 && IS_DIR_SEPARATOR (p[-2]))
{
if (p - name == 2)
{
if (name[0] == '~')
name = tilde_expand (name);
-#if defined(_WIN32) || defined(__MSDOS__) || defined(__CYGWIN__)
- else if (ROOTED_P (name) && p == name + 2) /* "d:" => "d:." */
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+ else if (IS_ABSOLUTE_PATH (name) && p == name + 2) /* "d:" => "d:." */
name = concat (name, ".", NULL);
#endif
- else if (!ROOTED_P (name) && name[0] != '$')
+ else if (!IS_ABSOLUTE_PATH (name) && name[0] != '$')
name = concat (current_directory, SLASH_STRING, name, NULL);
else
name = savestring (name, p - name);
printf_filtered ("Source language is %s.\n", language_str (s->language));
printf_filtered ("Compiled with %s debugging format.\n", s->debugformat);
+ printf_filtered ("%s preprocessor macro info.\n",
+ s->macro_table ? "Includes" : "Does not include");
}
\f
+/* Return True if the file NAME exists and is a regular file */
+static int
+is_regular_file (const char *name)
+{
+ struct stat st;
+ const int status = stat (name, &st);
+
+ /* Stat should never fail except when the file does not exist.
+ If stat fails, analyze the source of error and return True
+ unless the file does not exist, to avoid returning false results
+ on obscure systems where stat does not work as expected.
+ */
+ if (status != 0)
+ return (errno != ENOENT);
+
+ return S_ISREG (st.st_mode);
+}
/* Open a file named STRING, searching path PATH (dir names sep by some char)
using mode MODE and protection bits PROT in the calls to open.
get that particular version of foo or an error message).
If FILENAME_OPENED is non-null, set it to a newly allocated string naming
- the actual file opened (this string will always start with a "/". We
+ the actual file opened (this string will always start with a "/"). We
have to take special pains to avoid doubling the "/" between the directory
and the file, sigh! Emacs gets confuzzed by this when we print the
source file name!!!
Otherwise, return -1, with errno set for the last name we tried to open. */
/* >>>> This should only allow files of certain types,
- >>>> eg executable, non-directory */
+ >>>> eg executable, non-directory */
int
-openp (char *path, int try_cwd_first, char *string, int mode, int prot,
+openp (const char *path, int try_cwd_first, const char *string,
+ int mode, int prot,
char **filename_opened)
{
register int fd;
register char *filename;
- register char *p, *p1;
+ const char *p;
+ const char *p1;
register int len;
int alloclen;
mode |= O_BINARY;
#endif
- if (try_cwd_first || ROOTED_P (string))
+ if ((try_cwd_first || IS_ABSOLUTE_PATH (string)) && is_regular_file (string))
{
int i;
- filename = string;
+ filename = alloca (strlen (string) + 1);
+ strcpy (filename, string);
fd = open (filename, mode, prot);
if (fd >= 0)
goto done;
for (i = 0; string[i]; i++)
- if (SLASH_P (string[i]))
+ if (IS_DIR_SEPARATOR (string[i]))
goto done;
}
/* ./foo => foo */
- while (string[0] == '.' && SLASH_P (string[1]))
+ while (string[0] == '.' && IS_DIR_SEPARATOR (string[1]))
string += 2;
alloclen = strlen (path) + strlen (string) + 2;
- filename = (char *) alloca (alloclen);
+ filename = alloca (alloclen);
fd = -1;
for (p = path; p; p = p1 ? p1 + 1 : 0)
{
- p1 = (char *) strchr (p, DIRNAME_SEPARATOR);
+ p1 = strchr (p, DIRNAME_SEPARATOR);
if (p1)
len = p1 - p;
else
if (newlen > alloclen)
{
alloclen = newlen;
- filename = (char *) alloca (alloclen);
+ filename = alloca (alloclen);
}
strcpy (filename, current_directory);
}
}
/* Remove trailing slashes */
- while (len > 0 && SLASH_P (filename[len - 1]))
+ while (len > 0 && IS_DIR_SEPARATOR (filename[len - 1]))
filename[--len] = 0;
strcat (filename + len, SLASH_STRING);
strcat (filename, string);
- fd = open (filename, mode);
- if (fd >= 0)
- break;
+ if (is_regular_file (filename))
+ {
+ fd = open (filename, mode);
+ if (fd >= 0)
+ break;
+ }
}
done:
if (filename_opened)
{
+ /* If a file was opened, canonicalize its filename. Use xfullpath
+ rather than gdb_realpath to avoid resolving the basename part
+ of filenames when the associated file is a symbolic link. This
+ fixes a potential inconsistency between the filenames known to
+ GDB and the filenames it prints in the annotations. */
if (fd < 0)
- *filename_opened = (char *) 0;
- else if (ROOTED_P (filename))
- *filename_opened = savestring (filename, strlen (filename));
+ *filename_opened = NULL;
+ else if (IS_ABSOLUTE_PATH (filename))
+ *filename_opened = xfullpath (filename);
else
{
/* Beware the // my son, the Emacs barfs, the botch that catch... */
- *filename_opened = concat (current_directory,
- SLASH_P (current_directory[strlen (current_directory) - 1])
+ char *f = concat (current_directory,
+ IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
? "" : SLASH_STRING,
filename, NULL);
+ *filename_opened = xfullpath (f);
+ xfree (f);
}
}
- /* OBSOLETE #ifdef MPW */
- /* OBSOLETE This is a debugging hack that can go away when all combinations */
- /* OBSOLETE of Mac and Unix names are handled reasonably. */
- /* OBSOLETE { */
- /* OBSOLETE extern int debug_openp; */
- /* OBSOLETE */
- /* OBSOLETE if (debug_openp) */
- /* OBSOLETE { */
- /* OBSOLETE printf ("openp on %s, path %s mode %d prot %d\n returned %d", */
- /* OBSOLETE string, path, mode, prot, fd); */
- /* OBSOLETE if (*filename_opened) */
- /* OBSOLETE printf (" (filename is %s)", *filename_opened); */
- /* OBSOLETE printf ("\n"); */
- /* OBSOLETE } */
- /* OBSOLETE } */
- /* OBSOLETE #endif *//* MPW */
return fd;
}
open_source_file (struct symtab *s)
{
char *path = source_path;
- char *p;
+ const char *p;
int result;
char *fullname;
if (result >= 0)
return result;
/* Didn't work -- free old one, try again. */
- mfree (s->objfile->md, s->fullname);
+ xmfree (s->objfile->md, s->fullname);
s->fullname = NULL;
}
if (result < 0)
{
/* Didn't work. Try using just the basename. */
- p = basename (s->filename);
+ p = lbasename (s->filename);
if (p != s->filename)
result = openp (path, 0, p, OPEN_MODE, 0, &s->fullname);
}
- /* OBSOLETE #ifdef MPW */
- /* OBSOLETE if (result < 0) */
- /* OBSOLETE { */
- /* OBSOLETE *//* Didn't work. Try using just the MPW basename. */
- /* OBSOLETE p = (char *) mpw_basename (s->filename); */
- /* OBSOLETE if (p != s->filename) */
- /* OBSOLETE result = openp (path, 0, p, OPEN_MODE, 0, &s->fullname); */
- /* OBSOLETE } */
- /* OBSOLETE if (result < 0) */
- /* OBSOLETE { */
- /* OBSOLETE *//* Didn't work. Try using the mixed Unix/MPW basename. */
- /* OBSOLETE p = (char *) mpw_mixed_basename (s->filename); */
- /* OBSOLETE if (p != s->filename) */
- /* OBSOLETE result = openp (path, 0, p, OPEN_MODE, 0, &s->fullname); */
- /* OBSOLETE } */
- /* OBSOLETE #endif MPW */
if (result >= 0)
{
if (mtime && mtime < st.st_mtime)
{
- if (tui_version)
- printf_filtered ("\n");
warning ("Source file is more recent than executable.\n");
}
current_source_line = line;
first_line_listed = line;
-#ifdef UI_OUT
/* If printing of source lines is disabled, just print file and line number */
if (ui_out_test_flags (uiout, ui_source_list))
{
-#endif
/* Only prints "No such file or directory" once */
if ((s != last_source_visited) || (!last_source_error))
{
desc = last_source_error;
noerror = 1;
}
-#ifdef UI_OUT
}
else
{
desc = -1;
noerror = 1;
}
-#endif
if (desc < 0)
{
print_sys_errmsg (name, errno);
}
else
-#ifdef UI_OUT
ui_out_field_int (uiout, "line", line);
ui_out_text (uiout, "\tin ");
ui_out_field_string (uiout, "file", s->filename);
ui_out_text (uiout, "\n");
-#else
- printf_filtered ("%d\tin %s\n", line, s->filename);
-#endif
return;
}
while (nlines-- > 0)
{
-#ifdef UI_OUT
char buf[20];
c = fgetc (stream);
}
}
while (c != '\n' && (c = fgetc (stream)) >= 0);
-#else
- c = fgetc (stream);
- if (c == EOF)
- break;
- last_line_listed = current_source_line;
- printf_filtered ("%d\t", current_source_line++);
- do
- {
- if (c < 040 && c != '\t' && c != '\n' && c != '\r')
- printf_filtered ("^%c", c + 0100);
- else if (c == 0177)
- printf_filtered ("^?");
-#ifdef CRLF_SOURCE_FILES
- else if (c == '\r')
- {
- /* Just skip \r characters. */
- }
-#endif
- else
- printf_filtered ("%c", c);
- }
- while (c != '\n' && (c = fgetc (stream)) >= 0);
-#endif
}
fclose (stream);
void
print_source_lines (struct symtab *s, int line, int stopline, int noerror)
{
-#if defined(TUI)
- if (!tui_version ||
- m_winPtrIsNull (srcWin) || !srcWin->generic.isVisible)
- print_source_lines_base (s, line, stopline, noerror);
- else
- {
- TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
-extern void tui_vAddWinToLayout (va_list);
-extern void tui_vUpdateSourceWindowsWithLine (va_list);
-
- /* Regardless of whether we can open the file,
- set current_source_symtab. */
- current_source_symtab = s;
- current_source_line = line;
- first_line_listed = line;
-
- /* make sure that the source window is displayed */
- tuiDo ((TuiOpaqueFuncPtr) tui_vAddWinToLayout, SRC_WIN);
-
- tuiDo ((TuiOpaqueFuncPtr) tui_vUpdateSourceWindowsWithLine, s, line);
- tuiDo ((TuiOpaqueFuncPtr) tui_vUpdateLocatorFilename, s->filename);
- }
-#else
print_source_lines_base (s, line, stopline, noerror);
-#endif
}
\f
int line;
char *msg;
-#if defined(TUI)
- /*
- ** If this is the TUI, search from the first line displayed in
- ** the source window, otherwise, search from last_line_listed+1
- ** in current_source_symtab
- */
- if (!tui_version)
- line = last_line_listed;
- else
- {
- if (srcWin->generic.isVisible && srcWin->generic.contentSize > 0)
- line = ((TuiWinContent)
- srcWin->generic.content)[0]->whichElement.source.lineOrAddr.lineNo;
- else
- {
- printf_filtered ("No source displayed.\nExpression not found.\n");
- return;
- }
- }
- line++;
-#else
line = last_line_listed + 1;
-#endif
msg = (char *) re_comp (regex);
if (msg)
{
/* Match! */
fclose (stream);
- if (tui_version)
- print_source_lines_base (current_source_symtab, line, line + 1, 0);
print_source_lines (current_source_symtab, line, line + 1, 0);
set_internalvar (lookup_internalvar ("_"),
value_from_longest (builtin_type_int,
register FILE *stream;
int line;
char *msg;
-#if defined(TUI)
- /*
- ** If this is the TUI, search from the first line displayed in
- ** the source window, otherwise, search from last_line_listed-1
- ** in current_source_symtab
- */
- if (!tui_version)
- line = last_line_listed;
- else
- {
- if (srcWin->generic.isVisible && srcWin->generic.contentSize > 0)
- line = ((TuiWinContent)
- srcWin->generic.content)[0]->whichElement.source.lineOrAddr.lineNo;
- else
- {
- printf_filtered ("No source displayed.\nExpression not found.\n");
- return;
- }
- }
- line--;
-#else
+
line = last_line_listed - 1;
-#endif
msg = (char *) re_comp (regex);
if (msg)
{
/* Match! */
fclose (stream);
- if (tui_version)
- print_source_lines_base (current_source_symtab, line, line + 1, 0);
print_source_lines (current_source_symtab, line, line + 1, 0);
set_internalvar (lookup_internalvar ("_"),
value_from_longest (builtin_type_int,
if (dbx_commands)
add_com_alias ("use", "directory", class_files, 0);
- c->completer = filename_completer;
+ set_cmd_completer (c, filename_completer);
add_cmd ("directories", no_class, show_directories,
"Current search path for finding source files.\n\