X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fsource.c;h=e0ae0b179fd8c3221b0c09ce10d7200629fa65c7;hb=ec56be1b4dc25ec39c32ceab997747ad651c9d22;hp=2895dd388f683e76ff2e23cb349b3ee7bf052844;hpb=31889e007b0383eda46a0540aaae895c4e2cccb2;p=deliverable%2Fbinutils-gdb.git
diff --git a/gdb/source.c b/gdb/source.c
index 2895dd388f..e0ae0b179f 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -1,12 +1,13 @@
/* 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 (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+ 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
+ Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -15,9 +16,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see . */
#include "defs.h"
#include "symtab.h"
@@ -28,6 +27,7 @@
#include "gdbcmd.h"
#include "frame.h"
#include "value.h"
+#include "gdb_assert.h"
#include
#include "gdb_string.h"
@@ -41,30 +41,14 @@
#include "gdbtypes.h"
#include "linespec.h"
#include "filenames.h" /* for DOSish file names */
-#ifdef UI_OUT
+#include "completer.h"
#include "ui-out.h"
-#endif
-
-#ifdef CRLF_SOURCE_FILES
+#include "readline/readline.h"
-/* Define CRLF_SOURCE_FILES in an xm-*.h file if source files on the
- host use \r\n rather than just \n. Defining CRLF_SOURCE_FILES is
- much faster than defining LSEEK_NOT_LINEAR. */
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
#define OPEN_MODE (O_RDONLY | O_BINARY)
#define FDOPEN_MODE FOPEN_RB
-#else /* ! defined (CRLF_SOURCE_FILES) */
-
-#define OPEN_MODE O_RDONLY
-#define FDOPEN_MODE FOPEN_RT
-
-#endif /* ! defined (CRLF_SOURCE_FILES) */
-
/* Prototypes for exported functions. */
void _initialize_source (void);
@@ -79,10 +63,6 @@ static void forward_search_command (char *, int);
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);
static void show_directories (char *, int);
@@ -92,13 +72,24 @@ static void show_directories (char *, int);
char *source_path;
+/* Support for source path substitution commands. */
+
+struct substitute_path_rule
+{
+ char *from;
+ char *to;
+ struct substitute_path_rule *next;
+};
+
+static struct substitute_path_rule *substitute_path_rules = NULL;
+
/* Symtab of default file for listing lines of. */
-struct symtab *current_source_symtab;
+static struct symtab *current_source_symtab;
/* Default next line to list. */
-int current_source_line;
+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
@@ -107,6 +98,14 @@ int current_source_line;
things are wrapping, but that would be a fair amount of work. */
int lines_to_list = 10;
+static void
+show_lines_to_list (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("\
+Number of source lines gdb will list by default is %s.\n"),
+ value);
+}
/* Line number of last line printed. Default for various commands.
current_source_line is usually, but not always, the same as this. */
@@ -123,6 +122,93 @@ static int first_line_listed;
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 = { 0 };
+
+ cursal.symtab = current_source_symtab;
+ cursal.line = current_source_line;
+ cursal.pc = 0;
+ cursal.end = 0;
+
+ return cursal;
+}
+
+/* If the current source file for listing is not set, try and get a default.
+ Usually called before get_current_source_symtab_and_line() is called.
+ It may err out if a default cannot be determined.
+ We must be cautious about where it is called, as it can recurse as the
+ process of determining a new default may call the caller!
+ Use get_current_source_symtab_and_line only to get whatever
+ we have without erroring out or trying to get a default. */
+
+void
+set_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);
+}
+
+/* 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 current default to whatever is in SAL.
+ NOTE: The returned sal pc and end fields are not valid. */
+
+struct symtab_and_line
+set_current_source_symtab_and_line (const struct symtab_and_line *sal)
+{
+ struct symtab_and_line cursal = { 0 };
+
+ cursal.symtab = current_source_symtab;
+ cursal.line = current_source_line;
+
+ current_source_symtab = sal->symtab;
+ current_source_line = sal->line;
+ cursal.pc = 0;
+ cursal.end = 0;
+
+ 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.
@@ -133,7 +219,7 @@ static int last_source_error = 0;
before we need to would make things slower than necessary. */
void
-select_source_symtab (register struct symtab *s)
+select_source_symtab (struct symtab *s)
{
struct symtabs_and_lines sals;
struct symtab_and_line sal;
@@ -153,9 +239,9 @@ select_source_symtab (register struct symtab *s)
/* 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_DOMAIN, 0))
{
- 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;
@@ -164,7 +250,8 @@ select_source_symtab (register struct symtab *s)
return;
}
- /* All right; find the last file in the symtab list (ignoring .h's). */
+ /* Alright; find the last file in the symtab list (ignoring .h's
+ and namespace symtabs). */
current_source_line = 1;
@@ -172,29 +259,27 @@ select_source_symtab (register struct symtab *s)
{
for (s = ofp->symtabs; s; s = s->next)
{
- char *name = s->filename;
+ const char *name = s->filename;
int len = strlen (name);
- if (!(len > 2 && (STREQ (&name[len - 2], ".h"))))
- {
- current_source_symtab = s;
- }
+ if (!(len > 2 && (strcmp (&name[len - 2], ".h") == 0
+ || strcmp (name, "<>") == 0)))
+ current_source_symtab = s;
}
}
if (current_source_symtab)
return;
- /* Howabout the partial symbol tables? */
+ /* How about the partial symbol tables? */
for (ofp = object_files; ofp != NULL; ofp = ofp->next)
{
for (ps = ofp->psymtabs; ps != NULL; ps = ps->next)
{
- char *name = ps->filename;
+ const char *name = ps->filename;
int len = strlen (name);
- if (!(len > 2 && (STREQ (&name[len - 2], ".h"))))
- {
- cs_pst = ps;
- }
+ if (!(len > 2 && (strcmp (&name[len - 2], ".h") == 0
+ || strcmp (name, "<>") == 0)))
+ cs_pst = ps;
}
}
if (cs_pst)
@@ -202,8 +287,8 @@ select_source_symtab (register struct symtab *s)
if (cs_pst->readin)
{
internal_error (__FILE__, __LINE__,
- "select_source_symtab: "
- "readin pst found and no symtabs.");
+ _("select_source_symtab: "
+ "readin pst found and no symtabs."));
}
else
{
@@ -213,7 +298,7 @@ select_source_symtab (register struct symtab *s)
if (current_source_symtab)
return;
- error ("Can't find a default source file");
+ error (_("Can't find a default source file"));
}
static void
@@ -231,8 +316,9 @@ show_directories (char *ignore, int from_tty)
void
forget_cached_source_info (void)
{
- register struct symtab *s;
- register struct objfile *objfile;
+ struct symtab *s;
+ struct objfile *objfile;
+ struct partial_symtab *pst;
for (objfile = object_files; objfile != NULL; objfile = objfile->next)
{
@@ -240,15 +326,24 @@ forget_cached_source_info (void)
{
if (s->line_charpos != NULL)
{
- mfree (objfile->md, s->line_charpos);
+ xfree (s->line_charpos);
s->line_charpos = NULL;
}
if (s->fullname != NULL)
{
- mfree (objfile->md, s->fullname);
+ xfree (s->fullname);
s->fullname = NULL;
}
}
+
+ ALL_OBJFILE_PSYMTABS (objfile, pst)
+ {
+ if (pst->fullname != NULL)
+ {
+ xfree (pst->fullname);
+ pst->fullname = NULL;
+ }
+ }
}
}
@@ -262,6 +357,12 @@ init_source_path (void)
forget_cached_source_info ();
}
+void
+init_last_source_visited (void)
+{
+ last_source_visited = NULL;
+}
+
/* Add zero or more directories to the front of the source path. */
void
@@ -271,7 +372,7 @@ directory_command (char *dirname, int from_tty)
/* FIXME, this goes to "delete dir"... */
if (dirname == 0)
{
- if (from_tty && query ("Reinitialize source path to empty? "))
+ if (!from_tty || query (_("Reinitialize source path to empty? ")))
{
xfree (source_path);
init_source_path ();
@@ -287,56 +388,100 @@ directory_command (char *dirname, int from_tty)
forget_cached_source_info ();
}
+/* Add a path given with the -d command line switch.
+ This will not be quoted so we must not treat spaces as separators. */
+
+void
+directory_switch (char *dirname, int from_tty)
+{
+ add_path (dirname, &source_path, 0);
+}
+
/* Add zero or more directories to the front of an arbitrary path. */
void
mod_path (char *dirname, char **which_path)
+{
+ add_path (dirname, which_path, 1);
+}
+
+/* Workhorse of mod_path. Takes an extra argument to determine
+ if dirname should be parsed for separators that indicate multiple
+ directories. This allows for interfaces that pre-parse the dirname
+ and allow specification of traditional separator characters such
+ as space or tab. */
+
+void
+add_path (char *dirname, char **which_path, int parse_separators)
{
char *old = *which_path;
int prefix = 0;
+ char **argv = NULL;
+ char *arg;
+ int argv_index = 0;
if (dirname == 0)
return;
- dirname = xstrdup (dirname);
- make_cleanup (xfree, dirname);
+ if (parse_separators)
+ {
+ /* This will properly parse the space and tab separators
+ and any quotes that may exist. DIRNAME_SEPARATOR will
+ be dealt with later. */
+ argv = buildargv (dirname);
+ make_cleanup_freeargv (argv);
+
+ if (argv == NULL)
+ nomem (0);
+
+ arg = argv[0];
+ }
+ else
+ {
+ arg = xstrdup (dirname);
+ make_cleanup (xfree, arg);
+ }
do
{
- char *name = dirname;
- register char *p;
+ char *name = arg;
+ char *p;
struct stat st;
{
- char *separator = strchr (name, DIRNAME_SEPARATOR);
- char *space = strchr (name, ' ');
- char *tab = strchr (name, '\t');
+ char *separator = NULL;
- if (separator == 0 && space == 0 && tab == 0)
- p = dirname = name + strlen (name);
+ /* Spaces and tabs will have been removed by buildargv().
+ The directories will there be split into a list but
+ each entry may still contain DIRNAME_SEPARATOR. */
+ if (parse_separators)
+ separator = strchr (name, DIRNAME_SEPARATOR);
+
+ if (separator == 0)
+ p = arg = name + strlen (name);
else
{
- p = 0;
- if (separator != 0 && (p == 0 || separator < p))
- p = separator;
- if (space != 0 && (p == 0 || space < p))
- p = space;
- if (tab != 0 && (p == 0 || tab < p))
- p = tab;
- dirname = p + 1;
- while (*dirname == DIRNAME_SEPARATOR
- || *dirname == ' '
- || *dirname == '\t')
- ++dirname;
+ p = separator;
+ arg = p + 1;
+ while (*arg == DIRNAME_SEPARATOR)
+ ++arg;
}
+
+ /* If there are no more directories in this argument then start
+ on the next argument next time round the loop (if any). */
+ if (*arg == '\0')
+ arg = parse_separators ? argv[++argv_index] : NULL;
}
- if (!(IS_DIR_SEPARATOR (*name) && p <= name + 1) /* "/" */
+ /* name is the start of the directory.
+ p is the separator (or null) following the end. */
+
+ while (!(IS_DIR_SEPARATOR (*name) && p <= name + 1) /* "/" */
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
/* On MS-DOS and MS-Windows, h:\ is different from h: */
- && !(p == name + 3 && name[1] == ':') /* "d:/" */
+ && !(p == name + 3 && name[1] == ':') /* "d:/" */
#endif
- && IS_DIR_SEPARATOR (p[-1]))
+ && IS_DIR_SEPARATOR (p[-1]))
/* Sigh. "foo/" => "foo" */
--p;
*p = '\0';
@@ -373,10 +518,10 @@ mod_path (char *dirname, char **which_path)
name = tilde_expand (name);
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
else if (IS_ABSOLUTE_PATH (name) && p == name + 2) /* "d:" => "d:." */
- name = concat (name, ".", NULL);
+ name = concat (name, ".", (char *)NULL);
#endif
else if (!IS_ABSOLUTE_PATH (name) && name[0] != '$')
- name = concat (current_directory, SLASH_STRING, name, NULL);
+ name = concat (current_directory, SLASH_STRING, name, (char *)NULL);
else
name = savestring (name, p - name);
make_cleanup (xfree, name);
@@ -400,12 +545,12 @@ mod_path (char *dirname, char **which_path)
print_sys_errmsg (name, save_errno);
}
else if ((st.st_mode & S_IFMT) != S_IFDIR)
- warning ("%s is not a directory.", name);
+ warning (_("%s is not a directory."), name);
}
append:
{
- register unsigned int len = strlen (name);
+ unsigned int len = strlen (name);
p = *which_path;
while (1)
@@ -441,22 +586,24 @@ mod_path (char *dirname, char **which_path)
tinybuf[0] = DIRNAME_SEPARATOR;
tinybuf[1] = '\0';
- /* If we have already tacked on a name(s) in this command, be sure they stay on the front as we tack on some more. */
+ /* If we have already tacked on a name(s) in this command, be sure they stay
+ on the front as we tack on some more. */
if (prefix)
{
char *temp, c;
c = old[prefix];
old[prefix] = '\0';
- temp = concat (old, tinybuf, name, NULL);
+ temp = concat (old, tinybuf, name, (char *)NULL);
old[prefix] = c;
- *which_path = concat (temp, "", &old[prefix], NULL);
+ *which_path = concat (temp, "", &old[prefix], (char *)NULL);
prefix = strlen (temp);
xfree (temp);
}
else
{
- *which_path = concat (name, (old[0] ? tinybuf : old), old, NULL);
+ *which_path = concat (name, (old[0] ? tinybuf : old),
+ old, (char *)NULL);
prefix = strlen (name);
}
xfree (old);
@@ -465,46 +612,71 @@ mod_path (char *dirname, char **which_path)
}
skip_dup:;
}
- while (*dirname != '\0');
+ while (arg != NULL);
}
static void
source_info (char *ignore, int from_tty)
{
- register struct symtab *s = current_source_symtab;
+ struct symtab *s = current_source_symtab;
if (!s)
{
- printf_filtered ("No current source file.\n");
+ printf_filtered (_("No current source file.\n"));
return;
}
- printf_filtered ("Current source file is %s\n", s->filename);
+ printf_filtered (_("Current source file is %s\n"), s->filename);
if (s->dirname)
- printf_filtered ("Compilation directory is %s\n", s->dirname);
+ printf_filtered (_("Compilation directory is %s\n"), s->dirname);
if (s->fullname)
- printf_filtered ("Located in %s\n", s->fullname);
+ printf_filtered (_("Located in %s\n"), s->fullname);
if (s->nlines)
- printf_filtered ("Contains %d line%s.\n", s->nlines,
+ printf_filtered (_("Contains %d line%s.\n"), s->nlines,
s->nlines == 1 ? "" : "s");
- printf_filtered ("Source language is %s.\n", language_str (s->language));
- printf_filtered ("Compiled with %s debugging format.\n", s->debugformat);
+ 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");
}
+/* 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.
- If TRY_CWD_FIRST, try to open ./STRING before searching PATH.
+ OPTS specifies the function behaviour in specific cases.
+
+ If OPF_TRY_CWD_FIRST, try to open ./STRING before searching PATH.
(ie pretend the first element of PATH is "."). This also indicates
that a slash in STRING disables searching of the path (this is
so that "exec-file ./foo" or "symbol-file ./foo" insures that you
get that particular version of foo or an error message).
+ If OPTS has OPF_SEARCH_IN_PATH set, absolute names will also be
+ searched in path (we usually want this for source files but not for
+ executables).
+
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!!!
@@ -513,39 +685,52 @@ source_info (char *ignore, int from_tty)
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 (const char *path, int try_cwd_first, const char *string,
+openp (const char *path, int opts, const char *string,
int mode, int prot,
char **filename_opened)
{
- register int fd;
- register char *filename;
+ int fd;
+ char *filename;
const char *p;
const char *p1;
- register int len;
+ int len;
int alloclen;
if (!path)
path = ".";
-#if defined(_WIN32) || defined(__CYGWIN__)
mode |= O_BINARY;
-#endif
- if (try_cwd_first || IS_ABSOLUTE_PATH (string))
+ if ((opts & OPF_TRY_CWD_FIRST) || IS_ABSOLUTE_PATH (string))
{
int i;
- 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 (IS_DIR_SEPARATOR (string[i]))
- goto done;
+
+ if (is_regular_file (string))
+ {
+ filename = alloca (strlen (string) + 1);
+ strcpy (filename, string);
+ fd = open (filename, mode, prot);
+ if (fd >= 0)
+ goto done;
+ }
+ else
+ {
+ filename = NULL;
+ fd = -1;
+ }
+
+ if (!(opts & OPF_SEARCH_IN_PATH))
+ for (i = 0; string[i]; i++)
+ if (IS_DIR_SEPARATOR (string[i]))
+ goto done;
}
+ /* /foo => foo, to avoid multiple slashes that Emacs doesn't like. */
+ while (IS_DIR_SEPARATOR(string[0]))
+ string++;
+
/* ./foo => foo */
while (string[0] == '.' && IS_DIR_SEPARATOR (string[1]))
string += 2;
@@ -591,44 +776,38 @@ openp (const char *path, int try_cwd_first, const char *string,
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 = NULL;
else if (IS_ABSOLUTE_PATH (filename))
- *filename_opened = savestring (filename, strlen (filename));
+ *filename_opened = xfullpath (filename);
else
{
/* Beware the // my son, the Emacs barfs, the botch that catch... */
- *filename_opened = concat (current_directory,
- IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
- ? "" : SLASH_STRING,
- filename, NULL);
+ char *f = concat (current_directory,
+ IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
+ ? "" : SLASH_STRING,
+ filename, (char *)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;
}
@@ -644,14 +823,14 @@ done:
If the file was found, this function returns 1, and FULL_PATHNAME is
set to the fully-qualified pathname.
- Else, this functions returns 0, and FULL_PATHNAME is set to NULL.
- */
+ Else, this functions returns 0, and FULL_PATHNAME is set to NULL. */
int
source_full_path_of (char *filename, char **full_pathname)
{
int fd;
- fd = openp (source_path, 1, filename, O_RDONLY, 0, full_pathname);
+ fd = openp (source_path, OPF_TRY_CWD_FIRST | OPF_SEARCH_IN_PATH, filename,
+ O_RDONLY, 0, full_pathname);
if (fd < 0)
{
*full_pathname = NULL;
@@ -662,31 +841,153 @@ source_full_path_of (char *filename, char **full_pathname)
return 1;
}
+/* Return non-zero if RULE matches PATH, that is if the rule can be
+ applied to PATH. */
-/* Open a source file given a symtab S. Returns a file descriptor or
- negative number for error. */
+static int
+substitute_path_rule_matches (const struct substitute_path_rule *rule,
+ const char *path)
+{
+ const int from_len = strlen (rule->from);
+ const int path_len = strlen (path);
+ char *path_start;
-int
-open_source_file (struct symtab *s)
+ if (path_len < from_len)
+ return 0;
+
+ /* The substitution rules are anchored at the start of the path,
+ so the path should start with rule->from. There is no filename
+ comparison routine, so we need to extract the first FROM_LEN
+ characters from PATH first and use that to do the comparison. */
+
+ path_start = alloca (from_len + 1);
+ strncpy (path_start, path, from_len);
+ path_start[from_len] = '\0';
+
+ if (FILENAME_CMP (path_start, rule->from) != 0)
+ return 0;
+
+ /* Make sure that the region in the path that matches the substitution
+ rule is immediately followed by a directory separator (or the end of
+ string character). */
+
+ if (path[from_len] != '\0' && !IS_DIR_SEPARATOR (path[from_len]))
+ return 0;
+
+ return 1;
+}
+
+/* Find the substitute-path rule that applies to PATH and return it.
+ Return NULL if no rule applies. */
+
+static struct substitute_path_rule *
+get_substitute_path_rule (const char *path)
+{
+ struct substitute_path_rule *rule = substitute_path_rules;
+
+ while (rule != NULL && !substitute_path_rule_matches (rule, path))
+ rule = rule->next;
+
+ return rule;
+}
+
+/* If the user specified a source path substitution rule that applies
+ to PATH, then apply it and return the new path. This new path must
+ be deallocated afterwards.
+
+ Return NULL if no substitution rule was specified by the user,
+ or if no rule applied to the given PATH. */
+
+static char *
+rewrite_source_path (const char *path)
+{
+ const struct substitute_path_rule *rule = get_substitute_path_rule (path);
+ char *new_path;
+ int from_len;
+
+ if (rule == NULL)
+ return NULL;
+
+ from_len = strlen (rule->from);
+
+ /* Compute the rewritten path and return it. */
+
+ new_path =
+ (char *) xmalloc (strlen (path) + 1 + strlen (rule->to) - from_len);
+ strcpy (new_path, rule->to);
+ strcat (new_path, path + from_len);
+
+ return new_path;
+}
+
+/* This function is capable of finding the absolute path to a
+ source file, and opening it, provided you give it an
+ OBJFILE and FILENAME. Both the DIRNAME and FULLNAME are only
+ added suggestions on where to find the file.
+
+ OBJFILE should be the objfile associated with a psymtab or symtab.
+ FILENAME should be the filename to open.
+ DIRNAME is the compilation directory of a particular source file.
+ Only some debug formats provide this info.
+ FULLNAME can be the last known absolute path to the file in question.
+ Space for the path must have been malloc'd. If a path substitution
+ is applied we free the old value and set a new one.
+
+ On Success
+ A valid file descriptor is returned. ( the return value is positive )
+ FULLNAME is set to the absolute path to the file just opened.
+ The caller is responsible for freeing FULLNAME.
+
+ On Failure
+ An invalid file descriptor is returned. ( the return value is negative )
+ FULLNAME is set to NULL. */
+
+static int
+find_and_open_source (struct objfile *objfile,
+ const char *filename,
+ const char *dirname,
+ char **fullname)
{
char *path = source_path;
const char *p;
int result;
- char *fullname;
/* Quick way out if we already know its full name */
- if (s->fullname)
+
+ if (*fullname)
{
- result = open (s->fullname, OPEN_MODE);
+ /* The user may have requested that source paths be rewritten
+ according to substitution rules he provided. If a substitution
+ rule applies to this path, then apply it. */
+ char *rewritten_fullname = rewrite_source_path (*fullname);
+
+ if (rewritten_fullname != NULL)
+ {
+ xfree (*fullname);
+ *fullname = rewritten_fullname;
+ }
+
+ result = open (*fullname, OPEN_MODE);
if (result >= 0)
return result;
/* Didn't work -- free old one, try again. */
- mfree (s->objfile->md, s->fullname);
- s->fullname = NULL;
+ xfree (*fullname);
+ *fullname = NULL;
}
- if (s->dirname != NULL)
+ if (dirname != NULL)
{
+ /* If necessary, rewrite the compilation directory name according
+ to the source path substitution rules specified by the user. */
+
+ char *rewritten_dirname = rewrite_source_path (dirname);
+
+ if (rewritten_dirname != NULL)
+ {
+ make_cleanup (xfree, rewritten_dirname);
+ dirname = rewritten_dirname;
+ }
+
/* Replace a path entry of $cdir with the compilation directory name */
#define cdir_len 5
/* We cast strstr's result in case an ANSIhole has made it const,
@@ -698,77 +999,112 @@ open_source_file (struct symtab *s)
int len;
path = (char *)
- alloca (strlen (source_path) + 1 + strlen (s->dirname) + 1);
+ alloca (strlen (source_path) + 1 + strlen (dirname) + 1);
len = p - source_path;
strncpy (path, source_path, len); /* Before $cdir */
- strcpy (path + len, s->dirname); /* new stuff */
+ strcpy (path + len, dirname); /* new stuff */
strcat (path + len, source_path + len + cdir_len); /* After $cdir */
}
}
- result = openp (path, 0, s->filename, OPEN_MODE, 0, &s->fullname);
- if (result < 0)
+ if (IS_ABSOLUTE_PATH (filename))
{
- /* Didn't work. Try using just the basename. */
- p = lbasename (s->filename);
- if (p != s->filename)
- result = openp (path, 0, p, OPEN_MODE, 0, &s->fullname);
+ /* If filename is absolute path, try the source path
+ substitution on it. */
+ char *rewritten_filename = rewrite_source_path (filename);
+
+ if (rewritten_filename != NULL)
+ {
+ make_cleanup (xfree, rewritten_filename);
+ filename = rewritten_filename;
+ }
}
- /* 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)
+
+ result = openp (path, OPF_SEARCH_IN_PATH, filename, OPEN_MODE, 0, fullname);
+ if (result < 0)
{
- fullname = s->fullname;
- s->fullname = mstrsave (s->objfile->md, s->fullname);
- xfree (fullname);
+ /* Didn't work. Try using just the basename. */
+ p = lbasename (filename);
+ if (p != filename)
+ result = openp (path, OPF_SEARCH_IN_PATH, p, OPEN_MODE, 0, fullname);
}
+
return result;
}
-/* Return the path to the source file associated with symtab. Returns NULL
- if no symtab. */
+/* Open a source file given a symtab S. Returns a file descriptor or
+ negative number for error.
+
+ This function is a convience function to find_and_open_source. */
+
+int
+open_source_file (struct symtab *s)
+{
+ if (!s)
+ return -1;
+
+ return find_and_open_source (s->objfile, s->filename, s->dirname,
+ &s->fullname);
+}
+
+/* Finds the fullname that a symtab represents.
+
+ If this functions finds the fullname, it will save it in s->fullname
+ and it will also return the value.
+ If this function fails to find the file that this symtab represents,
+ NULL will be returned and s->fullname will be set to NULL. */
char *
-symtab_to_filename (struct symtab *s)
+symtab_to_fullname (struct symtab *s)
{
- int fd;
+ int r;
if (!s)
return NULL;
- /* If we've seen the file before, just return fullname. */
+ /* Don't check s->fullname here, the file could have been
+ deleted/moved/..., look for it again */
+ r = find_and_open_source (s->objfile, s->filename, s->dirname,
+ &s->fullname);
- if (s->fullname)
- return s->fullname;
+ if (r)
+ {
+ close (r);
+ return s->fullname;
+ }
- /* Try opening the file to setup fullname */
+ return NULL;
+}
- fd = open_source_file (s);
- if (fd < 0)
- return s->filename; /* File not found. Just use short name */
+/* Finds the fullname that a partial_symtab represents.
- /* Found the file. Cleanup and return the full name */
+ If this functions finds the fullname, it will save it in ps->fullname
+ and it will also return the value.
- close (fd);
- return s->fullname;
+ If this function fails to find the file that this partial_symtab represents,
+ NULL will be returned and ps->fullname will be set to NULL. */
+char *
+psymtab_to_fullname (struct partial_symtab *ps)
+{
+ int r;
+
+ if (!ps)
+ return NULL;
+
+ /* Don't check ps->fullname here, the file could have been
+ deleted/moved/..., look for it again */
+ r = find_and_open_source (ps->objfile, ps->filename, ps->dirname,
+ &ps->fullname);
+
+ if (r)
+ {
+ close (r);
+ return ps->fullname;
+ }
+
+ return NULL;
}
-
/* Create and initialize the table S->line_charpos that records
the positions of the lines in the source file, which is assumed
to be open on descriptor DESC.
@@ -778,29 +1114,25 @@ void
find_source_lines (struct symtab *s, int desc)
{
struct stat st;
- register char *data, *p, *end;
+ char *data, *p, *end;
int nlines = 0;
int lines_allocated = 1000;
int *line_charpos;
long mtime = 0;
int size;
- line_charpos = (int *) xmmalloc (s->objfile->md,
- lines_allocated * sizeof (int));
+ gdb_assert (s);
+ line_charpos = (int *) xmalloc (lines_allocated * sizeof (int));
if (fstat (desc, &st) < 0)
perror_with_name (s->filename);
- if (s && s->objfile && s->objfile->obfd)
- mtime = bfd_get_mtime (s->objfile->obfd);
+ if (s->objfile && s->objfile->obfd)
+ mtime = s->objfile->mtime;
else if (exec_bfd)
- mtime = bfd_get_mtime (exec_bfd);
+ mtime = exec_bfd_mtime;
if (mtime && mtime < st.st_mtime)
- {
- if (tui_version)
- printf_filtered ("\n");
- warning ("Source file is more recent than executable.\n");
- }
+ warning (_("Source file is more recent than executable."));
#ifdef LSEEK_NOT_LINEAR
{
@@ -818,8 +1150,8 @@ find_source_lines (struct symtab *s, int desc)
{
lines_allocated *= 2;
line_charpos =
- (int *) xmrealloc (s->objfile->md, (char *) line_charpos,
- sizeof (int) * lines_allocated);
+ (int *) xrealloc ((char *) line_charpos,
+ sizeof (int) * lines_allocated);
}
line_charpos[nlines++] = lseek (desc, 0, SEEK_CUR);
}
@@ -856,8 +1188,8 @@ find_source_lines (struct symtab *s, int desc)
{
lines_allocated *= 2;
line_charpos =
- (int *) xmrealloc (s->objfile->md, (char *) line_charpos,
- sizeof (int) * lines_allocated);
+ (int *) xrealloc ((char *) line_charpos,
+ sizeof (int) * lines_allocated);
}
line_charpos[nlines++] = p - data;
}
@@ -867,8 +1199,7 @@ find_source_lines (struct symtab *s, int desc)
#endif /* lseek linear. */
s->nlines = nlines;
s->line_charpos =
- (int *) xmrealloc (s->objfile->md, (char *) line_charpos,
- nlines * sizeof (int));
+ (int *) xrealloc ((char *) line_charpos, nlines * sizeof (int));
}
@@ -892,10 +1223,10 @@ source_line_charpos (struct symtab *s, int line)
/* Return the line number of character position POS in symtab S. */
int
-source_charpos_line (register struct symtab *s, register int chr)
+source_charpos_line (struct symtab *s, int chr)
{
- register int line = 0;
- register int *lnp;
+ int line = 0;
+ int *lnp;
if (s == 0 || s->line_charpos == 0)
return 0;
@@ -922,7 +1253,7 @@ source_charpos_line (register struct symtab *s, register int chr)
static int
get_filename_and_charpos (struct symtab *s, char **fullname)
{
- register int desc, linenums_changed = 0;
+ int desc, linenums_changed = 0;
desc = open_source_file (s);
if (desc < 0)
@@ -980,9 +1311,9 @@ static void print_source_lines_base (struct symtab *s, int line, int stopline,
static void
print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
{
- register int c;
- register int desc;
- register FILE *stream;
+ int c;
+ int desc;
+ FILE *stream;
int nlines = stopline - line;
/* Regardless of whether we can open the file, set current_source_symtab. */
@@ -990,11 +1321,9 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
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))
{
@@ -1006,14 +1335,12 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
desc = last_source_error;
noerror = 1;
}
-#ifdef UI_OUT
}
else
{
desc = -1;
noerror = 1;
}
-#endif
if (desc < 0)
{
@@ -1026,14 +1353,10 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
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;
}
@@ -1046,7 +1369,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
if (line < 1 || line > s->nlines)
{
close (desc);
- error ("Line number %d out of range; %s has %d lines.",
+ error (_("Line number %d out of range; %s has %d lines."),
line, s->filename, s->nlines);
}
@@ -1061,7 +1384,6 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
while (nlines-- > 0)
{
-#ifdef UI_OUT
char buf[20];
c = fgetc (stream);
@@ -1079,7 +1401,6 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
}
else if (c == 0177)
ui_out_text (uiout, "^?");
-#ifdef CRLF_SOURCE_FILES
else if (c == '\r')
{
/* Skip a \r character, but only before a \n. */
@@ -1090,7 +1411,6 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
if (c1 != EOF)
ungetc (c1, stream);
}
-#endif
else
{
sprintf (buf, "%c", c);
@@ -1098,260 +1418,20 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
}
}
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);
}
/* Show source lines from the file of symtab S, starting with line
- number LINE and stopping before line number STOPLINE. If this is the
+ number LINE and stopping before line number STOPLINE. If this is
not the command line version, then the source is shown in the source
window otherwise it is simply printed */
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
-}
-
-
-
-/* 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
-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. */
@@ -1364,7 +1444,7 @@ line_info (char *arg, int from_tty)
CORE_ADDR start_pc, end_pc;
int i;
- INIT_SAL (&sal); /* initialize to zeroes */
+ init_sal (&sal); /* initialize to zeroes */
if (arg == 0)
{
@@ -1390,7 +1470,7 @@ line_info (char *arg, int from_tty)
if (sal.symtab == 0)
{
- printf_filtered ("No line number information available");
+ printf_filtered (_("No line number information available"));
if (sal.pc != 0)
{
/* This is useful for "info line *0x7f34". If we can't tell the
@@ -1445,7 +1525,7 @@ line_info (char *arg, int from_tty)
/* Is there any case in which we get here, and have an address
which the user would want to see? If we have debugging symbols
and no line numbers? */
- printf_filtered ("Line number %d is out of range for \"%s\".\n",
+ printf_filtered (_("Line number %d is out of range for \"%s\".\n"),
sal.line, sal.symtab->filename);
}
xfree (sals.sals);
@@ -1453,43 +1533,20 @@ line_info (char *arg, int from_tty)
/* Commands to search the source file for a regexp. */
-/* ARGSUSED */
static void
forward_search_command (char *regex, int from_tty)
{
- register int c;
- register int desc;
- register FILE *stream;
+ int c;
+ int desc;
+ 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)
- error (msg);
+ error (("%s"), msg);
if (current_source_symtab == 0)
select_source_symtab (0);
@@ -1504,7 +1561,7 @@ forward_search_command (char *regex, int from_tty)
if (line < 1 || line > current_source_symtab->nlines)
{
close (desc);
- error ("Expression not found");
+ error (_("Expression not found"));
}
if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
@@ -1518,7 +1575,7 @@ forward_search_command (char *regex, int from_tty)
while (1)
{
static char *buf = NULL;
- register char *p;
+ char *p;
int cursize, newsize;
cursize = 256;
@@ -1541,7 +1598,6 @@ forward_search_command (char *regex, int from_tty)
}
while (c != '\n' && (c = getc (stream)) >= 0);
-#ifdef CRLF_SOURCE_FILES
/* Remove the \r, if any, at the end of the line, otherwise
regular expressions that end with $ or \n won't work. */
if (p - buf > 1 && p[-2] == '\r')
@@ -1549,7 +1605,6 @@ forward_search_command (char *regex, int from_tty)
p--;
p[-1] = '\n';
}
-#endif
/* we now have a source line in buf, null terminate and match */
*p = 0;
@@ -1557,8 +1612,6 @@ forward_search_command (char *regex, int from_tty)
{
/* 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,
@@ -1569,46 +1622,24 @@ forward_search_command (char *regex, int from_tty)
line++;
}
- printf_filtered ("Expression not found\n");
+ printf_filtered (_("Expression not found\n"));
fclose (stream);
}
-/* ARGSUSED */
static void
reverse_search_command (char *regex, int from_tty)
{
- register int c;
- register int desc;
- register FILE *stream;
+ int c;
+ int desc;
+ 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)
- error (msg);
+ error (("%s"), msg);
if (current_source_symtab == 0)
select_source_symtab (0);
@@ -1623,7 +1654,7 @@ reverse_search_command (char *regex, int from_tty)
if (line < 1 || line > current_source_symtab->nlines)
{
close (desc);
- error ("Expression not found");
+ error (_("Expression not found"));
}
if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
@@ -1638,7 +1669,7 @@ reverse_search_command (char *regex, int from_tty)
{
/* FIXME!!! We walk right off the end of buf if we get a long line!!! */
char buf[4096]; /* Should be reasonable??? */
- register char *p = buf;
+ char *p = buf;
c = getc (stream);
if (c == EOF)
@@ -1649,7 +1680,6 @@ reverse_search_command (char *regex, int from_tty)
}
while (c != '\n' && (c = getc (stream)) >= 0);
-#ifdef CRLF_SOURCE_FILES
/* Remove the \r, if any, at the end of the line, otherwise
regular expressions that end with $ or \n won't work. */
if (p - buf > 1 && p[-2] == '\r')
@@ -1657,7 +1687,6 @@ reverse_search_command (char *regex, int from_tty)
p--;
p[-1] = '\n';
}
-#endif
/* We now have a source line in buf; null terminate and match. */
*p = 0;
@@ -1665,8 +1694,6 @@ reverse_search_command (char *regex, int from_tty)
{
/* 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,
@@ -1682,10 +1709,225 @@ reverse_search_command (char *regex, int from_tty)
}
}
- printf_filtered ("Expression not found\n");
+ printf_filtered (_("Expression not found\n"));
fclose (stream);
return;
}
+
+/* If the last character of PATH is a directory separator, then strip it. */
+
+static void
+strip_trailing_directory_separator (char *path)
+{
+ const int last = strlen (path) - 1;
+
+ if (last < 0)
+ return; /* No stripping is needed if PATH is the empty string. */
+
+ if (IS_DIR_SEPARATOR (path[last]))
+ path[last] = '\0';
+}
+
+/* Return the path substitution rule that matches FROM.
+ Return NULL if no rule matches. */
+
+static struct substitute_path_rule *
+find_substitute_path_rule (const char *from)
+{
+ struct substitute_path_rule *rule = substitute_path_rules;
+
+ while (rule != NULL)
+ {
+ if (FILENAME_CMP (rule->from, from) == 0)
+ return rule;
+ rule = rule->next;
+ }
+
+ return NULL;
+}
+
+/* Add a new substitute-path rule at the end of the current list of rules.
+ The new rule will replace FROM into TO. */
+
+static void
+add_substitute_path_rule (char *from, char *to)
+{
+ struct substitute_path_rule *rule;
+ struct substitute_path_rule *new_rule;
+
+ new_rule = xmalloc (sizeof (struct substitute_path_rule));
+ new_rule->from = xstrdup (from);
+ new_rule->to = xstrdup (to);
+ new_rule->next = NULL;
+
+ /* If the list of rules are empty, then insert the new rule
+ at the head of the list. */
+
+ if (substitute_path_rules == NULL)
+ {
+ substitute_path_rules = new_rule;
+ return;
+ }
+
+ /* Otherwise, skip to the last rule in our list and then append
+ the new rule. */
+
+ rule = substitute_path_rules;
+ while (rule->next != NULL)
+ rule = rule->next;
+
+ rule->next = new_rule;
+}
+
+/* Remove the given source path substitution rule from the current list
+ of rules. The memory allocated for that rule is also deallocated. */
+
+static void
+delete_substitute_path_rule (struct substitute_path_rule *rule)
+{
+ if (rule == substitute_path_rules)
+ substitute_path_rules = rule->next;
+ else
+ {
+ struct substitute_path_rule *prev = substitute_path_rules;
+
+ while (prev != NULL && prev->next != rule)
+ prev = prev->next;
+
+ gdb_assert (prev != NULL);
+
+ prev->next = rule->next;
+ }
+
+ xfree (rule->from);
+ xfree (rule->to);
+ xfree (rule);
+}
+
+/* Implement the "show substitute-path" command. */
+
+static void
+show_substitute_path_command (char *args, int from_tty)
+{
+ struct substitute_path_rule *rule = substitute_path_rules;
+ char **argv;
+ char *from = NULL;
+
+ argv = buildargv (args);
+ make_cleanup_freeargv (argv);
+
+ /* We expect zero or one argument. */
+
+ if (argv != NULL && argv[0] != NULL && argv[1] != NULL)
+ error (_("Too many arguments in command"));
+
+ if (argv != NULL && argv[0] != NULL)
+ from = argv[0];
+
+ /* Print the substitution rules. */
+
+ if (from != NULL)
+ printf_filtered
+ (_("Source path substitution rule matching `%s':\n"), from);
+ else
+ printf_filtered (_("List of all source path substitution rules:\n"));
+
+ while (rule != NULL)
+ {
+ if (from == NULL || FILENAME_CMP (rule->from, from) == 0)
+ printf_filtered (" `%s' -> `%s'.\n", rule->from, rule->to);
+ rule = rule->next;
+ }
+}
+
+/* Implement the "unset substitute-path" command. */
+
+static void
+unset_substitute_path_command (char *args, int from_tty)
+{
+ struct substitute_path_rule *rule = substitute_path_rules;
+ char **argv = buildargv (args);
+ char *from = NULL;
+ int rule_found = 0;
+
+ /* This function takes either 0 or 1 argument. */
+
+ make_cleanup_freeargv (argv);
+ if (argv != NULL && argv[0] != NULL && argv[1] != NULL)
+ error (_("Incorrect usage, too many arguments in command"));
+
+ if (argv != NULL && argv[0] != NULL)
+ from = argv[0];
+
+ /* If the user asked for all the rules to be deleted, ask him
+ to confirm and give him a chance to abort before the action
+ is performed. */
+
+ if (from == NULL
+ && !query (_("Delete all source path substitution rules? ")))
+ error (_("Canceled"));
+
+ /* Delete the rule matching the argument. No argument means that
+ all rules should be deleted. */
+
+ while (rule != NULL)
+ {
+ struct substitute_path_rule *next = rule->next;
+
+ if (from == NULL || FILENAME_CMP (from, rule->from) == 0)
+ {
+ delete_substitute_path_rule (rule);
+ rule_found = 1;
+ }
+
+ rule = next;
+ }
+
+ /* If the user asked for a specific rule to be deleted but
+ we could not find it, then report an error. */
+
+ if (from != NULL && !rule_found)
+ error (_("No substitution rule defined for `%s'"), from);
+}
+
+/* Add a new source path substitution rule. */
+
+static void
+set_substitute_path_command (char *args, int from_tty)
+{
+ char *from_path, *to_path;
+ char **argv;
+ struct substitute_path_rule *rule;
+
+ argv = buildargv (args);
+ make_cleanup_freeargv (argv);
+
+ if (argv == NULL || argv[0] == NULL || argv [1] == NULL)
+ error (_("Incorrect usage, too few arguments in command"));
+
+ if (argv[2] != NULL)
+ error (_("Incorrect usage, too many arguments in command"));
+
+ if (*(argv[0]) == '\0')
+ error (_("First argument must be at least one character long"));
+
+ /* Strip any trailing directory separator character in either FROM
+ or TO. The substitution rule already implicitly contains them. */
+ strip_trailing_directory_separator (argv[0]);
+ strip_trailing_directory_separator (argv[1]);
+
+ /* If a rule with the same "from" was previously defined, then
+ delete it. This new rule replaces it. */
+
+ rule = find_substitute_path_rule (argv[0]);
+ if (rule != NULL)
+ delete_substitute_path_rule (rule);
+
+ /* Insert the new substitution rule. */
+
+ add_substitute_path_rule (argv[0], argv[1]);
+}
+
void
_initialize_source (void)
@@ -1700,59 +1942,58 @@ _initialize_source (void)
just an approximation. */
re_set_syntax (RE_SYNTAX_GREP);
- c = add_cmd ("directory", class_files, directory_command,
- "Add directory DIR to beginning of search path for source files.\n\
+ c = add_cmd ("directory", class_files, directory_command, _("\
+Add directory DIR to beginning of search path for source files.\n\
Forget cached info on source file locations and line positions.\n\
DIR can also be $cwd for the current working directory, or $cdir for the\n\
directory in which the source file was compiled into object code.\n\
-With no argument, reset the search path to $cdir:$cwd, the default.",
+With no argument, reset the search path to $cdir:$cwd, the default."),
&cmdlist);
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\
+ add_cmd ("directories", no_class, show_directories, _("\
+Current search path for finding source files.\n\
$cwd in the path means the current working directory.\n\
-$cdir in the path means the compilation directory of the source file.",
+$cdir in the path means the compilation directory of the source file."),
&showlist);
if (xdb_commands)
{
add_com_alias ("D", "directory", class_files, 0);
- add_cmd ("ld", no_class, show_directories,
- "Current search path for finding source files.\n\
+ add_cmd ("ld", no_class, show_directories, _("\
+Current search path for finding source files.\n\
$cwd in the path means the current working directory.\n\
-$cdir in the path means the compilation directory of the source file.",
+$cdir in the path means the compilation directory of the source file."),
&cmdlist);
}
add_info ("source", source_info,
- "Information about the current source file.");
+ _("Information about the current source file."));
- add_info ("line", line_info,
- concat ("Core addresses of the code for a source line.\n\
+ add_info ("line", line_info, _("\
+Core addresses of the code for a source line.\n\
Line can be specified as\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\
-", "\
Default is to describe the last source line that was listed.\n\n\
This sets the default address for \"x\" to the line's first instruction\n\
so that \"x/i\" suffices to start examining the machine code.\n\
-The address is also stored as the value of \"$_\".", NULL));
+The address is also stored as the value of \"$_\"."));
- add_com ("forward-search", class_files, forward_search_command,
- "Search for regular expression (see regex(3)) from last line listed.\n\
-The matching line number is also stored as the value of \"$_\".");
+ add_com ("forward-search", class_files, forward_search_command, _("\
+Search for regular expression (see regex(3)) from last line listed.\n\
+The matching line number is also stored as the value of \"$_\"."));
add_com_alias ("search", "forward-search", class_files, 0);
- add_com ("reverse-search", class_files, reverse_search_command,
- "Search backward for regular expression (see regex(3)) from last line listed.\n\
-The matching line number is also stored as the value of \"$_\".");
+ add_com ("reverse-search", class_files, reverse_search_command, _("\
+Search backward for regular expression (see regex(3)) from last line listed.\n\
+The matching line number is also stored as the value of \"$_\"."));
if (xdb_commands)
{
@@ -1760,33 +2001,33 @@ The matching line number is also stored as the value of \"$_\".");
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,
- (char *) &lines_to_list,
- "Set number of source lines gdb will list by default.",
- &setlist),
- &showlist);
+ add_setshow_integer_cmd ("listsize", class_support, &lines_to_list, _("\
+Set number of source lines gdb will list by default."), _("\
+Show number of source lines gdb will list by default."), NULL,
+ NULL,
+ show_lines_to_list,
+ &setlist, &showlist);
+
+ add_cmd ("substitute-path", class_files, set_substitute_path_command,
+ _("\
+Usage: set substitute-path FROM TO\n\
+Add a substitution rule replacing FROM into TO in source file names.\n\
+If a substitution rule was previously set for FROM, the old rule\n\
+is replaced by the new one."),
+ &setlist);
+
+ add_cmd ("substitute-path", class_files, unset_substitute_path_command,
+ _("\
+Usage: unset substitute-path [FROM]\n\
+Delete the rule for substituting FROM in source file names. If FROM\n\
+is not specified, all substituting rules are deleted.\n\
+If the debugger cannot find a rule for FROM, it will display a warning."),
+ &unsetlist);
+
+ add_cmd ("substitute-path", class_files, show_substitute_path_command,
+ _("\
+Usage: show substitute-path [FROM]\n\
+Print the rule for substituting FROM in source file names. If FROM\n\
+is not specified, print all substitution rules."),
+ &showlist);
}