tfiala updated this revision to Diff 71180.
tfiala added a comment.

Updated patch, tweaked and verified it is working, rebased against r281243.

I'd like to add some unittests for this, so this isn't ready quite yet.


https://reviews.llvm.org/D20835

Files:
  include/lldb/API/SBSourceManager.h
  include/lldb/Core/Debugger.h
  include/lldb/Core/Disassembler.h
  include/lldb/Core/SourceManager.h
  include/lldb/Core/Stream.h
  packages/Python/lldbsuite/test/settings/TestSettings.py
  packages/Python/lldbsuite/test/source-manager/TestSourceManager.py
  scripts/interface/SBSourceManager.i
  source/API/SBSourceManager.cpp
  source/Commands/CommandObjectSource.cpp
  source/Core/Debugger.cpp
  source/Core/Disassembler.cpp
  source/Core/SourceManager.cpp
  source/Core/StreamAsynchronousIO.cpp
  source/Target/StackFrame.cpp

Index: source/Target/StackFrame.cpp
===================================================================
--- source/Target/StackFrame.cpp
+++ source/Target/StackFrame.cpp
@@ -1875,7 +1875,8 @@
           size_t num_lines =
               target->GetSourceManager().DisplaySourceLinesWithLineNumbers(
                   m_sc.line_entry.file, m_sc.line_entry.line,
-                  source_lines_before, source_lines_after, "->", &strm);
+                  m_sc.line_entry.column, source_lines_before,
+                  source_lines_after, "->", &strm);
           if (num_lines != 0)
             have_source = true;
           // TODO: Give here a one time warning if source file is missing.
Index: source/Core/StreamAsynchronousIO.cpp
===================================================================
--- source/Core/StreamAsynchronousIO.cpp
+++ source/Core/StreamAsynchronousIO.cpp
@@ -16,8 +16,8 @@
 using namespace lldb_private;
 
 StreamAsynchronousIO::StreamAsynchronousIO(Debugger &debugger, bool for_stdout)
-    : Stream(0, 4, eByteOrderBig), m_debugger(debugger), m_data(),
-      m_for_stdout(for_stdout) {}
+    : Stream(debugger.GetUseColor() ? eANSIColor : 0, 4, eByteOrderBig),
+      m_debugger(debugger), m_data(), m_for_stdout(for_stdout) {}
 
 StreamAsynchronousIO::~StreamAsynchronousIO() {
   // Flush when we destroy to make sure we display the data
Index: source/Core/SourceManager.cpp
===================================================================
--- source/Core/SourceManager.cpp
+++ source/Core/SourceManager.cpp
@@ -22,6 +22,7 @@
 #include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Target/Target.h"
+#include "lldb/Utility/AnsiTerminal.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -80,7 +81,7 @@
 }
 
 size_t SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile(
-    uint32_t start_line, uint32_t count, uint32_t curr_line,
+    uint32_t start_line, uint32_t count, uint32_t curr_line, uint32_t column,
     const char *current_line_cstr, Stream *s,
     const SymbolContextList *bp_locs) {
   if (count == 0)
@@ -123,7 +124,23 @@
       return_value +=
           s->Printf("%s%2.2s %-4u\t", prefix,
                     line == curr_line ? current_line_cstr : "", line);
-      size_t this_line_size = m_last_file_sp->DisplaySourceLines(line, 0, 0, s);
+      // We only add the line position caret underneath if we don't have an
+      // ANSI-enabled terminal.  ANSI terminals will highlight the character
+      // by underlining it.
+      const bool use_ansi_color = s->GetFlags().Test(Stream::eANSIColor);
+      size_t this_line_size = m_last_file_sp->DisplaySourceLines(
+          line, line == curr_line ? column : 0, 0, 0, s);
+      if (!use_ansi_color && column != 0 && line == curr_line) {
+        // Display caret cursor.
+        std::string src_line;
+        m_last_file_sp->GetLine(line, src_line);
+        return_value += s->Printf("    \t");
+        // Insert a space for every non-tab character in the source line.
+        for (int i = 0; i < column - 1 && i < src_line.length(); ++i)
+          return_value += s->PutChar(src_line[i] == '\t' ? '\t' : ' ');
+        // Now add the caret.
+        return_value += s->Printf("^\n");
+      }
       if (this_line_size == 0) {
         m_last_line = UINT32_MAX;
         break;
@@ -135,8 +152,9 @@
 }
 
 size_t SourceManager::DisplaySourceLinesWithLineNumbers(
-    const FileSpec &file_spec, uint32_t line, uint32_t context_before,
-    uint32_t context_after, const char *current_line_cstr, Stream *s,
+    const FileSpec &file_spec, uint32_t line, uint32_t column,
+    uint32_t context_before, uint32_t context_after,
+    const char *current_line_cstr, Stream *s,
     const SymbolContextList *bp_locs) {
   FileSP file_sp(GetFile(file_spec));
 
@@ -153,7 +171,7 @@
     m_last_file_sp = file_sp;
   }
   return DisplaySourceLinesWithLineNumbersUsingLastFile(
-      start_line, count, line, current_line_cstr, s, bp_locs);
+      start_line, count, line, column, current_line_cstr, s, bp_locs);
 }
 
 size_t SourceManager::DisplayMoreWithLineNumbers(
@@ -193,8 +211,9 @@
     } else
       m_last_line = 1;
 
+    const uint32_t column = 0;
     return DisplaySourceLinesWithLineNumbersUsingLastFile(
-        m_last_line, m_last_count, UINT32_MAX, "", s, bp_locs);
+        m_last_line, m_last_count, UINT32_MAX, column, "", s, bp_locs);
   }
   return 0;
 }
@@ -418,7 +437,7 @@
   }
 }
 
-size_t SourceManager::File::DisplaySourceLines(uint32_t line,
+size_t SourceManager::File::DisplaySourceLines(uint32_t line, uint32_t column,
                                                uint32_t context_before,
                                                uint32_t context_after,
                                                Stream *s) {
@@ -440,7 +459,19 @@
     if (start_line_offset < end_line_offset) {
       size_t count = end_line_offset - start_line_offset;
       const uint8_t *cstr = m_data_sp->GetBytes() + start_line_offset;
-      bytes_written = s->Write(cstr, count);
+      bool use_ansi_color = s->GetFlags().Test(Stream::eANSIColor);
+      if (column && (column < count) && use_ansi_color) {
+        // Mark the current column with an underline.
+        std::string ctl;
+        bytes_written = s->Write(cstr, column - 1);
+        ctl = lldb_utility::ansi::FormatAnsiTerminalCodes("${ansi.underline}");
+        bytes_written += s->Write(ctl.c_str(), ctl.length());
+        bytes_written += s->Write(cstr + column - 1, 1);
+        ctl = lldb_utility::ansi::FormatAnsiTerminalCodes("${ansi.normal}");
+        bytes_written += s->Write(ctl.c_str(), ctl.length());
+        bytes_written += s->Write(cstr + column, count - column);
+      } else
+        bytes_written = s->Write(cstr, count);
       if (!is_newline_char(cstr[count - 1]))
         bytes_written += s->EOL();
     }
Index: source/Core/Disassembler.cpp
===================================================================
--- source/Core/Disassembler.cpp
+++ source/Core/Disassembler.cpp
@@ -289,6 +289,9 @@
         func_decl_file == prologue_end_line.original_file) {
       decl_line.file = func_decl_file;
       decl_line.line = func_decl_line;
+      // TODO do we care about column on these entries?  If so, we need to
+      // plumb that through GetStartLineSourceInfo.
+      decl_line.column = 0;
     }
   }
   return decl_line;
@@ -448,6 +451,7 @@
               SourceLine this_line;
               this_line.file = sc.line_entry.file;
               this_line.line = sc.line_entry.line;
+              this_line.column = sc.line_entry.column;
               if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line) ==
                   false)
                 AddLineToSourceLineTables(this_line, source_lines_seen);
@@ -613,7 +617,7 @@
             line_highlight = "**";
           }
           source_manager.DisplaySourceLinesWithLineNumbers(
-              ln.file, ln.line, 0, 0, line_highlight, &strm);
+              ln.file, ln.line, ln.column, 0, 0, line_highlight, &strm);
         }
         if (source_lines_to_display.print_source_context_end_eol)
           strm.EOL();
Index: source/Core/Debugger.cpp
===================================================================
--- source/Core/Debugger.cpp
+++ source/Core/Debugger.cpp
@@ -173,6 +173,10 @@
     {"stop-line-count-before", OptionValue::eTypeSInt64, true, 3, nullptr,
      nullptr, "The number of sources lines to display that come before the "
               "current source line when displaying a stopped context."},
+    {"stop-show-column", OptionValue::eTypeBoolean, true, true, nullptr,
+     nullptr, "If true, LLDB will use the column information from the debug "
+              "info to mark the current position when displaying a stopped "
+              "context."},
     {"term-width", OptionValue::eTypeSInt64, true, 80, nullptr, nullptr,
      "The maximum number of columns to use for displaying text."},
     {"thread-format", OptionValue::eTypeFormatEntity, true, 0,
@@ -210,6 +214,7 @@
   ePropertyStopDisassemblyDisplay,
   ePropertyStopLineCountAfter,
   ePropertyStopLineCountBefore,
+  ePropertyStopShowColumn,
   ePropertyTerminalWidth,
   ePropertyThreadFormat,
   ePropertyUseExternalEditor,
@@ -371,6 +376,12 @@
   return ret;
 }
 
+bool Debugger::GetStopShowColumn() const {
+  const uint32_t idx = ePropertyStopShowColumn;
+  return m_collection_sp->GetPropertyAtIndexAsBoolean(
+      nullptr, idx, g_properties[idx].default_uint_value != 0);
+}
+
 uint32_t Debugger::GetStopSourceLineCount(bool before) const {
   const uint32_t idx =
       before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
Index: source/Commands/CommandObjectSource.cpp
===================================================================
--- source/Commands/CommandObjectSource.cpp
+++ source/Commands/CommandObjectSource.cpp
@@ -896,8 +896,10 @@
 
       result.AppendMessageWithFormat("File: %s\n",
                                      start_file.GetPath().c_str());
+      // We don't care about the column here.
+      const uint32_t column = 0;
       return target->GetSourceManager().DisplaySourceLinesWithLineNumbers(
-          start_file, line_no, 0, m_options.num_lines, "",
+          start_file, line_no, 0, m_options.num_lines, column, "",
           &result.GetOutputStream(), GetBreakpointLocations());
     } else {
       result.AppendErrorWithFormat(
@@ -1150,8 +1152,12 @@
           size_t lines_to_back_up =
               m_options.num_lines >= 10 ? 5 : m_options.num_lines / 2;
 
+          const uint32_t column =
+              m_interpreter.GetDebugger().GetStopShowColumn()
+                  ? sc.line_entry.column
+                  : 0;
           target->GetSourceManager().DisplaySourceLinesWithLineNumbers(
-              sc.comp_unit, sc.line_entry.line, lines_to_back_up,
+              sc.comp_unit, sc.line_entry.line, lines_to_back_up, column,
               m_options.num_lines - lines_to_back_up, "->",
               &result.GetOutputStream(), GetBreakpointLocations());
           result.SetStatus(eReturnStatusSuccessFinishResult);
@@ -1187,12 +1193,14 @@
         } else
           m_breakpoint_locations.Clear();
 
+        const uint32_t column = 0;
         if (target->GetSourceManager()
                 .DisplaySourceLinesWithLineNumbersUsingLastFile(
                     m_options.start_line, // Line to display
                     m_options.num_lines,  // Lines after line to
                     UINT32_MAX,           // Don't mark "line"
-                    "",                   // Don't mark "line"
+                    column,
+                    "", // Don't mark "line"
                     &result.GetOutputStream(), GetBreakpointLocations())) {
           result.SetStatus(eReturnStatusSuccessFinishResult);
         }
@@ -1269,10 +1277,10 @@
 
           if (m_options.num_lines == 0)
             m_options.num_lines = 10;
-
+          const uint32_t column = 0;
           target->GetSourceManager().DisplaySourceLinesWithLineNumbers(
-              sc.comp_unit, m_options.start_line, 0, m_options.num_lines, "",
-              &result.GetOutputStream(), GetBreakpointLocations());
+              sc.comp_unit, m_options.start_line, 0, m_options.num_lines,
+              column, "", &result.GetOutputStream(), GetBreakpointLocations());
 
           result.SetStatus(eReturnStatusSuccessFinishResult);
         } else {
Index: source/API/SBSourceManager.cpp
===================================================================
--- source/API/SBSourceManager.cpp
+++ source/API/SBSourceManager.cpp
@@ -37,7 +37,7 @@
   }
 
   size_t DisplaySourceLinesWithLineNumbers(const lldb_private::FileSpec &file,
-                                           uint32_t line,
+                                           uint32_t line, uint32_t column,
                                            uint32_t context_before,
                                            uint32_t context_after,
                                            const char *current_line_cstr,
@@ -48,14 +48,15 @@
     lldb::TargetSP target_sp(m_target_wp.lock());
     if (target_sp) {
       return target_sp->GetSourceManager().DisplaySourceLinesWithLineNumbers(
-          file, line, context_before, context_after, current_line_cstr, s);
+          file, line, column, context_before, context_after, current_line_cstr,
+          s);
     } else {
       lldb::DebuggerSP debugger_sp(m_debugger_wp.lock());
       if (debugger_sp) {
         return debugger_sp->GetSourceManager()
-            .DisplaySourceLinesWithLineNumbers(file, line, context_before,
-                                               context_after, current_line_cstr,
-                                               s);
+            .DisplaySourceLinesWithLineNumbers(file, line, column,
+                                               context_before, context_after,
+                                               current_line_cstr, s);
       }
     }
     return 0;
@@ -96,10 +97,20 @@
 size_t SBSourceManager::DisplaySourceLinesWithLineNumbers(
     const SBFileSpec &file, uint32_t line, uint32_t context_before,
     uint32_t context_after, const char *current_line_cstr, SBStream &s) {
+  const uint32_t column = 0;
+  return DisplaySourceLinesWithLineNumbersAndColumn(
+      file.ref(), line, column, context_before, context_after,
+      current_line_cstr, s);
+}
+
+size_t SBSourceManager::DisplaySourceLinesWithLineNumbersAndColumn(
+    const SBFileSpec &file, uint32_t line, uint32_t column,
+    uint32_t context_before, uint32_t context_after,
+    const char *current_line_cstr, SBStream &s) {
   if (m_opaque_ap.get() == NULL)
     return 0;
 
   return m_opaque_ap->DisplaySourceLinesWithLineNumbers(
-      file.ref(), line, context_before, context_after, current_line_cstr,
-      s.get());
+      file.ref(), line, column, context_before, context_after,
+      current_line_cstr, s.get());
 }
Index: scripts/interface/SBSourceManager.i
===================================================================
--- scripts/interface/SBSourceManager.i
+++ scripts/interface/SBSourceManager.i
@@ -49,6 +49,13 @@
                                        uint32_t context_after,
                                        const char* current_line_cstr,
                                        lldb::SBStream &s);
+    size_t
+    DisplaySourceLinesWithLineNumbersAndColumn (const lldb::SBFileSpec &file,
+                                                uint32_t line, uint32_t column,
+                                                uint32_t context_before,
+                                                uint32_t context_after,
+                                                const char* current_line_cstr,
+                                                lldb::SBStream &s);
 };
 
 } // namespace lldb
Index: packages/Python/lldbsuite/test/source-manager/TestSourceManager.py
===================================================================
--- packages/Python/lldbsuite/test/source-manager/TestSourceManager.py
+++ packages/Python/lldbsuite/test/source-manager/TestSourceManager.py
@@ -51,21 +51,22 @@
         source_mgr = self.dbg.GetSourceManager()
         # Use a string stream as the destination.
         stream = lldb.SBStream()
-        source_mgr.DisplaySourceLinesWithLineNumbers(filespec,
-                                                     self.line,
-                                                     2,  # context before
-                                                     2,  # context after
-                                                     "=>",  # prefix for current line
-                                                     stream)
+        column = 1
+        context_before = 2
+        context_after = 2
+        current_line_prefix = "=>"
+        source_mgr.DisplaySourceLinesWithLineNumbersAndColumn(
+            filespec, self.line, column,  context_before, context_after,
+            current_line_prefix, stream)
 
         #    2
         #    3    int main(int argc, char const *argv[]) {
         # => 4        printf("Hello world.\n"); // Set break point at this line.
         #    5        return 0;
         #    6    }
         self.expect(stream.GetData(), "Source code displayed correctly",
                     exe=False,
-                    patterns=['=> %d.*Hello world' % self.line])
+                    patterns=['=> %d.*Hello world' % self.line, '*\^'])
 
         # Boundary condition testings for SBStream().  LLDB should not crash!
         stream.Print(None)
Index: packages/Python/lldbsuite/test/settings/TestSettings.py
===================================================================
--- packages/Python/lldbsuite/test/settings/TestSettings.py
+++ packages/Python/lldbsuite/test/settings/TestSettings.py
@@ -527,6 +527,7 @@
                              "stop-disassembly-display",
                              "stop-line-count-after",
                              "stop-line-count-before",
+                             "stop-show-column",
                              "term-width",
                              "thread-format",
                              "use-external-editor",
Index: include/lldb/Core/Stream.h
===================================================================
--- include/lldb/Core/Stream.h
+++ include/lldb/Core/Stream.h
@@ -34,9 +34,10 @@
     eVerbose = (1 << 0),   ///< If set, verbose logging is enabled
     eDebug = (1 << 1),     ///< If set, debug logging is enabled
     eAddPrefix = (1 << 2), ///< Add number prefixes for binary, octal and hex
-                           ///when eBinary is clear
-    eBinary = (1 << 3) ///< Get and put data as binary instead of as the default
-                       ///string mode.
+                           /// when eBinary is clear
+    eBinary = (1 << 3),    ///< Get and put data as binary instead of as the
+                           /// default string mode.
+    eANSIColor = (1 << 4)  ///< Indicates whether the stream supports ANSI color
   };
 
   //------------------------------------------------------------------
Index: include/lldb/Core/SourceManager.h
===================================================================
--- include/lldb/Core/SourceManager.h
+++ include/lldb/Core/SourceManager.h
@@ -36,8 +36,9 @@
 
     void UpdateIfNeeded();
 
-    size_t DisplaySourceLines(uint32_t line, uint32_t context_before,
-                              uint32_t context_after, Stream *s);
+    size_t DisplaySourceLines(uint32_t line, uint32_t column,
+                              uint32_t context_before, uint32_t context_after,
+                              Stream *s);
     void FindLinesMatchingRegex(RegularExpression &regex, uint32_t start_line,
                                 uint32_t end_line,
                                 std::vector<uint32_t> &match_lines);
@@ -114,14 +115,16 @@
 
   FileSP GetLastFile() { return m_last_file_sp; }
 
-  size_t DisplaySourceLinesWithLineNumbers(
-      const FileSpec &file, uint32_t line, uint32_t context_before,
-      uint32_t context_after, const char *current_line_cstr, Stream *s,
-      const SymbolContextList *bp_locs = nullptr);
+  size_t
+  DisplaySourceLinesWithLineNumbers(const FileSpec &file, uint32_t line,
+                                    uint32_t column, uint32_t context_before,
+                                    uint32_t context_after,
+                                    const char *current_line_cstr, Stream *s,
+                                    const SymbolContextList *bp_locs = nullptr);
 
   // This variant uses the last file we visited.
   size_t DisplaySourceLinesWithLineNumbersUsingLastFile(
-      uint32_t start_line, uint32_t count, uint32_t curr_line,
+      uint32_t start_line, uint32_t count, uint32_t curr_line, uint32_t column,
       const char *current_line_cstr, Stream *s,
       const SymbolContextList *bp_locs = nullptr);
 
Index: include/lldb/Core/Disassembler.h
===================================================================
--- include/lldb/Core/Disassembler.h
+++ include/lldb/Core/Disassembler.h
@@ -398,15 +398,16 @@
   struct SourceLine {
     FileSpec file;
     uint32_t line;
+    uint32_t column;
 
-    SourceLine() : file(), line(LLDB_INVALID_LINE_NUMBER) {}
+    SourceLine() : file(), line(LLDB_INVALID_LINE_NUMBER), column(0) {}
 
     bool operator==(const SourceLine &rhs) const {
-      return file == rhs.file && line == rhs.line;
+      return file == rhs.file && line == rhs.line && rhs.column == column;
     }
 
     bool operator!=(const SourceLine &rhs) const {
-      return file != rhs.file || line != rhs.line;
+      return file != rhs.file || line != rhs.line || column != rhs.column;
     }
 
     bool IsValid() const { return line != LLDB_INVALID_LINE_NUMBER; }
@@ -456,6 +457,7 @@
     SourceLine sl;
     sl.file = line.file;
     sl.line = line.line;
+    sl.column = line.column;
     return ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, sl);
   };
 
Index: include/lldb/Core/Debugger.h
===================================================================
--- include/lldb/Core/Debugger.h
+++ include/lldb/Core/Debugger.h
@@ -238,6 +238,8 @@
 
   bool SetUseColor(bool use_color);
 
+  bool GetStopShowColumn() const;
+
   uint32_t GetStopSourceLineCount(bool before) const;
 
   StopDisassemblyType GetStopDisassemblyDisplay() const;
Index: include/lldb/API/SBSourceManager.h
===================================================================
--- include/lldb/API/SBSourceManager.h
+++ include/lldb/API/SBSourceManager.h
@@ -30,6 +30,11 @@
       const lldb::SBFileSpec &file, uint32_t line, uint32_t context_before,
       uint32_t context_after, const char *current_line_cstr, lldb::SBStream &s);
 
+  size_t DisplaySourceLinesWithLineNumbersAndColumn(
+      const lldb::SBFileSpec &file, uint32_t line, uint32_t column,
+      uint32_t context_before, uint32_t context_after,
+      const char *current_line_cstr, lldb::SBStream &s);
+
 protected:
   friend class SBCommandInterpreter;
   friend class SBDebugger;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to