gdb: Remove an update of current_source_line and current_source_symtab
[deliverable/binutils-gdb.git] / gdb / source.c
index 575e46c2123e66a58eb20f3f227b881601e421cd..dec5a2f84bab5490c19a66b11f1e8bc0d1867457 100644 (file)
@@ -1,5 +1,5 @@
 /* List lines of source files for GDB, the GNU debugger.
-   Copyright (C) 1986-2018 Free Software Foundation, Inc.
+   Copyright (C) 1986-2019 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -26,7 +26,7 @@
 #include "gdbcmd.h"
 #include "frame.h"
 #include "value.h"
-#include "filestuff.h"
+#include "common/filestuff.h"
 
 #include <sys/types.h>
 #include <fcntl.h>
@@ -45,6 +45,7 @@
 #include "common/scoped_fd.h"
 #include <algorithm>
 #include "common/pathstuff.h"
+#include "source-cache.h"
 
 #define OPEN_MODE (O_RDONLY | O_BINARY)
 #define FDOPEN_MODE FOPEN_RB
@@ -232,20 +233,11 @@ clear_current_source_symtab_and_line (void)
   current_source_line = 0;
 }
 
-/* Set the source file default for the "list" command to be S.
-
-   If S is NULL, and we don't have a default, find one.  This
-   should only be called when the user actually tries to use the
-   default, since we produce an error if we can't find a reasonable
-   default.  Also, since this can cause symbols to be read, doing it
-   before we need to would make things slower than necessary.  */
+/* See source.h.  */
 
 void
 select_source_symtab (struct symtab *s)
 {
-  struct objfile *ofp;
-  struct compunit_symtab *cu;
-
   if (s)
     {
       current_source_symtab = s;
@@ -277,29 +269,35 @@ select_source_symtab (struct symtab *s)
 
   current_source_line = 1;
 
-  ALL_FILETABS (ofp, cu, s)
+  for (objfile *ofp : current_program_space->objfiles ())
     {
-      const char *name = s->filename;
-      int len = strlen (name);
-
-      if (!(len > 2 && (strcmp (&name[len - 2], ".h") == 0
-                       || strcmp (name, "<<C++-namespaces>>") == 0)))
+      for (compunit_symtab *cu : ofp->compunits ())
        {
-         current_source_pspace = current_program_space;
-         current_source_symtab = s;
+         for (symtab *symtab : compunit_filetabs (cu))
+           {
+             const char *name = symtab->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 = symtab;
+               }
+           }
        }
     }
 
   if (current_source_symtab)
     return;
 
-  ALL_OBJFILES (ofp)
-  {
-    if (ofp->sf)
-      s = ofp->sf->qf->find_last_source_symtab (ofp);
-    if (s)
-      current_source_symtab = s;
-  }
+  for (objfile *objfile : current_program_space->objfiles ())
+    {
+      if (objfile->sf)
+       s = objfile->sf->qf->find_last_source_symtab (objfile);
+      if (s)
+       current_source_symtab = s;
+    }
   if (current_source_symtab)
     return;
 
@@ -350,26 +348,25 @@ show_directories_command (struct ui_file *file, int from_tty,
   show_directories_1 (NULL, from_tty);
 }
 
-/* Forget line positions and file names for the symtabs in a
-   particular objfile.  */
+/* See source.h.  */
 
 void
 forget_cached_source_info_for_objfile (struct objfile *objfile)
 {
-  struct compunit_symtab *cu;
-  struct symtab *s;
-
-  ALL_OBJFILE_FILETABS (objfile, cu, s)
+  for (compunit_symtab *cu : objfile->compunits ())
     {
-      if (s->line_charpos != NULL)
+      for (symtab *s : compunit_filetabs (cu))
        {
-         xfree (s->line_charpos);
-         s->line_charpos = NULL;
-       }
-      if (s->fullname != NULL)
-       {
-         xfree (s->fullname);
-         s->fullname = NULL;
+         if (s->line_charpos != NULL)
+           {
+             xfree (s->line_charpos);
+             s->line_charpos = NULL;
+           }
+         if (s->fullname != NULL)
+           {
+             xfree (s->fullname);
+             s->fullname = NULL;
+           }
        }
     }
 
@@ -377,22 +374,20 @@ forget_cached_source_info_for_objfile (struct objfile *objfile)
     objfile->sf->qf->forget_cached_source_info (objfile);
 }
 
-/* Forget what we learned about line positions in source files, and
-   which directories contain them; must check again now since files
-   may be found in a different directory now.  */
+/* See source.h.  */
 
 void
 forget_cached_source_info (void)
 {
   struct program_space *pspace;
-  struct objfile *objfile;
 
   ALL_PSPACES (pspace)
-    ALL_PSPACE_OBJFILES (pspace, objfile)
-    {
-      forget_cached_source_info_for_objfile (objfile);
-    }
+    for (objfile *objfile : pspace->objfiles ())
+      {
+       forget_cached_source_info_for_objfile (objfile);
+      }
 
+  g_source_cache.clear ();
   last_source_visited = NULL;
 }
 
@@ -992,7 +987,10 @@ find_and_open_source (const char *filename,
       result = gdb_open_cloexec (fullname->get (), OPEN_MODE, 0);
       if (result >= 0)
        {
-         *fullname = gdb_realpath (fullname->get ());
+         if (basenames_may_differ)
+           *fullname = gdb_realpath (fullname->get ());
+         else
+           *fullname = gdb_abspath (fullname->get ());
          return scoped_fd (result);
        }
 
@@ -1014,9 +1012,7 @@ find_and_open_source (const char *filename,
       /* 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,
-         which produces a "required warning" when assigned to a nonconst.  */
-      p = (char *) strstr (source_path, "$cdir");
+      p = strstr (source_path, "$cdir");
       if (p && (p == path || p[-1] == DIRNAME_SEPARATOR)
          && (p[cdir_len] == DIRNAME_SEPARATOR || p[cdir_len] == '\0'))
        {
@@ -1032,26 +1028,22 @@ 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.  */
-      rewritten_filename = rewrite_source_path (filename);
+  gdb::unique_xmalloc_ptr<char> rewritten_filename
+    = rewrite_source_path (filename);
 
-      if (rewritten_filename != NULL)
-       filename = rewritten_filename.get ();
-    }
+  if (rewritten_filename != NULL)
+    filename = rewritten_filename.get ();
 
-  result = openp (path, OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH, filename,
-                 OPEN_MODE, fullname);
+  openp_flags flags = OPF_SEARCH_IN_PATH;
+  if (basenames_may_differ)
+    flags |= OPF_RETURN_REALPATH;
+  result = openp (path, flags, 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 | OPF_RETURN_REALPATH, p,
-                       OPEN_MODE, fullname);
+       result = openp (path, flags, p, OPEN_MODE, fullname);
     }
 
   return scoped_fd (result);
@@ -1137,7 +1129,7 @@ symtab_to_filename_for_display (struct symtab *symtab)
    to be open on descriptor DESC.
    All set S->nlines to the number of such lines.  */
 
-void
+static void
 find_source_lines (struct symtab *s, int desc)
 {
   struct stat st;
@@ -1204,54 +1196,20 @@ find_source_lines (struct symtab *s, int desc)
 
 \f
 
-/* Get full pathname and line number positions for a symtab.
-   Set *FULLNAME to actual name of the file as found by `openp',
-   or to 0 if the file is not found.  */
-
-static void
-get_filename_and_charpos (struct symtab *s, char **fullname)
-{
-  scoped_fd desc = open_source_file (s);
-  if (desc.get () < 0)
-    {
-      if (fullname)
-       *fullname = NULL;
-      return;
-    }
-  if (fullname)
-    *fullname = s->fullname;
-  if (s->line_charpos == 0)
-    find_source_lines (s, desc.get ());
-}
-
-/* Print text describing the full name of the source file S
-   and the line number LINE and its corresponding character position.
-   The text starts with two Ctrl-z so that the Emacs-GDB interface
-   can easily find it.
-
-   MID_STATEMENT is nonzero if the PC is not at the beginning of that line.
-
-   Return 1 if successful, 0 if could not find the file.  */
+/* See source.h.  */
 
-int
-identify_source_line (struct symtab *s, int line, int mid_statement,
-                     CORE_ADDR pc)
+scoped_fd
+open_source_file_with_line_charpos (struct symtab *s)
 {
-  if (s->line_charpos == 0)
-    get_filename_and_charpos (s, (char **) NULL);
-  if (s->fullname == 0)
-    return 0;
-  if (line > s->nlines)
-    /* 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 (SYMTAB_OBJFILE (s)), pc);
+  scoped_fd fd (open_source_file (s));
+  if (fd.get () < 0)
+    return fd;
 
-  current_source_line = line;
-  current_source_symtab = s;
-  clear_lines_listed_range ();
-  return 1;
+  if (s->line_charpos == nullptr)
+    find_source_lines (s, fd.get ());
+  return fd;
 }
+
 \f
 
 /* Print source lines from the file of symtab S,
@@ -1261,7 +1219,6 @@ static void
 print_source_lines_base (struct symtab *s, int line, int stopline,
                         print_source_lines_flags flags)
 {
-  int c;
   scoped_fd desc;
   int noprint = 0;
   int nlines = stopline - line;
@@ -1344,26 +1301,21 @@ 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.get ());
+  /* If the user requested a sequence of lines that seems to go backward
+     (from high to low line numbers) then we don't print anything.  */
+  if (stopline <= line)
+    return;
 
-  if (line < 1 || line > s->nlines)
+  std::string lines;
+  if (!g_source_cache.get_source_lines (s, line, stopline - 1, &lines))
     error (_("Line number %d out of range; %s has %d lines."),
           line, symtab_to_filename_for_display (s), s->nlines);
 
-  if (lseek (desc.get (), s->line_charpos[line - 1], 0) < 0)
-    perror_with_name (symtab_to_filename_for_display (s));
-
-  gdb_file_up stream = desc.to_file (FDOPEN_MODE);
-  clearerr (stream.get ());
-
-  while (nlines-- > 0)
+  const char *iter = lines.c_str ();
+  while (nlines-- > 0 && *iter != '\0')
     {
       char buf[20];
 
-      c = fgetc (stream.get ());
-      if (c == EOF)
-       break;
       last_line_listed = current_source_line;
       if (flags & PRINT_SOURCE_LINES_FILENAME)
         {
@@ -1372,39 +1324,63 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
         }
       xsnprintf (buf, sizeof (buf), "%d\t", current_source_line++);
       uiout->text (buf);
-      do
+
+      while (*iter != '\0')
        {
-         if (c < 040 && c != '\t' && c != '\n' && c != '\r')
+         /* Find a run of characters that can be emitted at once.
+            This is done so that escape sequences are kept
+            together.  */
+         const char *start = iter;
+         while (true)
            {
-             xsnprintf (buf, sizeof (buf), "^%c", c + 0100);
-             uiout->text (buf);
+             int skip_bytes;
+
+             char c = *iter;
+             if (c == '\033' && skip_ansi_escape (iter, &skip_bytes))
+               iter += skip_bytes;
+             else if (c >= 0 && c < 040 && c != '\t')
+               break;
+             else if (c == 0177)
+               break;
+             else
+               ++iter;
            }
-         else if (c == 0177)
-           uiout->text ("^?");
-         else if (c == '\r')
+         if (iter > start)
            {
-             /* Skip a \r character, but only before a \n.  */
-             int c1 = fgetc (stream.get ());
-
-             if (c1 != '\n')
-               printf_filtered ("^%c", c + 0100);
-             if (c1 != EOF)
-               ungetc (c1, stream.get ());
+             std::string text (start, iter);
+             uiout->text (text.c_str ());
            }
-         else
+         if (*iter == '\r')
            {
-             xsnprintf (buf, sizeof (buf), "%c", c);
+             /* Treat either \r or \r\n as a single newline.  */
+             ++iter;
+             if (*iter == '\n')
+               ++iter;
+             break;
+           }
+         else if (*iter == '\n')
+           {
+             ++iter;
+             break;
+           }
+         else if (*iter > 0 && *iter < 040)
+           {
+             xsnprintf (buf, sizeof (buf), "^%c", *iter + 0100);
              uiout->text (buf);
+             ++iter;
+           }
+         else if (*iter == 0177)
+           {
+             uiout->text ("^?");
+             ++iter;
            }
        }
-      while (c != '\n' && (c = fgetc (stream.get ())) >= 0);
+      uiout->text ("\n");
     }
 }
 \f
-/* Show source lines from the file of symtab S, starting with line
-   number LINE and stopping before line number STOPLINE.  If this is
-   not the command line version, then the source is shown in the source
-   window otherwise it is simply printed.  */
+
+/* See source.h.  */
 
 void
 print_source_lines (struct symtab *s, int line, int stopline,
@@ -1412,6 +1388,18 @@ print_source_lines (struct symtab *s, int line, int stopline,
 {
   print_source_lines_base (s, line, stopline, flags);
 }
+
+/* See source.h.  */
+
+void
+print_source_lines (struct symtab *s, source_lines_range line_range,
+                   print_source_lines_flags flags)
+{
+  print_source_lines_base (s, line_range.startline (),
+                          line_range.stopline (), flags);
+}
+
+
 \f
 /* Print info on range of pc's in a specified line.  */
 
@@ -1508,8 +1496,8 @@ info_line_command (const 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.size () == 1)
-           identify_source_line (sal.symtab, sal.line, 0, start_pc);
+         if (sals.size () == 1)
+           annotate_source_line (sal.symtab, sal.line, 0, start_pc);
        }
       else
        /* Is there any case in which we get here, and have an address
@@ -1536,13 +1524,10 @@ search_command_helper (const char *regex, int from_tty, bool forward)
   if (current_source_symtab == 0)
     select_source_symtab (0);
 
-  scoped_fd desc = open_source_file (current_source_symtab);
+  scoped_fd desc (open_source_file_with_line_charpos (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.get ());
-
   int line = (forward
              ? last_line_listed + 1
              : last_line_listed - 1);
@@ -1598,6 +1583,8 @@ search_command_helper (const char *regex, int from_tty, bool forward)
       else
        {
          line--;
+         if (line < 1)
+           break;
          if (fseek (stream.get (),
                     current_source_symtab->line_charpos[line - 1], 0) < 0)
            {
@@ -1833,6 +1820,33 @@ set_substitute_path_command (const char *args, int from_tty)
   forget_cached_source_info ();
 }
 
+/* See source.h.  */
+
+source_lines_range::source_lines_range (int startline,
+                                       source_lines_range::direction dir)
+{
+  if (dir == source_lines_range::FORWARD)
+    {
+      LONGEST end = static_cast <LONGEST> (startline) + get_lines_to_list ();
+
+      if (end > INT_MAX)
+       end = INT_MAX;
+
+      m_startline = startline;
+      m_stopline = static_cast <int> (end);
+    }
+  else
+    {
+      LONGEST start = static_cast <LONGEST> (startline) - get_lines_to_list ();
+
+      if (start < 1)
+       start = 1;
+
+      m_startline = static_cast <int> (start);
+      m_stopline = startline;
+    }
+}
+
 \f
 void
 _initialize_source (void)
This page took 0.0366 seconds and 4 git commands to generate.