AArch64: Refactor verifiers to make more general.
[deliverable/binutils-gdb.git] / gdb / source.c
index 54d569331b3815ddd7002939c0bdd6c18cb5cc85..ec0ea3b81e37fd10c3a75ab030a5688a37aef66e 100644 (file)
@@ -1,5 +1,5 @@
 /* List lines of source files for GDB, the GNU debugger.
-   Copyright (C) 1986-2013 Free Software Foundation, Inc.
+   Copyright (C) 1986-2018 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "gdbcmd.h"
 #include "frame.h"
 #include "value.h"
-#include "gdb_assert.h"
+#include "filestuff.h"
 
 #include <sys/types.h>
-#include "gdb_string.h"
-#include "gdb_stat.h"
 #include <fcntl.h>
 #include "gdbcore.h"
 #include "gdb_regex.h"
 #include "completer.h"
 #include "ui-out.h"
 #include "readline/readline.h"
-
-#include "psymtab.h"
-
+#include "common/enum-flags.h"
+#include "common/scoped_fd.h"
+#include <algorithm>
+#include "common/pathstuff.h"
 
 #define OPEN_MODE (O_RDONLY | O_BINARY)
 #define FDOPEN_MODE FOPEN_RB
 
-/* Prototypes for exported functions.  */
-
-void _initialize_source (void);
-
 /* Prototypes for local functions.  */
 
 static int get_filename_and_charpos (struct symtab *, char **);
 
-static void reverse_search_command (char *, int);
-
-static void forward_search_command (char *, int);
-
-static void line_info (char *, int);
-
-static void source_info (char *, int);
-
 /* Path of directories to search for source files.
    Same format as the PATH environment variable's value.  */
 
@@ -98,7 +85,7 @@ static struct program_space *current_source_pspace;
    and friends should be rewritten to count characters and see where
    things are wrapping, but that would be a fair amount of work.  */
 
-int lines_to_list = 10;
+static 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)
@@ -109,12 +96,35 @@ show_lines_to_list (struct ui_file *file, int from_tty,
                    value);
 }
 
+/* Possible values of 'set filename-display'.  */
+static const char filename_display_basename[] = "basename";
+static const char filename_display_relative[] = "relative";
+static const char filename_display_absolute[] = "absolute";
+
+static const char *const filename_display_kind_names[] = {
+  filename_display_basename,
+  filename_display_relative,
+  filename_display_absolute,
+  NULL
+};
+
+static const char *filename_display_string = filename_display_relative;
+
+static void
+show_filename_display_string (struct ui_file *file, int from_tty,
+                             struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Filenames are displayed as \"%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.  */
 
 static int last_line_listed;
 
-/* First line number listed by last listing command.  */
+/* First line number listed by last listing command.  If 0, then no
+   source lines have yet been listed since the last time the current
+   source line was changed.  */
 
 static int first_line_listed;
 
@@ -134,6 +144,16 @@ get_first_line_listed (void)
   return first_line_listed;
 }
 
+/* Clear line listed range.  This makes the next "list" center the
+   printed source lines around the current source line.  */
+
+static void
+clear_lines_listed_range (void)
+{
+  first_line_listed = 0;
+  last_line_listed = 0;
+}
+
 /* 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
@@ -151,7 +171,7 @@ get_lines_to_list (void)
 struct symtab_and_line
 get_current_source_symtab_and_line (void)
 {
-  struct symtab_and_line cursal = { 0 };
+  symtab_and_line cursal;
 
   cursal.pspace = current_source_pspace;
   cursal.symtab = current_source_symtab;
@@ -187,9 +207,9 @@ set_default_source_symtab_and_line (void)
    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)
+set_current_source_symtab_and_line (const symtab_and_line &sal)
 {
-  struct symtab_and_line cursal = { 0 };
+  symtab_and_line cursal;
 
   cursal.pspace = current_source_pspace;
   cursal.symtab = current_source_symtab;
@@ -197,9 +217,12 @@ set_current_source_symtab_and_line (const struct symtab_and_line *sal)
   cursal.pc = 0;
   cursal.end = 0;
 
-  current_source_pspace = sal->pspace;
-  current_source_symtab = sal->symtab;
-  current_source_line = sal->line;
+  current_source_pspace = sal.pspace;
+  current_source_symtab = sal.symtab;
+  current_source_line = sal.line;
+
+  /* Force the next "list" to center around the current line.  */
+  clear_lines_listed_range ();
 
   return cursal;
 }
@@ -224,9 +247,8 @@ clear_current_source_symtab_and_line (void)
 void
 select_source_symtab (struct symtab *s)
 {
-  struct symtabs_and_lines sals;
-  struct symtab_and_line sal;
   struct objfile *ofp;
+  struct compunit_symtab *cu;
 
   if (s)
     {
@@ -241,15 +263,15 @@ select_source_symtab (struct symtab *s)
 
   /* Make the default place to list be the function `main'
      if one exists.  */
-  if (lookup_symbol (main_name (), 0, VAR_DOMAIN, 0))
+  if (lookup_symbol (main_name (), 0, VAR_DOMAIN, 0).symbol)
     {
-      sals = decode_line_with_current_source (main_name (),
-                                             DECODE_LINE_FUNFIRSTLINE);
-      sal = sals.sals[0];
-      xfree (sals.sals);
+      std::vector<symtab_and_line> sals
+       = decode_line_with_current_source (main_name (),
+                                          DECODE_LINE_FUNFIRSTLINE);
+      const symtab_and_line &sal = sals[0];
       current_source_pspace = sal.pspace;
       current_source_symtab = sal.symtab;
-      current_source_line = max (sal.line - (lines_to_list - 1), 1);
+      current_source_line = std::max (sal.line - (lines_to_list - 1), 1);
       if (current_source_symtab)
        return;
     }
@@ -259,19 +281,16 @@ select_source_symtab (struct symtab *s)
 
   current_source_line = 1;
 
-  ALL_OBJFILES (ofp)
+  ALL_FILETABS (ofp, cu, s)
     {
-      for (s = ofp->symtabs; s; s = s->next)
-       {
-         const char *name = s->filename;
-         int len = strlen (name);
+      const char *name = s->filename;
+      int len = strlen (name);
 
-         if (!(len > 2 && (strcmp (&name[len - 2], ".h") == 0
-             || strcmp (name, "<<C++-namespaces>>") == 0)))
-           {
-             current_source_pspace = current_program_space;
-             current_source_symtab = s;
-           }
+      if (!(len > 2 && (strcmp (&name[len - 2], ".h") == 0
+                       || strcmp (name, "<<C++-namespaces>>") == 0)))
+       {
+         current_source_pspace = current_program_space;
+         current_source_symtab = s;
        }
     }
 
@@ -296,7 +315,8 @@ select_source_symtab (struct symtab *s)
    path list.  The theory is that set(show(dir)) should be a no-op.  */
 
 static void
-set_directories_command (char *args, int from_tty, struct cmd_list_element *c)
+set_directories_command (const char *args,
+                        int from_tty, struct cmd_list_element *c)
 {
   /* This is the value that was set.
      It needs to be processed to maintain $cdir:$cwd and remove dups.  */
@@ -340,9 +360,10 @@ show_directories_command (struct ui_file *file, int from_tty,
 void
 forget_cached_source_info_for_objfile (struct objfile *objfile)
 {
+  struct compunit_symtab *cu;
   struct symtab *s;
 
-  ALL_OBJFILE_SYMTABS (objfile, s)
+  ALL_OBJFILE_FILETABS (objfile, cu, s)
     {
       if (s->line_charpos != NULL)
        {
@@ -392,7 +413,7 @@ init_source_path (void)
 /* Add zero or more directories to the front of the source path.  */
 
 static void
-directory_command (char *dirname, int from_tty)
+directory_command (const char *dirname, int from_tty)
 {
   dont_repeat ();
   /* FIXME, this goes to "delete dir"...  */
@@ -417,7 +438,7 @@ directory_command (char *dirname, int from_tty)
    This will not be quoted so we must not treat spaces as separators.  */
 
 void
-directory_switch (char *dirname, int from_tty)
+directory_switch (const char *dirname, int from_tty)
 {
   add_path (dirname, &source_path, 0);
 }
@@ -425,7 +446,7 @@ directory_switch (char *dirname, int from_tty)
 /* Add zero or more directories to the front of an arbitrary path.  */
 
 void
-mod_path (char *dirname, char **which_path)
+mod_path (const char *dirname, char **which_path)
 {
   add_path (dirname, which_path, 1);
 }
@@ -437,39 +458,33 @@ mod_path (char *dirname, char **which_path)
    as space or tab.  */
 
 void
-add_path (char *dirname, char **which_path, int parse_separators)
+add_path (const char *dirname, char **which_path, int parse_separators)
 {
   char *old = *which_path;
   int prefix = 0;
-  VEC (char_ptr) *dir_vec = NULL;
-  struct cleanup *back_to;
-  int ix;
-  char *name;
+  std::vector<gdb::unique_xmalloc_ptr<char>> dir_vec;
 
   if (dirname == 0)
     return;
 
   if (parse_separators)
     {
-      char **argv, **argvp;
-
       /* This will properly parse the space and tab separators
         and any quotes that may exist.  */
-      argv = gdb_buildargv (dirname);
+      gdb_argv argv (dirname);
 
-      for (argvp = argv; *argvp; argvp++)
-       dirnames_to_char_ptr_vec_append (&dir_vec, *argvp);
-
-      freeargv (argv);
+      for (char *arg : argv)
+       dirnames_to_char_ptr_vec_append (&dir_vec, arg);
     }
   else
-    VEC_safe_push (char_ptr, dir_vec, xstrdup (dirname));
-  back_to = make_cleanup_free_char_ptr_vec (dir_vec);
+    dir_vec.emplace_back (xstrdup (dirname));
 
-  for (ix = 0; VEC_iterate (char_ptr, dir_vec, ix, name); ++ix)
+  for (const gdb::unique_xmalloc_ptr<char> &name_up : dir_vec)
     {
+      char *name = name_up.get ();
       char *p;
       struct stat st;
+      gdb::unique_xmalloc_ptr<char> new_name_holder;
 
       /* Spaces and tabs will have been removed by buildargv().
          NAME is the start of the directory.
@@ -515,16 +530,17 @@ add_path (char *dirname, char **which_path, int parse_separators)
        }
 
       if (name[0] == '~')
-       name = tilde_expand (name);
+       new_name_holder.reset (tilde_expand (name));
 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
       else if (IS_ABSOLUTE_PATH (name) && p == name + 2) /* "d:" => "d:." */
-       name = concat (name, ".", (char *)NULL);
+       new_name_holder.reset (concat (name, ".", (char *) NULL));
 #endif
       else if (!IS_ABSOLUTE_PATH (name) && name[0] != '$')
-       name = concat (current_directory, SLASH_STRING, name, (char *)NULL);
+       new_name_holder.reset (concat (current_directory, SLASH_STRING, name,
+                                      (char *) NULL));
       else
-       name = savestring (name, p - name);
-      make_cleanup (xfree, name);
+       new_name_holder.reset (savestring (name, p - name));
+      name = new_name_holder.get ();
 
       /* Unless it's a variable, check existence.  */
       if (name[0] != '$')
@@ -555,17 +571,33 @@ add_path (char *dirname, char **which_path, int parse_separators)
        char tinybuf[2];
 
        p = *which_path;
-       /* FIXME: we should use realpath() or its work-alike
-          before comparing.  Then all the code above which
-          removes excess slashes and dots could simply go away.  */
-       if (!filename_cmp (p, name))
+       while (1)
          {
-           /* Found it in the search path, remove old copy.  */
-           if (p > *which_path)
-             p--;              /* Back over leading separator.  */
-           if (prefix > p - *which_path)
-             goto skip_dup;    /* Same dir twice in one cmd.  */
-           memmove (p, &p[len + 1], strlen (&p[len + 1]) + 1); /* Copy from next \0 or  : */
+           /* FIXME: we should use realpath() or its work-alike
+              before comparing.  Then all the code above which
+              removes excess slashes and dots could simply go away.  */
+           if (!filename_ncmp (p, name, len)
+               && (p[len] == '\0' || p[len] == DIRNAME_SEPARATOR))
+             {
+               /* Found it in the search path, remove old copy.  */
+               if (p > *which_path)
+                 {
+                   /* Back over leading separator.  */
+                   p--;
+                 }
+               if (prefix > p - *which_path)
+                 {
+                   /* Same dir twice in one cmd.  */
+                   goto skip_dup;
+                 }
+               /* Copy from next '\0' or ':'.  */
+               memmove (p, &p[len + 1], strlen (&p[len + 1]) + 1);
+             }
+           p = strchr (p, DIRNAME_SEPARATOR);
+           if (p != 0)
+             ++p;
+           else
+             break;
          }
 
        tinybuf[0] = DIRNAME_SEPARATOR;
@@ -598,24 +630,25 @@ add_path (char *dirname, char **which_path, int parse_separators)
     skip_dup:
       ;
     }
-
-  do_cleanups (back_to);
 }
 
 
 static void
-source_info (char *ignore, int from_tty)
+info_source_command (const char *ignore, int from_tty)
 {
   struct symtab *s = current_source_symtab;
+  struct compunit_symtab *cust;
 
   if (!s)
     {
       printf_filtered (_("No current source file.\n"));
       return;
     }
+
+  cust = SYMTAB_COMPUNIT (s);
   printf_filtered (_("Current source file is %s\n"), s->filename);
-  if (s->dirname)
-    printf_filtered (_("Compilation directory is %s\n"), s->dirname);
+  if (SYMTAB_DIRNAME (s) != NULL)
+    printf_filtered (_("Compilation directory is %s\n"), SYMTAB_DIRNAME (s));
   if (s->fullname)
     printf_filtered (_("Located in %s\n"), s->fullname);
   if (s->nlines)
@@ -623,30 +656,17 @@ source_info (char *ignore, int from_tty)
                     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 (_("Producer is %s.\n"),
+                  COMPUNIT_PRODUCER (cust) != NULL
+                  ? COMPUNIT_PRODUCER (cust) : _("unknown"));
+  printf_filtered (_("Compiled with %s debugging format.\n"),
+                  COMPUNIT_DEBUGFORMAT (cust));
   printf_filtered (_("%s preprocessor macro info.\n"),
-                   s->macro_table ? "Includes" : "Does not include");
+                  COMPUNIT_MACRO_TABLE (cust) != NULL
+                  ? "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 in the calls to open.  You cannot use this function to
    create files (O_CREAT).
@@ -655,9 +675,10 @@ is_regular_file (const char *name)
 
    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).
+   that, unless OPF_SEARCH_IN_PATH is also specified, 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
@@ -669,22 +690,27 @@ is_regular_file (const char *name)
    and the file, sigh!  Emacs gets confuzzed by this when we print the
    source file name!!! 
 
+   If OPTS has OPF_RETURN_REALPATH set return FILENAME_OPENED resolved by
+   gdb_realpath.  Even without OPF_RETURN_REALPATH this function still returns
+   filename starting with "/".  If FILENAME_OPENED is NULL this option has no
+   effect.
+
    If a file is found, return the descriptor.
    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.  */
 int
-openp (const char *path, int opts, const char *string,
-       int mode, char **filename_opened)
+openp (const char *path, openp_flags opts, const char *string,
+       int mode, gdb::unique_xmalloc_ptr<char> *filename_opened)
 {
   int fd;
   char *filename;
   int alloclen;
-  VEC (char_ptr) *dir_vec;
-  struct cleanup *back_to;
-  int ix;
-  char *dir;
+  /* The errno set for the last name we tried to open (and
+     failed).  */
+  int last_errno = 0;
+  std::vector<gdb::unique_xmalloc_ptr<char>> dir_vec;
 
   /* The open syscall MODE parameter is not specified.  */
   gdb_assert ((mode & O_CREAT) == 0);
@@ -710,20 +736,22 @@ openp (const char *path, int opts, const char *string,
 
   if ((opts & OPF_TRY_CWD_FIRST) || IS_ABSOLUTE_PATH (string))
     {
-      int i;
+      int i, reg_file_errno;
 
-      if (is_regular_file (string))
+      if (is_regular_file (string, &reg_file_errno))
        {
-         filename = alloca (strlen (string) + 1);
+         filename = (char *) alloca (strlen (string) + 1);
          strcpy (filename, string);
-         fd = open (filename, mode);
+         fd = gdb_open_cloexec (filename, mode, 0);
          if (fd >= 0)
            goto done;
+         last_errno = errno;
        }
       else
        {
          filename = NULL;
          fd = -1;
+         last_errno = reg_file_errno;
        }
 
       if (!(opts & OPF_SEARCH_IN_PATH))
@@ -745,15 +773,17 @@ openp (const char *path, int opts, const char *string,
     string += 2;
 
   alloclen = strlen (path) + strlen (string) + 2;
-  filename = alloca (alloclen);
+  filename = (char *) alloca (alloclen);
   fd = -1;
+  last_errno = ENOENT;
 
   dir_vec = dirnames_to_char_ptr_vec (path);
-  back_to = make_cleanup_free_char_ptr_vec (dir_vec);
 
-  for (ix = 0; VEC_iterate (char_ptr, dir_vec, ix, dir); ++ix)
+  for (const gdb::unique_xmalloc_ptr<char> &dir_up : dir_vec)
     {
+      char *dir = dir_up.get ();
       size_t len = strlen (dir);
+      int reg_file_errno;
 
       if (strcmp (dir, "$cwd") == 0)
        {
@@ -766,7 +796,7 @@ openp (const char *path, int opts, const char *string,
          if (newlen > alloclen)
            {
              alloclen = newlen;
-             filename = alloca (alloclen);
+             filename = (char *) alloca (alloclen);
            }
          strcpy (filename, current_directory);
        }
@@ -774,20 +804,18 @@ openp (const char *path, int opts, const char *string,
        {
         /* See whether we need to expand the tilde.  */
          int newlen;
-         char *tilde_expanded;
 
-         tilde_expanded  = tilde_expand (dir);
+         gdb::unique_xmalloc_ptr<char> tilde_expanded (tilde_expand (dir));
 
          /* First, realloc the filename buffer if too short.  */
-         len = strlen (tilde_expanded);
+         len = strlen (tilde_expanded.get ());
          newlen = len + strlen (string) + 2;
          if (newlen > alloclen)
            {
              alloclen = newlen;
-             filename = alloca (alloclen);
+             filename = (char *) alloca (alloclen);
            }
-         strcpy (filename, tilde_expanded);
-         xfree (tilde_expanded);
+         strcpy (filename, tilde_expanded.get ());
        }
       else
        {
@@ -812,42 +840,30 @@ openp (const char *path, int opts, const char *string,
       strcat (filename + len, SLASH_STRING);
       strcat (filename, string);
 
-      if (is_regular_file (filename))
+      if (is_regular_file (filename, &reg_file_errno))
        {
-         fd = open (filename, mode);
+         fd = gdb_open_cloexec (filename, mode, 0);
          if (fd >= 0)
            break;
+         last_errno = errno;
        }
+      else
+       last_errno = reg_file_errno;
     }
 
-  do_cleanups (back_to);
-
 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 a file was opened, canonicalize its filename.  */
       if (fd < 0)
-       *filename_opened = NULL;
-      else if (IS_ABSOLUTE_PATH (filename))
-       *filename_opened = xfullpath (filename);
+       filename_opened->reset (NULL);
+      else if ((opts & OPF_RETURN_REALPATH) != 0)
+       *filename_opened = gdb_realpath (filename);
       else
-       {
-         /* Beware the // my son, the Emacs barfs, the botch that catch...  */
-
-         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);
-       }
+       *filename_opened = gdb_abspath (filename);
     }
 
+  errno = last_errno;
   return fd;
 }
 
@@ -864,15 +880,17 @@ done:
 
    Else, this functions returns 0, and FULL_PATHNAME is set to NULL.  */
 int
-source_full_path_of (const char *filename, char **full_pathname)
+source_full_path_of (const char *filename,
+                    gdb::unique_xmalloc_ptr<char> *full_pathname)
 {
   int fd;
 
-  fd = openp (source_path, OPF_TRY_CWD_FIRST | OPF_SEARCH_IN_PATH, filename,
-             O_RDONLY, full_pathname);
+  fd = openp (source_path,
+             OPF_TRY_CWD_FIRST | OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH,
+             filename, O_RDONLY, full_pathname);
   if (fd < 0)
     {
-      *full_pathname = NULL;
+      full_pathname->reset (NULL);
       return 0;
     }
 
@@ -889,27 +907,20 @@ substitute_path_rule_matches (const struct substitute_path_rule *rule,
 {
   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';
+     so the path should start with rule->from.  */
 
-  if (FILENAME_CMP (path_start, rule->from) != 0)
+  if (filename_ncmp (path, rule->from, from_len) != 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;
 
@@ -931,13 +942,12 @@ get_substitute_path_rule (const char *path)
 }
 
 /* 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.
-   
+   to PATH, then apply it and return the new path.
+
    Return NULL if no substitution rule was specified by the user,
    or if no rule applied to the given PATH.  */
-   
-static char *
+
+gdb::unique_xmalloc_ptr<char>
 rewrite_source_path (const char *path)
 {
   const struct substitute_path_rule *rule = get_substitute_path_rule (path);
@@ -956,13 +966,13 @@ rewrite_source_path (const char *path)
   strcpy (new_path, rule->to);
   strcat (new_path, path + from_len);
 
-  return new_path;
+  return gdb::unique_xmalloc_ptr<char> (new_path);
 }
 
 int
 find_and_open_source (const char *filename,
                      const char *dirname,
-                     char **fullname)
+                     gdb::unique_xmalloc_ptr<char> *fullname)
 {
   char *path = source_path;
   const char *p;
@@ -975,44 +985,34 @@ find_and_open_source (const char *filename,
       /* 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);
+      gdb::unique_xmalloc_ptr<char> rewritten_fullname
+       = rewrite_source_path (fullname->get ());
 
       if (rewritten_fullname != NULL)
-        {
-          xfree (*fullname);
-          *fullname = rewritten_fullname;
-        }
+       *fullname = std::move (rewritten_fullname);
 
-      result = open (*fullname, OPEN_MODE);
+      result = gdb_open_cloexec (fullname->get (), OPEN_MODE, 0);
       if (result >= 0)
        {
-         /* Call xfullpath here to be consistent with openp
-            which we use below.  */
-         char *lpath = xfullpath (*fullname);
-
-         xfree (*fullname);
-         *fullname = lpath;
+         *fullname = gdb_realpath (fullname->get ());
          return result;
        }
 
       /* Didn't work -- free old one, try again.  */
-      xfree (*fullname);
-      *fullname = NULL;
+      fullname->reset (NULL);
     }
 
+  gdb::unique_xmalloc_ptr<char> rewritten_dirname;
   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);
+      rewritten_dirname = rewrite_source_path (dirname);
 
       if (rewritten_dirname != NULL)
-        {
-          make_cleanup (xfree, rewritten_dirname);
-          dirname = rewritten_dirname;
-        }
-      
+       dirname = rewritten_dirname.get ();
+
       /* Replace a path entry of $cdir with the compilation directory
         name.  */
 #define        cdir_len        5
@@ -1034,26 +1034,26 @@ find_and_open_source (const char *filename,
        }
     }
 
+  gdb::unique_xmalloc_ptr<char> rewritten_filename;
   if (IS_ABSOLUTE_PATH (filename))
     {
       /* If filename is absolute path, try the source path
         substitution on it.  */
-      char *rewritten_filename = rewrite_source_path (filename);
+      rewritten_filename = rewrite_source_path (filename);
 
       if (rewritten_filename != NULL)
-        {
-          make_cleanup (xfree, rewritten_filename);
-          filename = rewritten_filename;
-        }
+       filename = rewritten_filename.get ();
     }
 
-  result = openp (path, OPF_SEARCH_IN_PATH, filename, OPEN_MODE, fullname);
+  result = openp (path, OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH, filename,
+                 OPEN_MODE, fullname);
   if (result < 0)
     {
       /* Didn't work.  Try using just the basename.  */
       p = lbasename (filename);
       if (p != filename)
-       result = openp (path, OPF_SEARCH_IN_PATH, p, OPEN_MODE, fullname);
+       result = openp (path, OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH, p,
+                       OPEN_MODE, fullname);
     }
 
   return result;
@@ -1070,7 +1070,10 @@ open_source_file (struct symtab *s)
   if (!s)
     return -1;
 
-  return find_and_open_source (s->filename, s->dirname, &s->fullname);
+  gdb::unique_xmalloc_ptr<char> fullname;
+  int fd = find_and_open_source (s->filename, SYMTAB_DIRNAME (s), &fullname);
+  s->fullname = fullname.release ();
+  return fd;
 }
 
 /* Finds the fullname that a symtab represents.
@@ -1090,33 +1093,46 @@ symtab_to_fullname (struct symtab *s)
      to handle cases like the file being moved.  */
   if (s->fullname == NULL)
     {
-      int fd = find_and_open_source (s->filename, s->dirname, &s->fullname);
+      int fd = open_source_file (s);
 
       if (fd >= 0)
        close (fd);
       else
        {
-         char *fullname;
-         struct cleanup *back_to;
+         gdb::unique_xmalloc_ptr<char> fullname;
 
          /* rewrite_source_path would be applied by find_and_open_source, we
             should report the pathname where GDB tried to find the file.  */
 
-         if (s->dirname == NULL || IS_ABSOLUTE_PATH (s->filename))
-           fullname = xstrdup (s->filename);
+         if (SYMTAB_DIRNAME (s) == NULL || IS_ABSOLUTE_PATH (s->filename))
+           fullname.reset (xstrdup (s->filename));
          else
-           fullname = concat (s->dirname, SLASH_STRING, s->filename, NULL);
+           fullname.reset (concat (SYMTAB_DIRNAME (s), SLASH_STRING,
+                                   s->filename, (char *) NULL));
 
-         back_to = make_cleanup (xfree, fullname);
-         s->fullname = rewrite_source_path (fullname);
+         s->fullname = rewrite_source_path (fullname.get ()).release ();
          if (s->fullname == NULL)
-           s->fullname = xstrdup (fullname);
-         do_cleanups (back_to);
+           s->fullname = fullname.release ();
        }
     } 
 
   return s->fullname;
 }
+
+/* See commentary in source.h.  */
+
+const char *
+symtab_to_filename_for_display (struct symtab *symtab)
+{
+  if (filename_display_string == filename_display_basename)
+    return lbasename (symtab->filename);
+  else if (filename_display_string == filename_display_absolute)
+    return symtab_to_fullname (symtab);
+  else if (filename_display_string == filename_display_relative)
+    return symtab->filename;
+  else
+    internal_error (__FILE__, __LINE__, _("invalid filename_display_string"));
+}
 \f
 /* Create and initialize the table S->line_charpos that records
    the positions of the lines in the source file, which is assumed
@@ -1127,7 +1143,7 @@ void
 find_source_lines (struct symtab *s, int desc)
 {
   struct stat st;
-  char *data, *p, *end;
+  char *p, *end;
   int nlines = 0;
   int lines_allocated = 1000;
   int *line_charpos;
@@ -1135,12 +1151,12 @@ find_source_lines (struct symtab *s, int desc)
   int size;
 
   gdb_assert (s);
-  line_charpos = (int *) xmalloc (lines_allocated * sizeof (int));
+  line_charpos = XNEWVEC (int, lines_allocated);
   if (fstat (desc, &st) < 0)
-    perror_with_name (s->filename);
+    perror_with_name (symtab_to_filename_for_display (s));
 
-  if (s->objfile && s->objfile->obfd)
-    mtime = s->objfile->mtime;
+  if (SYMTAB_OBJFILE (s) != NULL && SYMTAB_OBJFILE (s)->obfd != NULL)
+    mtime = SYMTAB_OBJFILE (s)->mtime;
   else if (exec_bfd)
     mtime = exec_bfd_mtime;
 
@@ -1148,23 +1164,20 @@ find_source_lines (struct symtab *s, int desc)
     warning (_("Source file is more recent than executable."));
 
   {
-    struct cleanup *old_cleanups;
-
     /* st_size might be a large type, but we only support source files whose 
        size fits in an int.  */
     size = (int) st.st_size;
 
-    /* Use malloc, not alloca, because this may be pretty large, and we may
-       run into various kinds of limits on stack size.  */
-    data = (char *) xmalloc (size);
-    old_cleanups = make_cleanup (xfree, data);
+    /* Use the heap, not the stack, because this may be pretty large,
+       and we may run into various kinds of limits on stack size.  */
+    gdb::def_vector<char> data (size);
 
     /* Reassign `size' to result of read for systems where \r\n -> \n.  */
-    size = myread (desc, data, size);
+    size = myread (desc, data.data (), size);
     if (size < 0)
-      perror_with_name (s->filename);
-    end = data + size;
-    p = data;
+      perror_with_name (symtab_to_filename_for_display (s));
+    end = data.data () + size;
+    p = &data[0];
     line_charpos[0] = 0;
     nlines = 1;
     while (p != end)
@@ -1180,10 +1193,9 @@ find_source_lines (struct symtab *s, int desc)
                  (int *) xrealloc ((char *) line_charpos,
                                    sizeof (int) * lines_allocated);
              }
-           line_charpos[nlines++] = p - data;
+           line_charpos[nlines++] = p - data.data ();
          }
       }
-    do_cleanups (old_cleanups);
   }
 
   s->nlines = nlines;
@@ -1202,24 +1214,21 @@ find_source_lines (struct symtab *s, int desc)
 static int
 get_filename_and_charpos (struct symtab *s, char **fullname)
 {
-  int desc, linenums_changed = 0;
-  struct cleanup *cleanups;
+  int linenums_changed = 0;
 
-  desc = open_source_file (s);
-  if (desc < 0)
+  scoped_fd desc (open_source_file (s));
+  if (desc.get () < 0)
     {
       if (fullname)
        *fullname = NULL;
       return 0;
     }
-  cleanups = make_cleanup_close (desc);
   if (fullname)
     *fullname = s->fullname;
   if (s->line_charpos == 0)
     linenums_changed = 1;
   if (linenums_changed)
-    find_source_lines (s, desc);
-  do_cleanups (cleanups);
+    find_source_lines (s, desc.get ());
   return linenums_changed;
 }
 
@@ -1244,12 +1253,11 @@ identify_source_line (struct symtab *s, int line, int mid_statement,
     /* Don't index off the end of the line_charpos array.  */
     return 0;
   annotate_source (s->fullname, line, s->line_charpos[line - 1],
-                  mid_statement, get_objfile_arch (s->objfile), pc);
+                  mid_statement, get_objfile_arch (SYMTAB_OBJFILE (s)), pc);
 
   current_source_line = line;
-  first_line_listed = line;
-  last_line_listed = line;
   current_source_symtab = s;
+  clear_lines_listed_range ();
   return 1;
 }
 \f
@@ -1259,14 +1267,12 @@ identify_source_line (struct symtab *s, int line, int mid_statement,
 
 static void
 print_source_lines_base (struct symtab *s, int line, int stopline,
-                        enum print_source_lines_flags flags)
+                        print_source_lines_flags flags)
 {
   int c;
   int desc;
   int noprint = 0;
-  FILE *stream;
   int nlines = stopline - line;
-  struct cleanup *cleanup;
   struct ui_out *uiout = current_uiout;
 
   /* Regardless of whether we can open the file, set current_source_symtab.  */
@@ -1276,7 +1282,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
 
   /* If printing of source lines is disabled, just print file and line
      number.  */
-  if (ui_out_test_flags (uiout, ui_source_list))
+  if (uiout->test_flags (ui_source_list))
     {
       /* Only prints "No such file or directory" once.  */
       if ((s != last_source_visited) || (!last_source_error))
@@ -1293,7 +1299,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
   else
     {
       desc = last_source_error;
-         flags |= PRINT_SOURCE_LINES_NOERROR;
+      flags |= PRINT_SOURCE_LINES_NOERROR;
       noprint = 1;
     }
 
@@ -1303,24 +1309,39 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
 
       if (!(flags & PRINT_SOURCE_LINES_NOERROR))
        {
-         int len = strlen (s->filename) + 100;
-         char *name = alloca (len);
+         const char *filename = symtab_to_filename_for_display (s);
+         int len = strlen (filename) + 100;
+         char *name = (char *) alloca (len);
 
-         xsnprintf (name, len, "%d\t%s", line, s->filename);
+         xsnprintf (name, len, "%d\t%s", line, filename);
          print_sys_errmsg (name, errno);
        }
       else
        {
-         ui_out_field_int (uiout, "line", line);
-         ui_out_text (uiout, "\tin ");
-         ui_out_field_string (uiout, "file", s->filename);
-         if (ui_out_is_mi_like_p (uiout))
-           {
-             const char *fullname = symtab_to_fullname (s);
-
-             ui_out_field_string (uiout, "fullname", fullname);
-           }
-         ui_out_text (uiout, "\n");
+         uiout->field_int ("line", line);
+         uiout->text ("\tin ");
+
+         /* CLI expects only the "file" field.  TUI expects only the
+            "fullname" field (and TUI does break if "file" is printed).
+            MI expects both fields.  ui_source_list is set only for CLI,
+            not for TUI.  */
+         if (uiout->is_mi_like_p () || uiout->test_flags (ui_source_list))
+           uiout->field_string ("file", symtab_to_filename_for_display (s));
+         if (uiout->is_mi_like_p () || !uiout->test_flags (ui_source_list))
+           {
+             const char *s_fullname = symtab_to_fullname (s);
+             char *local_fullname;
+
+             /* ui_out_field_string may free S_FULLNAME by calling
+                open_source_file for it again.  See e.g.,
+                tui_field_string->tui_show_source.  */
+             local_fullname = (char *) alloca (strlen (s_fullname) + 1);
+             strcpy (local_fullname, s_fullname);
+
+             uiout->field_string ("fullname", local_fullname);
+           }
+
+         uiout->text ("\n");
        }
 
       return;
@@ -1335,63 +1356,60 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
     {
       close (desc);
       error (_("Line number %d out of range; %s has %d lines."),
-            line, s->filename, s->nlines);
+            line, symtab_to_filename_for_display (s), s->nlines);
     }
 
   if (lseek (desc, s->line_charpos[line - 1], 0) < 0)
     {
       close (desc);
-      perror_with_name (s->filename);
+      perror_with_name (symtab_to_filename_for_display (s));
     }
 
-  stream = fdopen (desc, FDOPEN_MODE);
-  clearerr (stream);
-  cleanup = make_cleanup_fclose (stream);
+  gdb_file_up stream (fdopen (desc, FDOPEN_MODE));
+  clearerr (stream.get ());
 
   while (nlines-- > 0)
     {
       char buf[20];
 
-      c = fgetc (stream);
+      c = fgetc (stream.get ());
       if (c == EOF)
        break;
       last_line_listed = current_source_line;
       if (flags & PRINT_SOURCE_LINES_FILENAME)
         {
-          ui_out_text (uiout, s->filename);
-          ui_out_text (uiout, ":");
+          uiout->text (symtab_to_filename_for_display (s));
+          uiout->text (":");
         }
       xsnprintf (buf, sizeof (buf), "%d\t", current_source_line++);
-      ui_out_text (uiout, buf);
+      uiout->text (buf);
       do
        {
          if (c < 040 && c != '\t' && c != '\n' && c != '\r')
            {
              xsnprintf (buf, sizeof (buf), "^%c", c + 0100);
-             ui_out_text (uiout, buf);
+             uiout->text (buf);
            }
          else if (c == 0177)
-           ui_out_text (uiout, "^?");
+           uiout->text ("^?");
          else if (c == '\r')
            {
              /* Skip a \r character, but only before a \n.  */
-             int c1 = fgetc (stream);
+             int c1 = fgetc (stream.get ());
 
              if (c1 != '\n')
                printf_filtered ("^%c", c + 0100);
              if (c1 != EOF)
-               ungetc (c1, stream);
+               ungetc (c1, stream.get ());
            }
          else
            {
              xsnprintf (buf, sizeof (buf), "%c", c);
-             ui_out_text (uiout, buf);
+             uiout->text (buf);
            }
        }
-      while (c != '\n' && (c = fgetc (stream)) >= 0);
+      while (c != '\n' && (c = fgetc (stream.get ())) >= 0);
     }
-
-  do_cleanups (cleanup);
 }
 \f
 /* Show source lines from the file of symtab S, starting with line
@@ -1401,7 +1419,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
 
 void
 print_source_lines (struct symtab *s, int line, int stopline,
-                   enum print_source_lines_flags flags)
+                   print_source_lines_flags flags)
 {
   print_source_lines_base (s, line, stopline, flags);
 }
@@ -1409,40 +1427,38 @@ print_source_lines (struct symtab *s, int line, int stopline,
 /* Print info on range of pc's in a specified line.  */
 
 static void
-line_info (char *arg, int from_tty)
+info_line_command (const char *arg, int from_tty)
 {
-  struct symtabs_and_lines sals;
-  struct symtab_and_line sal;
   CORE_ADDR start_pc, end_pc;
-  int i;
-  struct cleanup *cleanups;
 
-  init_sal (&sal);             /* initialize to zeroes */
+  std::vector<symtab_and_line> decoded_sals;
+  symtab_and_line curr_sal;
+  gdb::array_view<symtab_and_line> sals;
 
   if (arg == 0)
     {
-      sal.symtab = current_source_symtab;
-      sal.pspace = current_program_space;
-      sal.line = last_line_listed;
-      sals.nelts = 1;
-      sals.sals = (struct symtab_and_line *)
-       xmalloc (sizeof (struct symtab_and_line));
-      sals.sals[0] = sal;
+      curr_sal.symtab = current_source_symtab;
+      curr_sal.pspace = current_program_space;
+      if (last_line_listed != 0)
+       curr_sal.line = last_line_listed;
+      else
+       curr_sal.line = current_source_line;
+
+      sals = curr_sal;
     }
   else
     {
-      sals = decode_line_with_last_displayed (arg, DECODE_LINE_LIST_MODE);
+      decoded_sals = decode_line_with_last_displayed (arg,
+                                                     DECODE_LINE_LIST_MODE);
+      sals = decoded_sals;
 
       dont_repeat ();
     }
 
-  cleanups = make_cleanup (xfree, sals.sals);
-
   /* C++  More than one line may have been specified, as when the user
      specifies an overloaded function name.  Print info on them all.  */
-  for (i = 0; i < sals.nelts; i++)
+  for (const auto &sal : sals)
     {
-      sal = sals.sals[i];
       if (sal.pspace != current_program_space)
        continue;
 
@@ -1467,12 +1483,14 @@ line_info (char *arg, int from_tty)
       else if (sal.line > 0
               && find_line_pc_range (sal, &start_pc, &end_pc))
        {
-         struct gdbarch *gdbarch = get_objfile_arch (sal.symtab->objfile);
+         struct gdbarch *gdbarch
+           = get_objfile_arch (SYMTAB_OBJFILE (sal.symtab));
 
          if (start_pc == end_pc)
            {
              printf_filtered ("Line %d of \"%s\"",
-                              sal.line, sal.symtab->filename);
+                              sal.line,
+                              symtab_to_filename_for_display (sal.symtab));
              wrap_here ("  ");
              printf_filtered (" is at address ");
              print_address (gdbarch, start_pc, gdb_stdout);
@@ -1482,7 +1500,8 @@ line_info (char *arg, int from_tty)
          else
            {
              printf_filtered ("Line %d of \"%s\"",
-                              sal.line, sal.symtab->filename);
+                              sal.line,
+                              symtab_to_filename_for_display (sal.symtab));
              wrap_here ("  ");
              printf_filtered (" starts at address ");
              print_address (gdbarch, start_pc, gdb_stdout);
@@ -1500,7 +1519,7 @@ line_info (char *arg, int from_tty)
 
          /* If this is the only line, show the source code.  If it could
             not find the file, don't do anything special.  */
-         if (annotation_level && sals.nelts == 1)
+         if (annotation_level && sals.size () == 1)
            identify_source_line (sal.symtab, sal.line, 0, start_pc);
        }
       else
@@ -1508,22 +1527,18 @@ line_info (char *arg, int from_tty)
           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"),
-                        sal.line, sal.symtab->filename);
+                        sal.line, symtab_to_filename_for_display (sal.symtab));
     }
-  do_cleanups (cleanups);
 }
 \f
 /* Commands to search the source file for a regexp.  */
 
 static void
-forward_search_command (char *regex, int from_tty)
+forward_search_command (const char *regex, int from_tty)
 {
   int c;
-  int desc;
-  FILE *stream;
   int line;
   char *msg;
-  struct cleanup *cleanups;
 
   line = last_line_listed + 1;
 
@@ -1534,24 +1549,22 @@ forward_search_command (char *regex, int from_tty)
   if (current_source_symtab == 0)
     select_source_symtab (0);
 
-  desc = open_source_file (current_source_symtab);
-  if (desc < 0)
-    perror_with_name (current_source_symtab->filename);
-  cleanups = make_cleanup_close (desc);
+  scoped_fd desc (open_source_file (current_source_symtab));
+  if (desc.get () < 0)
+    perror_with_name (symtab_to_filename_for_display (current_source_symtab));
 
   if (current_source_symtab->line_charpos == 0)
-    find_source_lines (current_source_symtab, desc);
+    find_source_lines (current_source_symtab, desc.get ());
 
   if (line < 1 || line > current_source_symtab->nlines)
     error (_("Expression not found"));
 
-  if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
-    perror_with_name (current_source_symtab->filename);
+  if (lseek (desc.get (), current_source_symtab->line_charpos[line - 1], 0)
+      < 0)
+    perror_with_name (symtab_to_filename_for_display (current_source_symtab));
 
-  discard_cleanups (cleanups);
-  stream = fdopen (desc, FDOPEN_MODE);
-  clearerr (stream);
-  cleanups = make_cleanup_fclose (stream);
+  gdb_file_up stream (fdopen (desc.release (), FDOPEN_MODE));
+  clearerr (stream.get ());
   while (1)
     {
       static char *buf = NULL;
@@ -1559,10 +1572,10 @@ forward_search_command (char *regex, int from_tty)
       int cursize, newsize;
 
       cursize = 256;
-      buf = xmalloc (cursize);
+      buf = (char *) xmalloc (cursize);
       p = buf;
 
-      c = getc (stream);
+      c = fgetc (stream.get ());
       if (c == EOF)
        break;
       do
@@ -1571,12 +1584,12 @@ forward_search_command (char *regex, int from_tty)
          if (p - buf == cursize)
            {
              newsize = cursize + cursize / 2;
-             buf = xrealloc (buf, newsize);
+             buf = (char *) xrealloc (buf, newsize);
              p = buf + cursize;
              cursize = newsize;
            }
        }
-      while (c != '\n' && (c = getc (stream)) >= 0);
+      while (c != '\n' && (c = fgetc (stream.get ())) >= 0);
 
       /* Remove the \r, if any, at the end of the line, otherwise
          regular expressions that end with $ or \n won't work.  */
@@ -1591,28 +1604,23 @@ forward_search_command (char *regex, int from_tty)
       if (re_exec (buf) > 0)
        {
          /* Match!  */
-         do_cleanups (cleanups);
          print_source_lines (current_source_symtab, line, line + 1, 0);
          set_internalvar_integer (lookup_internalvar ("_"), line);
-         current_source_line = max (line - lines_to_list / 2, 1);
+         current_source_line = std::max (line - lines_to_list / 2, 1);
          return;
        }
       line++;
     }
 
   printf_filtered (_("Expression not found\n"));
-  do_cleanups (cleanups);
 }
 
 static void
-reverse_search_command (char *regex, int from_tty)
+reverse_search_command (const char *regex, int from_tty)
 {
   int c;
-  int desc;
-  FILE *stream;
   int line;
   char *msg;
-  struct cleanup *cleanups;
 
   line = last_line_listed - 1;
 
@@ -1623,38 +1631,36 @@ reverse_search_command (char *regex, int from_tty)
   if (current_source_symtab == 0)
     select_source_symtab (0);
 
-  desc = open_source_file (current_source_symtab);
-  if (desc < 0)
-    perror_with_name (current_source_symtab->filename);
-  cleanups = make_cleanup_close (desc);
+  scoped_fd desc (open_source_file (current_source_symtab));
+  if (desc.get () < 0)
+    perror_with_name (symtab_to_filename_for_display (current_source_symtab));
 
   if (current_source_symtab->line_charpos == 0)
-    find_source_lines (current_source_symtab, desc);
+    find_source_lines (current_source_symtab, desc.get ());
 
   if (line < 1 || line > current_source_symtab->nlines)
     error (_("Expression not found"));
 
-  if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
-    perror_with_name (current_source_symtab->filename);
+  if (lseek (desc.get (), current_source_symtab->line_charpos[line - 1], 0)
+      < 0)
+    perror_with_name (symtab_to_filename_for_display (current_source_symtab));
 
-  discard_cleanups (cleanups);
-  stream = fdopen (desc, FDOPEN_MODE);
-  clearerr (stream);
-  cleanups = make_cleanup_fclose (stream);
+  gdb_file_up stream (fdopen (desc.release (), FDOPEN_MODE));
+  clearerr (stream.get ());
   while (line > 1)
     {
 /* FIXME!!!  We walk right off the end of buf if we get a long line!!!  */
       char buf[4096];          /* Should be reasonable???  */
       char *p = buf;
 
-      c = getc (stream);
+      c = fgetc (stream.get ());
       if (c == EOF)
        break;
       do
        {
          *p++ = c;
        }
-      while (c != '\n' && (c = getc (stream)) >= 0);
+      while (c != '\n' && (c = fgetc (stream.get ())) >= 0);
 
       /* Remove the \r, if any, at the end of the line, otherwise
          regular expressions that end with $ or \n won't work.  */
@@ -1669,22 +1675,23 @@ reverse_search_command (char *regex, int from_tty)
       if (re_exec (buf) > 0)
        {
          /* Match!  */
-         do_cleanups (cleanups);
          print_source_lines (current_source_symtab, line, line + 1, 0);
          set_internalvar_integer (lookup_internalvar ("_"), line);
-         current_source_line = max (line - lines_to_list / 2, 1);
+         current_source_line = std::max (line - lines_to_list / 2, 1);
          return;
        }
       line--;
-      if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0)
+      if (fseek (stream.get (),
+                current_source_symtab->line_charpos[line - 1], 0) < 0)
        {
-         do_cleanups (cleanups);
-         perror_with_name (current_source_symtab->filename);
+         const char *filename;
+
+         filename = symtab_to_filename_for_display (current_source_symtab);
+         perror_with_name (filename);
        }
     }
 
   printf_filtered (_("Expression not found\n"));
-  do_cleanups (cleanups);
   return;
 }
 
@@ -1727,9 +1734,8 @@ void
 add_substitute_path_rule (char *from, char *to)
 {
   struct substitute_path_rule *rule;
-  struct substitute_path_rule *new_rule;
+  struct substitute_path_rule *new_rule = XNEW (struct substitute_path_rule);
 
-  new_rule = xmalloc (sizeof (struct substitute_path_rule));
   new_rule->from = xstrdup (from);
   new_rule->to = xstrdup (to);
   new_rule->next = NULL;
@@ -1781,14 +1787,12 @@ delete_substitute_path_rule (struct substitute_path_rule *rule)
 /* Implement the "show substitute-path" command.  */
 
 static void
-show_substitute_path_command (char *args, int from_tty)
+show_substitute_path_command (const char *args, int from_tty)
 {
   struct substitute_path_rule *rule = substitute_path_rules;
-  char **argv;
   char *from = NULL;
   
-  argv = gdb_buildargv (args);
-  make_cleanup_freeargv (argv);
+  gdb_argv argv (args);
 
   /* We expect zero or one argument.  */
 
@@ -1808,7 +1812,7 @@ show_substitute_path_command (char *args, int from_tty)
 
   while (rule != NULL)
     {
-      if (from == NULL || FILENAME_CMP (rule->from, from) == 0)
+      if (from == NULL || substitute_path_rule_matches (rule, from) != 0)
         printf_filtered ("  `%s' -> `%s'.\n", rule->from, rule->to);
       rule = rule->next;
     }
@@ -1817,16 +1821,15 @@ show_substitute_path_command (char *args, int from_tty)
 /* Implement the "unset substitute-path" command.  */
 
 static void
-unset_substitute_path_command (char *args, int from_tty)
+unset_substitute_path_command (const char *args, int from_tty)
 {
   struct substitute_path_rule *rule = substitute_path_rules;
-  char **argv = gdb_buildargv (args);
+  gdb_argv argv (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"));
 
@@ -1869,13 +1872,11 @@ unset_substitute_path_command (char *args, int from_tty)
 /* Add a new source path substitution rule.  */
 
 static void
-set_substitute_path_command (char *args, int from_tty)
+set_substitute_path_command (const char *args, int from_tty)
 {
-  char **argv;
   struct substitute_path_rule *rule;
   
-  argv = gdb_buildargv (args);
-  make_cleanup_freeargv (argv);
+  gdb_argv argv (args);
 
   if (argv == NULL || argv[0] == NULL || argv [1] == NULL)
     error (_("Incorrect usage, too few arguments in command"));
@@ -1949,20 +1950,10 @@ Setting the value to an empty string sets it to $cdir:$cwd, the default."),
                            show_directories_command,
                            &setlist, &showlist);
 
-  if (xdb_commands)
-    {
-      add_com_alias ("D", "directory", class_files, 0);
-      add_cmd ("ld", no_class, show_directories_1, _("\
-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."),
-              &cmdlist);
-    }
-
-  add_info ("source", source_info,
+  add_info ("source", info_source_command,
            _("Information about the current source file."));
 
-  add_info ("line", line_info, _("\
+  add_info ("line", info_line_command, _("\
 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\
@@ -1985,18 +1976,15 @@ 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_alias ("rev", "reverse-search", class_files, 1);
 
-  if (xdb_commands)
-    {
-      add_com_alias ("/", "forward-search", class_files, 0);
-      add_com_alias ("?", "reverse-search", class_files, 0);
-    }
-
-  add_setshow_zuinteger_unlimited_cmd ("listsize", class_support,
-                                      &lines_to_list, _("\
+  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);
+Show number of source lines gdb will list by default."), _("\
+Use this to choose how many source lines the \"list\" displays (unless\n\
+the \"list\" argument explicitly specifies some other number).\n\
+A value of \"unlimited\", or zero, means there's no limit."),
+                           NULL,
+                           show_lines_to_list,
+                           &setlist, &showlist);
 
   add_cmd ("substitute-path", class_files, set_substitute_path_command,
            _("\
@@ -2020,4 +2008,19 @@ 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);
+
+  add_setshow_enum_cmd ("filename-display", class_files,
+                       filename_display_kind_names,
+                       &filename_display_string, _("\
+Set how to display filenames."), _("\
+Show how to display filenames."), _("\
+filename-display can be:\n\
+  basename - display only basename of a filename\n\
+  relative - display a filename relative to the compilation directory\n\
+  absolute - display an absolute filename\n\
+By default, relative filenames are displayed."),
+                       NULL,
+                       show_filename_display_string,
+                       &setlist, &showlist);
+
 }
This page took 0.045064 seconds and 4 git commands to generate.