*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / source.c
index ebc82dc88f3ebdbdda577fe031a040ff366f0fc9..38aae31a4a3f9dfc6f84baa5b27160c36bd00a71 100644 (file)
@@ -1,6 +1,7 @@
 /* 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
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -16,8 +17,8 @@
 
    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.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
 #include "symtab.h"
@@ -28,6 +29,7 @@
 #include "gdbcmd.h"
 #include "frame.h"
 #include "value.h"
+#include "gdb_assert.h"
 
 #include <sys/types.h>
 #include "gdb_string.h"
 #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
-
-/* 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.  */
+#include "readline/readline.h"
 
-#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 +65,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 +74,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 +100,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 +124,93 @@ static int first_line_listed;
 static struct symtab *last_source_visited = NULL;
 static int last_source_error = 0;
 \f
+/* 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 +221,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 +241,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, 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;
@@ -172,12 +260,10 @@ 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))
+           current_source_symtab = s;
        }
     }
   if (current_source_symtab)
@@ -189,12 +275,10 @@ select_source_symtab (register struct symtab *s)
     {
       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))
+           cs_pst = ps;
        }
     }
   if (cs_pst)
@@ -202,8 +286,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 +297,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"));
 }
 \f
 static void
@@ -231,8 +315,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 +325,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 +356,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 +371,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 +387,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;
+
+       /* 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 && space == 0 && tab == 0)
-         p = dirname = name + strlen (name);
+       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 +517,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 +544,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 +585,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 +611,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");
 }
 \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.
 
-   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,46 +684,62 @@ 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 (char *path, int try_cwd_first, char *string, int mode, int prot,
+openp (const char *path, int opts, const char *string,
+       int mode, int prot,
        char **filename_opened)
 {
-  register int fd;
-  register char *filename;
-  register char *p, *p1;
-  register int len;
+  int fd;
+  char *filename;
+  const char *p;
+  const char *p1;
+  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 = 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;
 
   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
@@ -570,7 +757,7 @@ openp (char *path, int try_cwd_first, char *string, int mode, int prot,
          if (newlen > alloclen)
            {
              alloclen = newlen;
-             filename = (char *) alloca (alloclen);
+             filename = alloca (alloclen);
            }
          strcpy (filename, current_directory);
        }
@@ -588,44 +775,38 @@ openp (char *path, int try_cwd_first, char *string, int mode, int prot,
       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;
+       *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;
 }
@@ -641,14 +822,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;
@@ -659,31 +840,149 @@ 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;
+
+  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.
+
+   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.
+
+   On Failure
+     An invalid file descriptor is returned. ( the return value is negative ) 
+     FULLNAME is set to NULL.  */
 int
-open_source_file (struct symtab *s)
+find_and_open_source (struct objfile *objfile,
+                     const char *filename,
+                     const char *dirname,
+                     char **fullname)
 {
   char *path = source_path;
-  char *p;
+  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,
@@ -695,77 +994,106 @@ 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);
+  result = openp (path, OPF_SEARCH_IN_PATH, filename, OPEN_MODE, 0, fullname);
   if (result < 0)
     {
       /* Didn't work.  Try using just the basename. */
-      p = basename (s->filename);
-      if (p != s->filename)
-       result = openp (path, 0, p, OPEN_MODE, 0, &s->fullname);
+      p = lbasename (filename);
+      if (p != filename)
+       result = openp (path, OPF_SEARCH_IN_PATH, p, OPEN_MODE, 0, 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)
     {
-      fullname = s->fullname;
-      s->fullname = mstrsave (s->objfile->md, s->fullname);
-      xfree (fullname);
+      char *tmp_fullname;
+      tmp_fullname = *fullname;
+      *fullname = xstrdup (tmp_fullname);
+      xfree (tmp_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 ps->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 ps->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;
 }
 \f
-
 /* 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.
@@ -775,15 +1103,14 @@ 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));
+  line_charpos = (int *) xmalloc (lines_allocated * sizeof (int));
   if (fstat (desc, &st) < 0)
     perror_with_name (s->filename);
 
@@ -793,11 +1120,7 @@ find_source_lines (struct symtab *s, int desc)
     mtime = bfd_get_mtime (exec_bfd);
 
   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
   {
@@ -815,8 +1138,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);
          }
@@ -853,8 +1176,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;
          }
@@ -864,8 +1187,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));
 
 }
 
@@ -889,10 +1211,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;
@@ -919,7 +1241,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)
@@ -977,9 +1299,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. */
@@ -987,11 +1309,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))
        {
@@ -1003,14 +1323,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)
     {
@@ -1023,14 +1341,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;
     }
@@ -1043,7 +1357,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);
     }
 
@@ -1058,7 +1372,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);
@@ -1076,7 +1389,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.  */
@@ -1087,7 +1399,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);
@@ -1095,29 +1406,6 @@ 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);
@@ -1131,224 +1419,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror)
 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
-
-
-/* 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);
 }
 \f
 /* Print info on range of pc's in a specified line.  */
@@ -1361,7 +1432,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)
     {
@@ -1387,7 +1458,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
@@ -1442,7 +1513,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);
@@ -1450,43 +1521,20 @@ line_info (char *arg, int from_tty)
 \f
 /* 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);
@@ -1501,7 +1549,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)
@@ -1515,7 +1563,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;
@@ -1538,7 +1586,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')
@@ -1546,7 +1593,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;
@@ -1554,8 +1600,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,
@@ -1566,46 +1610,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);
@@ -1620,7 +1642,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)
@@ -1635,7 +1657,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)
@@ -1646,7 +1668,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')
@@ -1654,7 +1675,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;
@@ -1662,8 +1682,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,
@@ -1679,10 +1697,224 @@ 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.  */
+
+  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]);
+}
+
 \f
 void
 _initialize_source (void)
@@ -1697,59 +1929,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)
     {
@@ -1757,33 +1988,25 @@ 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,
+           _("\
+Add a source path substitution rule.  If a substitution rule was previously\n\
+set, it is overridden."), &setlist);
+
+  add_cmd ("substitute-path", class_files, unset_substitute_path_command,
+           _("\
+Remove the current source path substitution rule.  This has no effect\n\
+if no path substitution rule was previously specified."),
+           &unsetlist);
+
+  add_cmd ("substitute-path", class_files, show_substitute_path_command,
+           _("Show the current source path substitution rule."),
+           &showlist);
 }
This page took 0.046952 seconds and 4 git commands to generate.