gold won't build with gcc-9
[binutils-gdb.git] / gdb / source.c
index 3b4920fe8a4028b0d85a5096d3f4445233fb05b3..c75351e65f4e0c48b64e55af7bd388bff8a1b25f 100644 (file)
 #include "ui-out.h"
 #include "readline/readline.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 local functions.  */
-
-static int get_filename_and_charpos (struct symtab *, char **);
-
 /* Path of directories to search for source files.
    Same format as the PATH environment variable's value.  */
 
@@ -478,13 +475,12 @@ add_path (const char *dirname, char **which_path, int parse_separators)
   else
     dir_vec.emplace_back (xstrdup (dirname));
 
-  struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
-
   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.
@@ -530,16 +526,17 @@ add_path (const 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] != '$')
@@ -629,8 +626,6 @@ add_path (const char *dirname, char **which_path, int parse_separators)
     skip_dup:
       ;
     }
-
-  do_cleanups (back_to);
 }
 
 
@@ -970,7 +965,9 @@ rewrite_source_path (const char *path)
   return gdb::unique_xmalloc_ptr<char> (new_path);
 }
 
-int
+/* See source.h.  */
+
+scoped_fd
 find_and_open_source (const char *filename,
                      const char *dirname,
                      gdb::unique_xmalloc_ptr<char> *fullname)
@@ -996,7 +993,7 @@ find_and_open_source (const char *filename,
       if (result >= 0)
        {
          *fullname = gdb_realpath (fullname->get ());
-         return result;
+         return scoped_fd (result);
        }
 
       /* Didn't work -- free old one, try again.  */
@@ -1057,7 +1054,7 @@ find_and_open_source (const char *filename,
                        OPEN_MODE, fullname);
     }
 
-  return result;
+  return scoped_fd (result);
 }
 
 /* Open a source file given a symtab S.  Returns a file descriptor or
@@ -1065,14 +1062,16 @@ find_and_open_source (const char *filename,
    
    This function is a convience function to find_and_open_source.  */
 
-int
+scoped_fd
 open_source_file (struct symtab *s)
 {
   if (!s)
-    return -1;
+    return scoped_fd (-1);
 
-  gdb::unique_xmalloc_ptr<char> fullname;
-  int fd = find_and_open_source (s->filename, SYMTAB_DIRNAME (s), &fullname);
+  gdb::unique_xmalloc_ptr<char> fullname (s->fullname);
+  s->fullname = NULL;
+  scoped_fd fd = find_and_open_source (s->filename, SYMTAB_DIRNAME (s),
+                                      &fullname);
   s->fullname = fullname.release ();
   return fd;
 }
@@ -1094,11 +1093,9 @@ symtab_to_fullname (struct symtab *s)
      to handle cases like the file being moved.  */
   if (s->fullname == NULL)
     {
-      int fd = open_source_file (s);
+      scoped_fd fd = open_source_file (s);
 
-      if (fd >= 0)
-       close (fd);
-      else
+      if (fd.get () < 0)
        {
          gdb::unique_xmalloc_ptr<char> fullname;
 
@@ -1208,32 +1205,23 @@ find_source_lines (struct symtab *s, int desc)
 \f
 
 /* Get full pathname and line number positions for a symtab.
-   Return nonzero if line numbers may have changed.
    Set *FULLNAME to actual name of the file as found by `openp',
    or to 0 if the file is not found.  */
 
-static int
+static void
 get_filename_and_charpos (struct symtab *s, char **fullname)
 {
-  int desc, linenums_changed = 0;
-  struct cleanup *cleanups;
-
-  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;
+      return;
     }
-  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);
-  return linenums_changed;
+    find_source_lines (s, desc.get ());
 }
 
 /* Print text describing the full name of the source file S
@@ -1274,7 +1262,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
                         print_source_lines_flags flags)
 {
   int c;
-  int desc;
+  scoped_fd desc;
   int noprint = 0;
   int nlines = stopline - line;
   struct ui_out *uiout = current_uiout;
@@ -1293,24 +1281,26 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
        {
          last_source_visited = s;
          desc = open_source_file (s);
+         if (desc.get () < 0)
+           {
+             last_source_error = desc.get ();
+             noprint = 1;
+           }
        }
       else
        {
-         desc = last_source_error;
          flags |= PRINT_SOURCE_LINES_NOERROR;
+         noprint = 1;
        }
     }
   else
     {
-      desc = last_source_error;
       flags |= PRINT_SOURCE_LINES_NOERROR;
       noprint = 1;
     }
 
-  if (desc < 0 || noprint)
+  if (noprint)
     {
-      last_source_error = desc;
-
       if (!(flags & PRINT_SOURCE_LINES_NOERROR))
        {
          const char *filename = symtab_to_filename_for_display (s);
@@ -1354,22 +1344,16 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
   last_source_error = 0;
 
   if (s->line_charpos == 0)
-    find_source_lines (s, desc);
+    find_source_lines (s, desc.get ());
 
   if (line < 1 || line > s->nlines)
-    {
-      close (desc);
-      error (_("Line number %d out of range; %s has %d lines."),
-            line, symtab_to_filename_for_display (s), s->nlines);
-    }
+    error (_("Line number %d out of range; %s has %d lines."),
+          line, symtab_to_filename_for_display (s), s->nlines);
 
-  if (lseek (desc, s->line_charpos[line - 1], 0) < 0)
-    {
-      close (desc);
-      perror_with_name (symtab_to_filename_for_display (s));
-    }
+  if (lseek (desc.get (), s->line_charpos[line - 1], 0) < 0)
+    perror_with_name (symtab_to_filename_for_display (s));
 
-  gdb_file_up stream (fdopen (desc, FDOPEN_MODE));
+  gdb_file_up stream = desc.to_file (FDOPEN_MODE);
   clearerr (stream.get ());
 
   while (nlines-- > 0)
@@ -1541,10 +1525,8 @@ static void
 forward_search_command (const char *regex, int from_tty)
 {
   int c;
-  int desc;
   int line;
   char *msg;
-  struct cleanup *cleanups;
 
   line = last_line_listed + 1;
 
@@ -1555,22 +1537,21 @@ forward_search_command (const char *regex, int from_tty)
   if (current_source_symtab == 0)
     select_source_symtab (0);
 
-  desc = open_source_file (current_source_symtab);
-  if (desc < 0)
+  scoped_fd desc = open_source_file (current_source_symtab);
+  if (desc.get () < 0)
     perror_with_name (symtab_to_filename_for_display (current_source_symtab));
-  cleanups = make_cleanup_close (desc);
 
   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)
+  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);
-  gdb_file_up stream (fdopen (desc, FDOPEN_MODE));
+  gdb_file_up stream = desc.to_file (FDOPEN_MODE);
   clearerr (stream.get ());
   while (1)
     {
@@ -1579,7 +1560,7 @@ forward_search_command (const char *regex, int from_tty)
       int cursize, newsize;
 
       cursize = 256;
-      buf = (char *) xmalloc (cursize);
+      buf = (char *) xrealloc (buf, cursize);
       p = buf;
 
       c = fgetc (stream.get ());
@@ -1626,10 +1607,8 @@ static void
 reverse_search_command (const char *regex, int from_tty)
 {
   int c;
-  int desc;
   int line;
   char *msg;
-  struct cleanup *cleanups;
 
   line = last_line_listed - 1;
 
@@ -1640,22 +1619,21 @@ reverse_search_command (const char *regex, int from_tty)
   if (current_source_symtab == 0)
     select_source_symtab (0);
 
-  desc = open_source_file (current_source_symtab);
-  if (desc < 0)
+  scoped_fd desc = open_source_file (current_source_symtab);
+  if (desc.get () < 0)
     perror_with_name (symtab_to_filename_for_display (current_source_symtab));
-  cleanups = make_cleanup_close (desc);
 
   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)
+  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);
-  gdb_file_up stream (fdopen (desc, FDOPEN_MODE));
+  gdb_file_up stream = desc.to_file (FDOPEN_MODE);
   clearerr (stream.get ());
   while (line > 1)
     {