[Lldb-commits] [lldb] r228207 - Get rid of Debugger::FormatPrompt() and replace it with the new FormatEntity class.
Greg Clayton
gclayton at apple.com
Wed Feb 4 14:00:54 PST 2015
Author: gclayton
Date: Wed Feb 4 16:00:53 2015
New Revision: 228207
URL: http://llvm.org/viewvc/llvm-project?rev=228207&view=rev
Log:
Get rid of Debugger::FormatPrompt() and replace it with the new FormatEntity class.
Why? Debugger::FormatPrompt() would run through the format prompt every time and parse it and emit it piece by piece. It also did formatting differently depending on which key/value pair it was parsing.
The new code improves on this with the following features:
1 - Allow format strings to be parsed into a FormatEntity::Entry which can contain multiple child FormatEntity::Entry objects. This FormatEntity::Entry is a parsed version of what was previously always done in Debugger::FormatPrompt() so it is more efficient to emit formatted strings using the new parsed FormatEntity::Entry.
2 - Allows errors in format strings to be shown immediately when setting the settings (frame-format, thread-format, disassembly-format
3 - Allows auto completion by implementing a new OptionValueFormatEntity and switching frame-format, thread-format, and disassembly-format settings over to using it.
4 - The FormatEntity::Entry for each of the frame-format, thread-format, disassembly-format settings only replaces the old one if the format parses correctly
5 - Combines all consecutive string values together for efficient output. This means all "${ansi.*}" keys and all desensitized characters like "\n" "\t" "\0721" "\x23" will get combined with their previous strings
6 - ${*.script:} (like "${var.script:mymodule.my_var_function}") have all been switched over to use ${script.*:} "${script.var:mymodule.my_var_function}") to make the format easier to parse as I don't believe anyone was using these format string power user features.
7 - All key values pairs are defined in simple C arrays of entries so it is much easier to add new entries.
These changes pave the way for subsequent modifications where we can modify formats to do more (like control the width of value strings can do more and add more functionality more easily like string formatting to control the width, printf formats and more).
Added:
lldb/trunk/include/lldb/Core/FormatEntity.h
lldb/trunk/include/lldb/Interpreter/OptionValueFormatEntity.h
lldb/trunk/source/Core/FormatEntity.cpp
lldb/trunk/source/Interpreter/OptionValueFormatEntity.cpp
lldb/trunk/test/functionalities/format/
lldb/trunk/test/functionalities/format/Makefile
lldb/trunk/test/functionalities/format/TestFormats.py
lldb/trunk/test/functionalities/format/main.c
Modified:
lldb/trunk/include/lldb/Core/Debugger.h
lldb/trunk/include/lldb/Core/Disassembler.h
lldb/trunk/include/lldb/DataFormatters/TypeSummary.h
lldb/trunk/include/lldb/Interpreter/OptionValue.h
lldb/trunk/include/lldb/Interpreter/OptionValueProperties.h
lldb/trunk/include/lldb/Interpreter/OptionValues.h
lldb/trunk/include/lldb/Utility/AnsiTerminal.h
lldb/trunk/include/lldb/lldb-forward.h
lldb/trunk/lldb.xcodeproj/project.pbxproj
lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme
lldb/trunk/source/API/SBInstruction.cpp
lldb/trunk/source/API/SBInstructionList.cpp
lldb/trunk/source/Core/Debugger.cpp
lldb/trunk/source/Core/Disassembler.cpp
lldb/trunk/source/Core/IOHandler.cpp
lldb/trunk/source/DataFormatters/LibCxx.cpp
lldb/trunk/source/DataFormatters/TypeSummary.cpp
lldb/trunk/source/Expression/IRExecutionUnit.cpp
lldb/trunk/source/Interpreter/OptionValue.cpp
lldb/trunk/source/Interpreter/OptionValueProperties.cpp
lldb/trunk/source/Interpreter/Property.cpp
lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
lldb/trunk/source/Target/StackFrame.cpp
lldb/trunk/source/Target/Thread.cpp
lldb/trunk/source/Target/ThreadPlanTracer.cpp
lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py
lldb/trunk/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py
lldb/trunk/test/settings/TestSettings.py
Modified: lldb/trunk/include/lldb/Core/Debugger.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Debugger.h?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Debugger.h (original)
+++ lldb/trunk/include/lldb/Core/Debugger.h Wed Feb 4 16:00:53 2015
@@ -19,6 +19,7 @@
#include "lldb/lldb-public.h"
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Communication.h"
+#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Core/Listener.h"
#include "lldb/Core/SourceManager.h"
@@ -247,15 +248,7 @@ public:
GetDebuggerAtIndex (size_t index);
static bool
- FormatPrompt (const char *format,
- const SymbolContext *sc,
- const ExecutionContext *exe_ctx,
- const Address *addr,
- Stream &s,
- ValueObject* valobj = NULL);
-
- static bool
- FormatDisassemblerAddress (const char *format,
+ FormatDisassemblerAddress (const FormatEntity::Entry *format,
const SymbolContext *sc,
const SymbolContext *prev_sc,
const ExecutionContext *exe_ctx,
@@ -300,13 +293,13 @@ public:
bool
GetAutoConfirm () const;
- const char *
+ const FormatEntity::Entry *
GetDisassemblyFormat() const;
- const char *
+ const FormatEntity::Entry *
GetFrameFormat() const;
- const char *
+ const FormatEntity::Entry *
GetThreadFormat() const;
lldb::ScriptLanguage
Modified: lldb/trunk/include/lldb/Core/Disassembler.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Disassembler.h?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Disassembler.h (original)
+++ lldb/trunk/include/lldb/Core/Disassembler.h Wed Feb 4 16:00:53 2015
@@ -117,7 +117,7 @@ public:
/// the InstructionList.
/// Only needed if show_address is true.
///
- /// @param[in] disassembly_addr_format_spec
+ /// @param[in] disassembly_addr_format
/// The format specification for how addresses are printed.
/// Only needed if show_address is true.
//------------------------------------------------------------------
@@ -130,7 +130,7 @@ public:
const ExecutionContext* exe_ctx,
const SymbolContext *sym_ctx,
const SymbolContext *prev_sym_ctx,
- const char *disassembly_addr_format_spec);
+ const FormatEntity::Entry *disassembly_addr_format);
virtual bool
DoesBranch () = 0;
Added: lldb/trunk/include/lldb/Core/FormatEntity.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatEntity.h?rev=228207&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Core/FormatEntity.h (added)
+++ lldb/trunk/include/lldb/Core/FormatEntity.h Wed Feb 4 16:00:53 2015
@@ -0,0 +1,260 @@
+//===-- FormatEntity.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_FormatEntity_h_
+#define liblldb_FormatEntity_h_
+#if defined(__cplusplus)
+
+#include <string>
+#include <vector>
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Error.h"
+
+namespace llvm
+{
+ class StringRef;
+}
+
+namespace lldb_private
+{
+ class FormatEntity
+ {
+ public:
+ struct Entry
+ {
+ enum class Type {
+ Invalid,
+ ParentNumber,
+ ParentString,
+ InsertString,
+ Root,
+ String,
+ Scope,
+ Variable,
+ VariableSynthetic,
+ ScriptVariable,
+ ScriptVariableSynthetic,
+ AddressLoad,
+ AddressFile,
+ AddressLoadOrFile,
+ ProcessID,
+ ProcessFile,
+ ScriptProcess,
+ ThreadID,
+ ThreadProtocolID,
+ ThreadIndexID,
+ ThreadName,
+ ThreadQueue,
+ ThreadStopReason,
+ ThreadReturnValue,
+ ThreadCompletedExpression,
+ ScriptThread,
+ ThreadInfo,
+ TargetArch,
+ ScriptTarget,
+ ModuleFile,
+ File,
+ FrameIndex,
+ FrameRegisterPC,
+ FrameRegisterSP,
+ FrameRegisterFP,
+ FrameRegisterFlags,
+ FrameRegisterByName,
+ ScriptFrame,
+ FunctionID,
+ FunctionDidChange,
+ FunctionInitialFunction,
+ FunctionName,
+ FunctionNameWithArgs,
+ FunctionNameNoArgs,
+ FunctionAddrOffset,
+ FunctionAddrOffsetConcrete,
+ FunctionLineOffset,
+ FunctionPCOffset,
+ LineEntryFile,
+ LineEntryLineNumber,
+ LineEntryStartAddress,
+ LineEntryEndAddress,
+ CurrentPCArrow
+ };
+
+ enum FormatType
+ {
+ None,
+ UInt32,
+ UInt64,
+ CString
+ };
+
+ struct Definition
+ {
+ const char *name;
+ const char *string; // Insert this exact string into the output
+ Entry::Type type;
+ FormatType format_type; // uint32_t, uint64_t, cstr, or anything that can be formatted by printf or lldb::Format
+ uint64_t data;
+ uint32_t num_children;
+ Definition *children; // An array of "num_children" Definition entries,
+ bool keep_separator;
+ };
+
+ Entry (Type t = Type::Invalid,
+ const char *s = NULL,
+ const char *f = NULL) :
+ string (s ? s : ""),
+ printf_format (f ? f : ""),
+ children (),
+ definition (NULL),
+ type (t),
+ fmt (lldb::eFormatDefault),
+ number (0),
+ deref (false)
+ {
+ }
+
+ Entry (llvm::StringRef s);
+ Entry (char ch);
+
+ void
+ AppendChar (char ch);
+
+ void
+ AppendText (const llvm::StringRef &s);
+
+ void
+ AppendText (const char *cstr);
+
+ void
+ AppendEntry (const Entry &&entry)
+ {
+ children.push_back(entry);
+ }
+
+ void
+ Clear ()
+ {
+ string.clear();
+ printf_format.clear();
+ children.clear();
+ definition = NULL;
+ type = Type::Invalid;
+ fmt = lldb::eFormatDefault;
+ number = 0;
+ deref = false;
+ }
+
+ static const char *
+ TypeToCString (Type t);
+
+ void
+ Dump (Stream &s, int depth = 0) const;
+
+ bool
+ operator == (const Entry &rhs) const
+ {
+ if (string != rhs.string)
+ return false;
+ if (printf_format != rhs.printf_format)
+ return false;
+ const size_t n = children.size();
+ const size_t m = rhs.children.size();
+ for (size_t i=0; i < std::min<size_t>(n, m); ++i)
+ {
+ if (!(children[i] == rhs.children[i]))
+ return false;
+ }
+ if (children != rhs.children)
+ return false;
+ if (definition != rhs.definition)
+ return false;
+ if (type != rhs.type)
+ return false;
+ if (fmt != rhs.fmt)
+ return false;
+ if (deref != rhs.deref)
+ return false;
+ return true;
+ }
+
+ std::string string;
+ std::string printf_format;
+ std::vector<Entry> children;
+ Definition *definition;
+ Type type;
+ lldb::Format fmt;
+ lldb::addr_t number;
+ bool deref;
+ };
+
+ static bool
+ Format (const Entry &entry,
+ Stream &s,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ const Address *addr,
+ ValueObject* valobj,
+ bool function_changed,
+ bool initial_function);
+
+ static bool
+ FormatStringRef (const llvm::StringRef &format,
+ Stream &s,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ const Address *addr,
+ ValueObject* valobj,
+ bool function_changed,
+ bool initial_function);
+
+ static bool
+ FormatCString (const char *format,
+ Stream &s,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ const Address *addr,
+ ValueObject* valobj,
+ bool function_changed,
+ bool initial_function);
+
+ static Error
+ Parse (const llvm::StringRef &format, Entry &entry);
+
+ static Error
+ ExtractVariableInfo (llvm::StringRef &format_str,
+ llvm::StringRef &variable_name,
+ llvm::StringRef &variable_format);
+
+ static size_t
+ AutoComplete (const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches);
+
+ //----------------------------------------------------------------------
+ // Format the current elements into the stream \a s.
+ //
+ // The root element will be stripped off and the format str passed in
+ // will be either an empty string (print a description of this object),
+ // or contain a . separated series like a domain name that identifies
+ // further sub elements to display.
+ //----------------------------------------------------------------------
+ static bool
+ FormatFileSpec (const FileSpec &file, Stream &s, llvm::StringRef elements, llvm::StringRef element_format);
+ protected:
+
+ static Error
+ ParseInternal (llvm::StringRef &format, Entry &parent_entry, uint32_t depth);
+
+ };
+
+}
+#endif // #if defined(__cplusplus)
+#endif // liblldb_FormatEntity_h_
Modified: lldb/trunk/include/lldb/DataFormatters/TypeSummary.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/DataFormatters/TypeSummary.h?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/include/lldb/DataFormatters/TypeSummary.h (original)
+++ lldb/trunk/include/lldb/DataFormatters/TypeSummary.h Wed Feb 4 16:00:53 2015
@@ -23,6 +23,8 @@
#include "lldb/lldb-public.h"
#include "lldb/lldb-enumerations.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Interpreter/ScriptInterpreterPython.h"
#include "lldb/Symbol/Type.h"
@@ -372,31 +374,27 @@ namespace lldb_private {
// simple string-based summaries, using ${var to show data
struct StringSummaryFormat : public TypeSummaryImpl
{
- std::string m_format;
+ std::string m_format_str;
+ FormatEntity::Entry m_format;
+ Error m_error;
StringSummaryFormat(const TypeSummaryImpl::Flags& flags,
const char* f);
+ virtual
+ ~StringSummaryFormat()
+ {
+ }
+
const char*
GetSummaryString () const
{
- return m_format.c_str();
+ return m_format_str.c_str();
}
void
- SetSummaryString (const char* data)
- {
- if (data)
- m_format.assign(data);
- else
- m_format.clear();
- }
-
- virtual
- ~StringSummaryFormat()
- {
- }
-
+ SetSummaryString (const char* f);
+
virtual bool
FormatObject(ValueObject *valobj,
std::string& dest,
Modified: lldb/trunk/include/lldb/Interpreter/OptionValue.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/OptionValue.h?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/OptionValue.h (original)
+++ lldb/trunk/include/lldb/Interpreter/OptionValue.h Wed Feb 4 16:00:53 2015
@@ -17,6 +17,7 @@
#include "lldb/lldb-defines.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
+#include "lldb/Core/FormatEntity.h"
namespace lldb_private {
@@ -45,7 +46,8 @@ namespace lldb_private {
eTypeSInt64,
eTypeString,
eTypeUInt64,
- eTypeUUID
+ eTypeUUID,
+ eTypeFormatEntity
} Type;
enum {
@@ -309,7 +311,13 @@ namespace lldb_private {
const OptionValueUUID *
GetAsUUID () const;
-
+
+ OptionValueFormatEntity *
+ GetAsFormatEntity ();
+
+ const OptionValueFormatEntity *
+ GetAsFormatEntity () const;
+
bool
GetBooleanValue (bool fail_value = false) const;
@@ -341,6 +349,9 @@ namespace lldb_private {
bool
SetFormatValue (lldb::Format new_value);
+ const FormatEntity::Entry *
+ GetFormatEntity () const;
+
const RegularExpression *
GetRegexValue () const;
Added: lldb/trunk/include/lldb/Interpreter/OptionValueFormatEntity.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/OptionValueFormatEntity.h?rev=228207&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/OptionValueFormatEntity.h (added)
+++ lldb/trunk/include/lldb/Interpreter/OptionValueFormatEntity.h Wed Feb 4 16:00:53 2015
@@ -0,0 +1,107 @@
+//===-- OptionValueFormatEntity.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_OptionValueFormatEntity_h_
+#define liblldb_OptionValueFormatEntity_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/FormatEntity.h"
+#include "lldb/Interpreter/OptionValue.h"
+
+namespace lldb_private {
+
+class OptionValueFormatEntity : public OptionValue
+{
+public:
+ OptionValueFormatEntity (const char *default_format);
+
+ virtual
+ ~OptionValueFormatEntity()
+ {
+ }
+
+ //---------------------------------------------------------------------
+ // Virtual subclass pure virtual overrides
+ //---------------------------------------------------------------------
+
+ OptionValue::Type
+ GetType () const override
+ {
+ return eTypeFormatEntity;
+ }
+
+ void
+ DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override;
+
+ Error
+ SetValueFromCString (const char *value,
+ VarSetOperationType op = eVarSetOperationAssign) override;
+
+ bool
+ Clear () override;
+
+ lldb::OptionValueSP
+ DeepCopy () const override;
+
+ size_t
+ AutoComplete (CommandInterpreter &interpreter,
+ const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches) override;
+
+ //---------------------------------------------------------------------
+ // Subclass specific functions
+ //---------------------------------------------------------------------
+
+ FormatEntity::Entry &
+ GetCurrentValue()
+ {
+ return m_current_entry;
+ }
+
+ const FormatEntity::Entry &
+ GetCurrentValue() const
+ {
+ return m_current_entry;
+ }
+
+ void
+ SetCurrentValue (const FormatEntity::Entry &value)
+ {
+ m_current_entry = value;
+ }
+
+ FormatEntity::Entry &
+ GetDefaultValue()
+ {
+ return m_default_entry;
+ }
+
+ const FormatEntity::Entry &
+ GetDefaultValue() const
+ {
+ return m_default_entry;
+ }
+
+
+protected:
+ std::string m_current_format;
+ std::string m_default_format;
+ FormatEntity::Entry m_current_entry;
+ FormatEntity::Entry m_default_entry;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_OptionValueFormatEntity_h_
Modified: lldb/trunk/include/lldb/Interpreter/OptionValueProperties.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/OptionValueProperties.h?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/OptionValueProperties.h (original)
+++ lldb/trunk/include/lldb/Interpreter/OptionValueProperties.h Wed Feb 4 16:00:53 2015
@@ -15,6 +15,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Core/ConstString.h"
+#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Interpreter/Property.h"
@@ -191,6 +192,9 @@ public:
bool
SetPropertyAtIndexAsEnumeration (const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value);
+ const FormatEntity::Entry *
+ GetPropertyAtIndexAsFormatEntity (const ExecutionContext *exe_ctx, uint32_t idx);
+
const RegularExpression *
GetPropertyAtIndexAsOptionValueRegex (const ExecutionContext *exe_ctx, uint32_t idx) const;
Modified: lldb/trunk/include/lldb/Interpreter/OptionValues.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/OptionValues.h?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/OptionValues.h (original)
+++ lldb/trunk/include/lldb/Interpreter/OptionValues.h Wed Feb 4 16:00:53 2015
@@ -21,6 +21,7 @@
#include "lldb/Interpreter/OptionValueFileSpec.h"
#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Interpreter/OptionValueFormat.h"
+#include "lldb/Interpreter/OptionValueFormatEntity.h"
#include "lldb/Interpreter/OptionValuePathMappings.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/OptionValueRegex.h"
Modified: lldb/trunk/include/lldb/Utility/AnsiTerminal.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/AnsiTerminal.h?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Utility/AnsiTerminal.h (original)
+++ lldb/trunk/include/lldb/Utility/AnsiTerminal.h Wed Feb 4 16:00:53 2015
@@ -50,37 +50,6 @@
namespace lldb_utility {
namespace ansi {
- const char *k_escape_start = "\033[";
- const char *k_escape_end = "m";
-
- const char *k_fg_black = "30";
- const char *k_fg_red = "31";
- const char *k_fg_green = "32";
- const char *k_fg_yellow = "33";
- const char *k_fg_blue = "34";
- const char *k_fg_purple = "35";
- const char *k_fg_cyan = "36";
- const char *k_fg_white = "37";
-
- const char *k_bg_black = "40";
- const char *k_bg_red = "41";
- const char *k_bg_green = "42";
- const char *k_bg_yellow = "43";
- const char *k_bg_blue = "44";
- const char *k_bg_purple = "45";
- const char *k_bg_cyan = "46";
- const char *k_bg_white = "47";
-
- const char *k_ctrl_normal = "0";
- const char *k_ctrl_bold = "1";
- const char *k_ctrl_faint = "2";
- const char *k_ctrl_italic = "3";
- const char *k_ctrl_underline = "4";
- const char *k_ctrl_slow_blink = "5";
- const char *k_ctrl_fast_blink = "6";
- const char *k_ctrl_negative = "7";
- const char *k_ctrl_conceal = "8";
- const char *k_ctrl_crossed_out = "9";
inline std::string
FormatAnsiTerminalCodes(const char *format, bool do_color = true)
Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Wed Feb 4 16:00:53 2015
@@ -146,6 +146,7 @@ class OptionValueEnumeration;
class OptionValueFileSpec;
class OptionValueFileSpecList;
class OptionValueFormat;
+class OptionValueFormatEntity;
class OptionValuePathMappings;
class OptionValueProperties;
class OptionValueRegex;
Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Wed Feb 4 16:00:53 2015
@@ -147,6 +147,7 @@
263C4938178B50C40070F12D /* SBModuleSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263C4937178B50C40070F12D /* SBModuleSpec.cpp */; };
263C493A178B50CF0070F12D /* SBModuleSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 263C4939178B50CF0070F12D /* SBModuleSpec.h */; settings = {ATTRIBUTES = (Public, ); }; };
263E949F13661AEA00E7D1CE /* UnwindAssembly-x86.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263E949D13661AE400E7D1CE /* UnwindAssembly-x86.cpp */; };
+ 263FDE601A79A01500E68013 /* FormatEntity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263FDE5F1A79A01500E68013 /* FormatEntity.cpp */; };
2640E19F15DC78FD00F23B50 /* Property.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2640E19E15DC78FD00F23B50 /* Property.cpp */; };
2642FBAE13D003B400ED6808 /* CommunicationKDP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBA813D003B400ED6808 /* CommunicationKDP.cpp */; };
2642FBB013D003B400ED6808 /* ProcessKDP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBAA13D003B400ED6808 /* ProcessKDP.cpp */; };
@@ -183,6 +184,8 @@
26491E3E15E1DB9F00CBFFC2 /* OptionValueRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26491E3D15E1DB9F00CBFFC2 /* OptionValueRegex.cpp */; };
264A12FC1372522000875C42 /* EmulateInstructionARM64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A12FA1372522000875C42 /* EmulateInstructionARM64.cpp */; };
264A1300137252C700875C42 /* ARM64_DWARF_Registers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A12FE137252C700875C42 /* ARM64_DWARF_Registers.cpp */; };
+ 264A58EC1A7DBC8C00A6B1B0 /* OptionValueFormatEntity.h in Headers */ = {isa = PBXBuildFile; fileRef = 264A58EB1A7DBC8C00A6B1B0 /* OptionValueFormatEntity.h */; };
+ 264A58EE1A7DBCAD00A6B1B0 /* OptionValueFormatEntity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A58ED1A7DBCAD00A6B1B0 /* OptionValueFormatEntity.cpp */; };
264A97BF133918BC0017F0BE /* PlatformRemoteGDBServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */; };
264D8D5013661BD7003A368F /* UnwindAssembly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264D8D4F13661BD7003A368F /* UnwindAssembly.cpp */; };
265205A813D3E3F700132FE2 /* RegisterContextKDP_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265205A213D3E3F700132FE2 /* RegisterContextKDP_arm.cpp */; };
@@ -1363,6 +1366,8 @@
263C493B178B61CC0070F12D /* SBModuleSpec.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBModuleSpec.i; sourceTree = "<group>"; };
263E949D13661AE400E7D1CE /* UnwindAssembly-x86.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "UnwindAssembly-x86.cpp"; sourceTree = "<group>"; };
263E949E13661AE400E7D1CE /* UnwindAssembly-x86.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UnwindAssembly-x86.h"; sourceTree = "<group>"; };
+ 263FDE5D1A799F2D00E68013 /* FormatEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FormatEntity.h; path = include/lldb/Core/FormatEntity.h; sourceTree = "<group>"; };
+ 263FDE5F1A79A01500E68013 /* FormatEntity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatEntity.cpp; path = source/Core/FormatEntity.cpp; sourceTree = "<group>"; };
263FEDA5112CC1DA00E4C208 /* ThreadSafeSTLMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSafeSTLMap.h; path = include/lldb/Core/ThreadSafeSTLMap.h; sourceTree = "<group>"; };
2640E19E15DC78FD00F23B50 /* Property.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Property.cpp; path = source/Interpreter/Property.cpp; sourceTree = "<group>"; };
26424E3C125986CB0016D82C /* ValueObjectConstResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectConstResult.cpp; path = source/Core/ValueObjectConstResult.cpp; sourceTree = "<group>"; };
@@ -1412,6 +1417,8 @@
264A12FF137252C700875C42 /* ARM64_DWARF_Registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARM64_DWARF_Registers.h; path = source/Utility/ARM64_DWARF_Registers.h; sourceTree = "<group>"; };
264A43BB1320B3B4005B4096 /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Platform.h; path = include/lldb/Target/Platform.h; sourceTree = "<group>"; };
264A43BD1320BCEB005B4096 /* Platform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Platform.cpp; path = source/Target/Platform.cpp; sourceTree = "<group>"; };
+ 264A58EB1A7DBC8C00A6B1B0 /* OptionValueFormatEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueFormatEntity.h; path = include/lldb/Interpreter/OptionValueFormatEntity.h; sourceTree = "<group>"; };
+ 264A58ED1A7DBCAD00A6B1B0 /* OptionValueFormatEntity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueFormatEntity.cpp; path = source/Interpreter/OptionValueFormatEntity.cpp; sourceTree = "<group>"; };
264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformRemoteGDBServer.cpp; path = "gdb-server/PlatformRemoteGDBServer.cpp"; sourceTree = "<group>"; };
264A97BE133918BC0017F0BE /* PlatformRemoteGDBServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlatformRemoteGDBServer.h; path = "gdb-server/PlatformRemoteGDBServer.h"; sourceTree = "<group>"; };
264AD83711095BA600E0B039 /* CommandObjectLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectLog.cpp; path = source/Commands/CommandObjectLog.cpp; sourceTree = "<group>"; };
@@ -3826,6 +3833,8 @@
26BC7D6310F1B77400F91463 /* FileSpecList.h */,
26BC7E7B10F1B85900F91463 /* FileSpecList.cpp */,
26BC7D6410F1B77400F91463 /* Flags.h */,
+ 263FDE5D1A799F2D00E68013 /* FormatEntity.h */,
+ 263FDE5F1A79A01500E68013 /* FormatEntity.cpp */,
26F7305F139D8FC900FD51C7 /* History.h */,
26F73061139D8FDB00FD51C7 /* History.cpp */,
260A63161861008E00FECF8E /* IOHandler.h */,
@@ -4259,6 +4268,8 @@
260CC64215D0440D002BF2E0 /* OptionValueFileSpecLIst.cpp */,
260CC62915D04377002BF2E0 /* OptionValueFormat.h */,
260CC64315D0440D002BF2E0 /* OptionValueFormat.cpp */,
+ 264A58EB1A7DBC8C00A6B1B0 /* OptionValueFormatEntity.h */,
+ 264A58ED1A7DBCAD00A6B1B0 /* OptionValueFormatEntity.cpp */,
26DAED5F15D327A200E15819 /* OptionValuePathMappings.h */,
26DAED6215D327C200E15819 /* OptionValuePathMappings.cpp */,
260CC62415D04377002BF2E0 /* OptionValueProperties.h */,
@@ -5133,6 +5144,7 @@
AF77E0A21A033D360096C0EA /* RegisterContextFreeBSD_powerpc.h in Headers */,
260CC63715D04377002BF2E0 /* OptionValueSInt64.h in Headers */,
AF061F8C182C980000B6A19C /* HistoryUnwind.h in Headers */,
+ 264A58EC1A7DBC8C00A6B1B0 /* OptionValueFormatEntity.h in Headers */,
260CC63815D04377002BF2E0 /* OptionValueString.h in Headers */,
260CC63915D04377002BF2E0 /* OptionValueUInt64.h in Headers */,
AF0F6E511739A76D009180FE /* RegisterContextKDP_arm64.h in Headers */,
@@ -5745,6 +5757,7 @@
AF254E31170CCC33007AE5C9 /* PlatformDarwinKernel.cpp in Sources */,
2689004813353E0400698AC0 /* RegularExpression.cpp in Sources */,
2689004913353E0400698AC0 /* Scalar.cpp in Sources */,
+ 263FDE601A79A01500E68013 /* FormatEntity.cpp in Sources */,
2689004A13353E0400698AC0 /* SearchFilter.cpp in Sources */,
2689004B13353E0400698AC0 /* Section.cpp in Sources */,
2689004C13353E0400698AC0 /* SourceManager.cpp in Sources */,
@@ -5770,6 +5783,7 @@
2689005A13353E0400698AC0 /* ValueObjectList.cpp in Sources */,
2689005B13353E0400698AC0 /* ValueObjectRegister.cpp in Sources */,
2689005C13353E0400698AC0 /* ValueObjectVariable.cpp in Sources */,
+ 264A58EE1A7DBCAD00A6B1B0 /* OptionValueFormatEntity.cpp in Sources */,
8C2D6A53197A1EAF006989C9 /* MemoryHistory.cpp in Sources */,
2689005D13353E0400698AC0 /* VMRange.cpp in Sources */,
2689005E13353E0E00698AC0 /* ClangASTSource.cpp in Sources */,
Modified: lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme (original)
+++ lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme Wed Feb 4 16:00:53 2015
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0600"
- version = "1.3">
+ version = "1.8">
<BuildAction
parallelizeBuildables = "NO"
buildImplicitDependencies = "YES">
@@ -102,6 +102,16 @@
ReferencedContainer = "container:lldb.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
+ <CommandLineArguments>
+ <CommandLineArgument
+ argument = "/Volumes/work/gclayton/Documents/src/args/a.out -o 'b main' -o r"
+ isEnabled = "YES">
+ </CommandLineArgument>
+ <CommandLineArgument
+ argument = "-x"
+ isEnabled = "YES">
+ </CommandLineArgument>
+ </CommandLineArguments>
<EnvironmentVariables>
<EnvironmentVariable
key = "LLDB_LAUNCH_FLAG_DISABLE_ASLR"
Modified: lldb/trunk/source/API/SBInstruction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBInstruction.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/API/SBInstruction.cpp (original)
+++ lldb/trunk/source/API/SBInstruction.cpp Wed Feb 4 16:00:53 2015
@@ -178,8 +178,9 @@ SBInstruction::GetDescription (lldb::SBS
module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
// Use the "ref()" instead of the "get()" accessor in case the SBStream
// didn't have a stream already created, one will get created...
- const char *disassemble_format = "${addr-file-or-load}: ";
- m_opaque_sp->Dump (&s.ref(), 0, true, false, NULL, &sc, NULL, disassemble_format);
+ FormatEntity::Entry format;
+ FormatEntity::Parse("${addr}: ", format);
+ m_opaque_sp->Dump (&s.ref(), 0, true, false, NULL, &sc, NULL, &format);
return true;
}
return false;
@@ -199,8 +200,9 @@ SBInstruction::Print (FILE *out)
if (module_sp)
module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
StreamFile out_stream (out, false);
- const char *disassemble_format = "${addr-file-or-load}: ";
- m_opaque_sp->Dump (&out_stream, 0, true, false, NULL, &sc, NULL, disassemble_format);
+ FormatEntity::Entry format;
+ FormatEntity::Parse("${addr}: ", format);
+ m_opaque_sp->Dump (&out_stream, 0, true, false, NULL, &sc, NULL, &format);
}
}
Modified: lldb/trunk/source/API/SBInstructionList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBInstructionList.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/API/SBInstructionList.cpp (original)
+++ lldb/trunk/source/API/SBInstructionList.cpp Wed Feb 4 16:00:53 2015
@@ -102,7 +102,8 @@ SBInstructionList::GetDescription (lldb:
// exist already inside description...
Stream &sref = description.ref();
const uint32_t max_opcode_byte_size = m_opaque_sp->GetInstructionList().GetMaxOpcocdeByteSize();
- const char *disassemble_format = "${addr-file-or-load}: ";
+ FormatEntity::Entry format;
+ FormatEntity::Parse("${addr}: ", format);
SymbolContext sc;
SymbolContext prev_sc;
for (size_t i=0; i<num_instructions; ++i)
@@ -119,7 +120,7 @@ SBInstructionList::GetDescription (lldb:
module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
}
- inst->Dump (&sref, max_opcode_byte_size, true, false, NULL, &sc, &prev_sc, disassemble_format);
+ inst->Dump (&sref, max_opcode_byte_size, true, false, NULL, &sc, &prev_sc, &format);
sref.EOL();
}
return true;
Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Wed Feb 4 16:00:53 2015
@@ -18,6 +18,7 @@
#include "llvm/ADT/StringRef.h"
#include "lldb/lldb-private.h"
+#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegisterValue.h"
@@ -130,24 +131,23 @@ g_language_enumerators[] =
static PropertyDefinition
g_properties[] =
{
-{ "auto-confirm", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." },
-{ "disassembly-format", OptionValue::eTypeString , true, 0 , DEFAULT_DISASSEMBLY_FORMAT, NULL, "The default disassembly format string to use when disassembling instruction sequences." },
-{ "frame-format", OptionValue::eTypeString , true, 0 , DEFAULT_FRAME_FORMAT, NULL, "The default frame format string to use when displaying stack frame information for threads." },
-{ "notify-void", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." },
-{ "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." },
-{ "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." },
-{ "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." },
-{ "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoSource, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." },
-{ "stop-line-count-after", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come after the current source line when displaying a stopped context." },
-{ "stop-line-count-before", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come before the current source line when displaying a stopped context." },
-{ "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." },
-{ "thread-format", OptionValue::eTypeString , true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." },
-{ "use-external-editor", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Whether to use an external editor or not." },
-{ "use-color", OptionValue::eTypeBoolean, true, true , NULL, NULL, "Whether to use Ansi color codes or not." },
-{ "auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." },
-{ "escape-non-printables", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will automatically escape non-printable and escape characters when formatting strings." },
-
- { NULL, OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL }
+{ "auto-confirm", OptionValue::eTypeBoolean , true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." },
+{ "disassembly-format", OptionValue::eTypeFormatEntity, true, 0 , DEFAULT_DISASSEMBLY_FORMAT, NULL, "The default disassembly format string to use when disassembling instruction sequences." },
+{ "frame-format", OptionValue::eTypeFormatEntity, true, 0 , DEFAULT_FRAME_FORMAT, NULL, "The default frame format string to use when displaying stack frame information for threads." },
+{ "notify-void", OptionValue::eTypeBoolean , true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." },
+{ "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." },
+{ "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." },
+{ "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." },
+{ "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoSource, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." },
+{ "stop-line-count-after", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come after the current source line when displaying a stopped context." },
+{ "stop-line-count-before", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come before the current source line when displaying a stopped context." },
+{ "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." },
+{ "thread-format", OptionValue::eTypeFormatEntity, true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." },
+{ "use-external-editor", OptionValue::eTypeBoolean , true, false, NULL, NULL, "Whether to use an external editor or not." },
+{ "use-color", OptionValue::eTypeBoolean , true, true , NULL, NULL, "Whether to use Ansi color codes or not." },
+{ "auto-one-line-summaries", OptionValue::eTypeBoolean , true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." },
+{ "escape-non-printables", OptionValue::eTypeBoolean , true, true, NULL, NULL, "If true, LLDB will automatically escape non-printable and escape characters when formatting strings." },
+{ NULL, OptionValue::eTypeInvalid , true, 0 , NULL, NULL, NULL }
};
enum
@@ -242,18 +242,18 @@ Debugger::GetAutoConfirm () const
return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
}
-const char *
+const FormatEntity::Entry *
Debugger::GetDisassemblyFormat() const
{
const uint32_t idx = ePropertyDisassemblyFormat;
- return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value);
+ return m_collection_sp->GetPropertyAtIndexAsFormatEntity(NULL, idx);
}
-const char *
+const FormatEntity::Entry *
Debugger::GetFrameFormat() const
{
const uint32_t idx = ePropertyFrameFormat;
- return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value);
+ return m_collection_sp->GetPropertyAtIndexAsFormatEntity(NULL, idx);
}
bool
@@ -282,11 +282,11 @@ Debugger::SetPrompt(const char *p)
GetCommandInterpreter().UpdatePrompt(new_prompt);
}
-const char *
+const FormatEntity::Entry *
Debugger::GetThreadFormat() const
{
const uint32_t idx = ePropertyThreadFormat;
- return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value);
+ return m_collection_sp->GetPropertyAtIndexAsFormatEntity(NULL, idx);
}
lldb::ScriptLanguage
@@ -1226,1691 +1226,25 @@ TestPromptFormats (StackFrame *frame)
}
#endif
-static bool
-ScanFormatDescriptor (const char* var_name_begin,
- const char* var_name_end,
- const char** var_name_final,
- const char** percent_position,
- Format* custom_format,
- ValueObject::ValueObjectRepresentationStyle* val_obj_display)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
- *percent_position = ::strchr(var_name_begin,'%');
- if (!*percent_position || *percent_position > var_name_end)
- {
- if (log)
- log->Printf("[ScanFormatDescriptor] no format descriptor in string, skipping");
- *var_name_final = var_name_end;
- }
- else
- {
- *var_name_final = *percent_position;
- std::string format_name(*var_name_final+1, var_name_end-*var_name_final-1);
- if (log)
- log->Printf("[ScanFormatDescriptor] parsing %s as a format descriptor", format_name.c_str());
- if ( !FormatManager::GetFormatFromCString(format_name.c_str(),
- true,
- *custom_format) )
- {
- if (log)
- log->Printf("[ScanFormatDescriptor] %s is an unknown format", format_name.c_str());
-
- switch (format_name.front())
- {
- case '@': // if this is an @ sign, print ObjC description
- *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific;
- break;
- case 'V': // if this is a V, print the value using the default format
- *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
- break;
- case 'L': // if this is an L, print the location of the value
- *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation;
- break;
- case 'S': // if this is an S, print the summary after all
- *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary;
- break;
- case '#': // if this is a '#', print the number of children
- *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount;
- break;
- case 'T': // if this is a 'T', print the type
- *val_obj_display = ValueObject::eValueObjectRepresentationStyleType;
- break;
- case 'N': // if this is a 'N', print the name
- *val_obj_display = ValueObject::eValueObjectRepresentationStyleName;
- break;
- case '>': // if this is a '>', print the name
- *val_obj_display = ValueObject::eValueObjectRepresentationStyleExpressionPath;
- break;
- default:
- if (log)
- log->Printf("ScanFormatDescriptor] %s is an error, leaving the previous value alone", format_name.c_str());
- break;
- }
- }
- // a good custom format tells us to print the value using it
- else
- {
- if (log)
- log->Printf("[ScanFormatDescriptor] will display value for this VO");
- *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
- }
- }
- if (log)
- log->Printf("[ScanFormatDescriptor] final format description outcome: custom_format = %d, val_obj_display = %d",
- *custom_format,
- *val_obj_display);
- return true;
-}
-
-static bool
-ScanBracketedRange (const char* var_name_begin,
- const char* var_name_end,
- const char* var_name_final,
- const char** open_bracket_position,
- const char** separator_position,
- const char** close_bracket_position,
- const char** var_name_final_if_array_range,
- int64_t* index_lower,
- int64_t* index_higher)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
- *open_bracket_position = ::strchr(var_name_begin,'[');
- if (*open_bracket_position && *open_bracket_position < var_name_final)
- {
- *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield
- *close_bracket_position = ::strchr(*open_bracket_position,']');
- // as usual, we assume that [] will come before %
- //printf("trying to expand a []\n");
- *var_name_final_if_array_range = *open_bracket_position;
- if (*close_bracket_position - *open_bracket_position == 1)
- {
- if (log)
- log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
- *index_lower = 0;
- }
- else if (*separator_position == NULL || *separator_position > var_name_end)
- {
- char *end = NULL;
- *index_lower = ::strtoul (*open_bracket_position+1, &end, 0);
- *index_higher = *index_lower;
- if (log)
- log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", *index_lower);
- }
- else if (*close_bracket_position && *close_bracket_position < var_name_end)
- {
- char *end = NULL;
- *index_lower = ::strtoul (*open_bracket_position+1, &end, 0);
- *index_higher = ::strtoul (*separator_position+1, &end, 0);
- if (log)
- log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", *index_lower, *index_higher);
- }
- else
- {
- if (log)
- log->Printf("[ScanBracketedRange] expression is erroneous, cannot extract indices out of it");
- return false;
- }
- if (*index_lower > *index_higher && *index_higher > 0)
- {
- if (log)
- log->Printf("[ScanBracketedRange] swapping indices");
- int64_t temp = *index_lower;
- *index_lower = *index_higher;
- *index_higher = temp;
- }
- }
- else if (log)
- log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
- return true;
-}
-
-template <typename T>
-static bool RunScriptFormatKeyword(Stream &s, ScriptInterpreter *script_interpreter, T t, const std::string& script_name)
-{
- if (script_interpreter)
- {
- Error script_error;
- std::string script_output;
-
- if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), t, script_output, script_error) && script_error.Success())
- {
- s.Printf("%s", script_output.c_str());
- return true;
- }
- else
- {
- s.Printf("<error: %s>",script_error.AsCString());
- }
- }
- return false;
-}
-
-static ValueObjectSP
-ExpandIndexedExpression (ValueObject* valobj,
- size_t index,
- StackFrame* frame,
- bool deref_pointer)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
- const char* ptr_deref_format = "[%d]";
- std::string ptr_deref_buffer(10,0);
- ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index);
- if (log)
- log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str());
- const char* first_unparsed;
- ValueObject::GetValueForExpressionPathOptions options;
- ValueObject::ExpressionPathEndResultType final_value_type;
- ValueObject::ExpressionPathScanEndReason reason_to_stop;
- ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing);
- ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(),
- &first_unparsed,
- &reason_to_stop,
- &final_value_type,
- options,
- &what_next);
- if (!item)
- {
- if (log)
- log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d,"
- " final_value_type %d",
- first_unparsed, reason_to_stop, final_value_type);
- }
- else
- {
- if (log)
- log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d,"
- " final_value_type %d",
- first_unparsed, reason_to_stop, final_value_type);
- }
- return item;
-}
-
-static inline bool
-IsToken(const char *var_name_begin, const char *var)
-{
- return (::strncmp (var_name_begin, var, strlen(var)) == 0);
-}
-
-static bool
-IsTokenWithFormat(const char *var_name_begin, const char *var, std::string &format, const char *default_format,
- const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr)
-{
- int var_len = strlen(var);
- if (::strncmp (var_name_begin, var, var_len) == 0)
- {
- var_name_begin += var_len;
- if (*var_name_begin == '}')
- {
- format = default_format;
- return true;
- }
- else if (*var_name_begin == '%')
- {
- // Allow format specifiers: x|X|u with optional width specifiers.
- // ${thread.id%x} ; hex
- // ${thread.id%X} ; uppercase hex
- // ${thread.id%u} ; unsigned decimal
- // ${thread.id%8.8X} ; width.precision + specifier
- // ${thread.id%tid} ; unsigned on FreeBSD/Linux, otherwise default_format (0x%4.4x for thread.id)
- int dot_count = 0;
- const char *specifier = NULL;
- int width_precision_length = 0;
- const char *width_precision = ++var_name_begin;
- while (isdigit(*var_name_begin) || *var_name_begin == '.')
- {
- dot_count += (*var_name_begin == '.');
- if (dot_count > 1)
- break;
- var_name_begin++;
- width_precision_length++;
- }
-
- if (IsToken (var_name_begin, "tid}"))
- {
- Target *target = Target::GetTargetFromContexts (exe_ctx_ptr, sc_ptr);
- if (target)
- {
- ArchSpec arch (target->GetArchitecture ());
- llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS;
- if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux))
- specifier = PRIu64;
- }
- if (!specifier)
- {
- format = default_format;
- return true;
- }
- }
- else if (IsToken (var_name_begin, "x}"))
- specifier = PRIx64;
- else if (IsToken (var_name_begin, "X}"))
- specifier = PRIX64;
- else if (IsToken (var_name_begin, "u}"))
- specifier = PRIu64;
-
- if (specifier)
- {
- format = "%";
- if (width_precision_length)
- format += std::string(width_precision, width_precision_length);
- format += specifier;
- return true;
- }
- }
- }
- return false;
-}
-
-// Find information for the "thread.info.*" specifiers in a format string
-static bool
-FormatThreadExtendedInfoRecurse
-(
- const char *var_name_begin,
- StructuredData::ObjectSP thread_info_dictionary,
- const SymbolContext *sc,
- const ExecutionContext *exe_ctx,
- Stream &s
-)
-{
- bool var_success = false;
- std::string token_format;
-
- llvm::StringRef var_name(var_name_begin);
- size_t percent_idx = var_name.find('%');
- size_t close_curly_idx = var_name.find('}');
- llvm::StringRef path = var_name;
- llvm::StringRef formatter = var_name;
-
- // 'path' will be the dot separated list of objects to transverse up until we hit
- // a close curly brace, a percent sign, or an end of string.
- if (percent_idx != llvm::StringRef::npos || close_curly_idx != llvm::StringRef::npos)
- {
- if (percent_idx != llvm::StringRef::npos && close_curly_idx != llvm::StringRef::npos)
- {
- if (percent_idx < close_curly_idx)
- {
- path = var_name.slice(0, percent_idx);
- formatter = var_name.substr (percent_idx);
- }
- else
- {
- path = var_name.slice(0, close_curly_idx);
- formatter = var_name.substr (close_curly_idx);
- }
- }
- else if (percent_idx != llvm::StringRef::npos)
- {
- path = var_name.slice(0, percent_idx);
- formatter = var_name.substr (percent_idx);
- }
- else if (close_curly_idx != llvm::StringRef::npos)
- {
- path = var_name.slice(0, close_curly_idx);
- formatter = var_name.substr (close_curly_idx);
- }
- }
-
- StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path);
-
- if (value.get())
- {
- if (value->GetType() == StructuredData::Type::eTypeInteger)
- {
- if (IsTokenWithFormat (formatter.str().c_str(), "", token_format, "0x%4.4" PRIx64, exe_ctx, sc))
- {
- s.Printf(token_format.c_str(), value->GetAsInteger()->GetValue());
- var_success = true;
- }
- }
- else if (value->GetType() == StructuredData::Type::eTypeFloat)
- {
- s.Printf ("%f", value->GetAsFloat()->GetValue());
- var_success = true;
- }
- else if (value->GetType() == StructuredData::Type::eTypeString)
- {
- s.Printf("%s", value->GetAsString()->GetValue().c_str());
- var_success = true;
- }
- else if (value->GetType() == StructuredData::Type::eTypeArray)
- {
- if (value->GetAsArray()->GetSize() > 0)
- {
- s.Printf ("%zu", value->GetAsArray()->GetSize());
- var_success = true;
- }
- }
- else if (value->GetType() == StructuredData::Type::eTypeDictionary)
- {
- s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
- var_success = true;
- }
- }
-
- return var_success;
-}
-
-
-static bool
-FormatPromptRecurse
-(
- const char *format,
- const SymbolContext *sc,
- const ExecutionContext *exe_ctx,
- const Address *addr,
- Stream &s,
- const char **end,
- ValueObject* valobj,
- bool function_changed,
- bool initial_function
-)
-{
- ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers
- bool success = true;
- const char *p;
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
-
- for (p = format; *p != '\0'; ++p)
- {
- if (realvalobj)
- {
- valobj = realvalobj;
- realvalobj = NULL;
- }
- size_t non_special_chars = ::strcspn (p, "${}\\");
- if (non_special_chars > 0)
- {
- if (success)
- s.Write (p, non_special_chars);
- p += non_special_chars;
- }
-
- if (*p == '\0')
- {
- break;
- }
- else if (*p == '{')
- {
- // Start a new scope that must have everything it needs if it is to
- // to make it into the final output stream "s". If you want to make
- // a format that only prints out the function or symbol name if there
- // is one in the symbol context you can use:
- // "{function =${function.name}}"
- // The first '{' starts a new scope that end with the matching '}' at
- // the end of the string. The contents "function =${function.name}"
- // will then be evaluated and only be output if there is a function
- // or symbol with a valid name.
- StreamString sub_strm;
-
- ++p; // Skip the '{'
-
- if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj, function_changed, initial_function))
- {
- // The stream had all it needed
- s.Write(sub_strm.GetData(), sub_strm.GetSize());
- }
- if (*p != '}')
- {
- success = false;
- break;
- }
- }
- else if (*p == '}')
- {
- // End of a enclosing scope
- break;
- }
- else if (*p == '$')
- {
- // We have a prompt variable to print
- ++p;
- if (*p == '{')
- {
- ++p;
- const char *var_name_begin = p;
- const char *var_name_end = ::strchr (p, '}');
-
- if (var_name_end && var_name_begin < var_name_end)
- {
- // if we have already failed to parse, skip this variable
- if (success)
- {
- const char *cstr = NULL;
- std::string token_format;
- Address format_addr;
-
- // normally "addr" means print a raw address but
- // "file-addr-or-load-addr" means print a module + file addr if there's no load addr
- bool print_file_addr_or_load_addr = false;
- bool addr_offset_concrete_func_only = false;
- bool addr_offset_print_with_no_padding = false;
- bool calculate_format_addr_function_offset = false;
- // Set reg_kind and reg_num to invalid values
- RegisterKind reg_kind = kNumRegisterKinds;
- uint32_t reg_num = LLDB_INVALID_REGNUM;
- FileSpec format_file_spec;
- const RegisterInfo *reg_info = NULL;
- RegisterContext *reg_ctx = NULL;
- bool do_deref_pointer = false;
- ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
- ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain;
-
- // Each variable must set success to true below...
- bool var_success = false;
- switch (var_name_begin[0])
- {
- case '*':
- case 'v':
- case 's':
- {
- if (!valobj)
- break;
-
- if (log)
- log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin);
-
- // check for *var and *svar
- if (*var_name_begin == '*')
- {
- do_deref_pointer = true;
- var_name_begin++;
- if (log)
- log->Printf("[Debugger::FormatPrompt] found a deref, new string is: %s",var_name_begin);
- }
-
- if (*var_name_begin == 's')
- {
- if (!valobj->IsSynthetic())
- valobj = valobj->GetSyntheticValue().get();
- if (!valobj)
- break;
- var_name_begin++;
- if (log)
- log->Printf("[Debugger::FormatPrompt] found a synthetic, new string is: %s",var_name_begin);
- }
-
- // should be a 'v' by now
- if (*var_name_begin != 'v')
- break;
-
- if (log)
- log->Printf("[Debugger::FormatPrompt] string I am working with: %s",var_name_begin);
-
- ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ?
- ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing);
- ValueObject::GetValueForExpressionPathOptions options;
- options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren();
- ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary;
- ValueObject* target = NULL;
- Format custom_format = eFormatInvalid;
- const char* var_name_final = NULL;
- const char* var_name_final_if_array_range = NULL;
- const char* close_bracket_position = NULL;
- int64_t index_lower = -1;
- int64_t index_higher = -1;
- bool is_array_range = false;
- const char* first_unparsed;
- bool was_plain_var = false;
- bool was_var_format = false;
- bool was_var_indexed = false;
-
- if (!valobj) break;
- // simplest case ${var}, just print valobj's value
- if (IsToken (var_name_begin, "var}"))
- {
- was_plain_var = true;
- target = valobj;
- val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
- }
- else if (IsToken (var_name_begin, "var.script:"))
- {
- var_name_begin += ::strlen("var.script:");
- std::string script_name(var_name_begin,var_name_end);
- ScriptInterpreter* script_interpreter = valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
- if (RunScriptFormatKeyword (s, script_interpreter, valobj, script_name))
- var_success = true;
- break;
- }
- else if (IsToken (var_name_begin,"var%"))
- {
- was_var_format = true;
- // this is a variable with some custom format applied to it
- const char* percent_position;
- target = valobj;
- val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
- ScanFormatDescriptor (var_name_begin,
- var_name_end,
- &var_name_final,
- &percent_position,
- &custom_format,
- &val_obj_display);
- }
- // this is ${var.something} or multiple .something nested
- else if (IsToken (var_name_begin, "var"))
- {
- if (IsToken (var_name_begin, "var["))
- was_var_indexed = true;
- const char* percent_position;
- ScanFormatDescriptor (var_name_begin,
- var_name_end,
- &var_name_final,
- &percent_position,
- &custom_format,
- &val_obj_display);
-
- const char* open_bracket_position;
- const char* separator_position;
- ScanBracketedRange (var_name_begin,
- var_name_end,
- var_name_final,
- &open_bracket_position,
- &separator_position,
- &close_bracket_position,
- &var_name_final_if_array_range,
- &index_lower,
- &index_higher);
-
- Error error;
-
- std::string expr_path(var_name_final-var_name_begin-1,0);
- memcpy(&expr_path[0], var_name_begin+3,var_name_final-var_name_begin-3);
-
- if (log)
- log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str());
-
- target = valobj->GetValueForExpressionPath(expr_path.c_str(),
- &first_unparsed,
- &reason_to_stop,
- &final_value_type,
- options,
- &what_next).get();
-
- if (!target)
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d,"
- " final_value_type %d",
- first_unparsed, reason_to_stop, final_value_type);
- break;
- }
- else
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d,"
- " final_value_type %d",
- first_unparsed, reason_to_stop, final_value_type);
- target = target->GetQualifiedRepresentationIfAvailable(target->GetDynamicValueType(), true).get();
- }
- }
- else
- break;
-
- is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange ||
- final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange);
-
- do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference);
-
- if (do_deref_pointer && !is_array_range)
- {
- // I have not deref-ed yet, let's do it
- // this happens when we are not going through GetValueForVariableExpressionPath
- // to get to the target ValueObject
- Error error;
- target = target->Dereference(error).get();
- if (error.Fail())
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \
- break;
- }
- do_deref_pointer = false;
- }
-
- if (!target)
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression");
- break;
- }
-
- // we do not want to use the summary for a bitfield of type T:n
- // if we were originally dealing with just a T - that would get
- // us into an endless recursion
- if (target->IsBitfield() && was_var_indexed)
- {
- // TODO: check for a (T:n)-specific summary - we should still obey that
- StreamString bitfield_name;
- bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize());
- lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false));
- if (!DataVisualization::GetSummaryForType(type_sp))
- val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
- }
-
- // TODO use flags for these
- const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL);
- bool is_array = (type_info_flags & eTypeIsArray) != 0;
- bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
- bool is_aggregate = target->GetClangType().IsAggregateType();
-
- if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions
- {
- StreamString str_temp;
- if (log)
- log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range");
-
- if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format))
- {
- // try to use the special cases
- var_success = target->DumpPrintableRepresentation(str_temp,
- val_obj_display,
- custom_format);
- if (log)
- log->Printf("[Debugger::FormatPrompt] special cases did%s match", var_success ? "" : "n't");
-
- // should not happen
- if (var_success)
- s << str_temp.GetData();
- var_success = true;
- break;
- }
- else
- {
- if (was_plain_var) // if ${var}
- {
- s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
- }
- else if (is_pointer) // if pointer, value is the address stored
- {
- target->DumpPrintableRepresentation (s,
- val_obj_display,
- custom_format,
- ValueObject::ePrintableRepresentationSpecialCasesDisable);
- }
- var_success = true;
- break;
- }
- }
-
- // if directly trying to print ${var}, and this is an aggregate, display a nice
- // type @ location message
- if (is_aggregate && was_plain_var)
- {
- s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
- var_success = true;
- break;
- }
-
- // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it
- if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue)))
- {
- s << "<invalid use of aggregate type>";
- var_success = true;
- break;
- }
-
- if (!is_array_range)
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output");
- var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format);
- }
- else
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] checking if I can handle as array");
- if (!is_array && !is_pointer)
- break;
- if (log)
- log->Printf("[Debugger::FormatPrompt] handle as array");
- const char* special_directions = NULL;
- StreamString special_directions_writer;
- if (close_bracket_position && (var_name_end-close_bracket_position > 1))
- {
- ConstString additional_data;
- additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1);
- special_directions_writer.Printf("${%svar%s}",
- do_deref_pointer ? "*" : "",
- additional_data.GetCString());
- special_directions = special_directions_writer.GetData();
- }
-
- // let us display items index_lower thru index_higher of this array
- s.PutChar('[');
- var_success = true;
-
- if (index_higher < 0)
- index_higher = valobj->GetNumChildren() - 1;
-
- uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
-
- for (;index_lower<=index_higher;index_lower++)
- {
- ValueObject* item = ExpandIndexedExpression (target,
- index_lower,
- exe_ctx->GetFramePtr(),
- false).get();
-
- if (!item)
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index_lower);
- }
- else
- {
- if (log)
- log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions);
- }
-
- if (!special_directions)
- var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format);
- else
- var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL, item, function_changed, initial_function);
-
- if (--max_num_children == 0)
- {
- s.PutCString(", ...");
- break;
- }
-
- if (index_lower < index_higher)
- s.PutChar(',');
- }
- s.PutChar(']');
- }
- }
- break;
- case 'a':
- if (IsToken (var_name_begin, "addr-file-or-load}"))
- {
- print_file_addr_or_load_addr = true;
- }
- if (IsToken (var_name_begin, "addr}")
- || IsToken (var_name_begin, "addr-file-or-load}"))
- {
- if (addr && addr->IsValid())
- {
- var_success = true;
- format_addr = *addr;
- }
- }
- break;
-
- case 'p':
- if (IsToken (var_name_begin, "process."))
- {
- if (exe_ctx)
- {
- Process *process = exe_ctx->GetProcessPtr();
- if (process)
- {
- var_name_begin += ::strlen ("process.");
- if (IsTokenWithFormat (var_name_begin, "id", token_format, "%" PRIu64, exe_ctx, sc))
- {
- s.Printf(token_format.c_str(), process->GetID());
- var_success = true;
- }
- else if ((IsToken (var_name_begin, "name}")) ||
- (IsToken (var_name_begin, "file.basename}")) ||
- (IsToken (var_name_begin, "file.fullpath}")))
- {
- Module *exe_module = process->GetTarget().GetExecutableModulePointer();
- if (exe_module)
- {
- if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f')
- {
- format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename();
- var_success = (bool)format_file_spec;
- }
- else
- {
- format_file_spec = exe_module->GetFileSpec();
- var_success = (bool)format_file_spec;
- }
- }
- }
- else if (IsToken (var_name_begin, "script:"))
- {
- var_name_begin += ::strlen("script:");
- std::string script_name(var_name_begin,var_name_end);
- ScriptInterpreter* script_interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
- if (RunScriptFormatKeyword (s, script_interpreter, process, script_name))
- var_success = true;
- }
- }
- }
- }
- break;
-
- case 't':
- if (IsToken (var_name_begin, "thread."))
- {
- if (exe_ctx)
- {
- Thread *thread = exe_ctx->GetThreadPtr();
- if (thread)
- {
- var_name_begin += ::strlen ("thread.");
- if (IsTokenWithFormat (var_name_begin, "id", token_format, "0x%4.4" PRIx64, exe_ctx, sc))
- {
- s.Printf(token_format.c_str(), thread->GetID());
- var_success = true;
- }
- else if (IsTokenWithFormat (var_name_begin, "protocol_id", token_format, "0x%4.4" PRIx64, exe_ctx, sc))
- {
- s.Printf(token_format.c_str(), thread->GetProtocolID());
- var_success = true;
- }
- else if (IsTokenWithFormat (var_name_begin, "index", token_format, "%" PRIu64, exe_ctx, sc))
- {
- s.Printf(token_format.c_str(), (uint64_t)thread->GetIndexID());
- var_success = true;
- }
- else if (IsToken (var_name_begin, "name}"))
- {
- cstr = thread->GetName();
- var_success = cstr && cstr[0];
- if (var_success)
- s.PutCString(cstr);
- }
- else if (IsToken (var_name_begin, "queue}"))
- {
- cstr = thread->GetQueueName();
- var_success = cstr && cstr[0];
- if (var_success)
- s.PutCString(cstr);
- }
- else if (IsToken (var_name_begin, "stop-reason}"))
- {
- StopInfoSP stop_info_sp = thread->GetStopInfo ();
- if (stop_info_sp && stop_info_sp->IsValid())
- {
- cstr = stop_info_sp->GetDescription();
- if (cstr && cstr[0])
- {
- s.PutCString(cstr);
- var_success = true;
- }
- }
- }
- else if (IsToken (var_name_begin, "return-value}"))
- {
- StopInfoSP stop_info_sp = thread->GetStopInfo ();
- if (stop_info_sp && stop_info_sp->IsValid())
- {
- ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
- if (return_valobj_sp)
- {
- return_valobj_sp->Dump(s);
- var_success = true;
- }
- }
- }
- else if (IsToken (var_name_begin, "completed-expression}"))
- {
- StopInfoSP stop_info_sp = thread->GetStopInfo ();
- if (stop_info_sp && stop_info_sp->IsValid())
- {
- ClangExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp);
- if (expression_var_sp && expression_var_sp->GetValueObject())
- {
- expression_var_sp->GetValueObject()->Dump(s);
- var_success = true;
- }
- }
- }
- else if (IsToken (var_name_begin, "script:"))
- {
- var_name_begin += ::strlen("script:");
- std::string script_name(var_name_begin,var_name_end);
- ScriptInterpreter* script_interpreter = thread->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
- if (RunScriptFormatKeyword (s, script_interpreter, thread, script_name))
- var_success = true;
- }
- else if (IsToken (var_name_begin, "info."))
- {
- var_name_begin += ::strlen("info.");
- StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
- if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary)
- {
- var_success = FormatThreadExtendedInfoRecurse (var_name_begin, object_sp, sc, exe_ctx, s);
- }
- }
- }
- }
- }
- else if (IsToken (var_name_begin, "target."))
- {
- // TODO: hookup properties
-// if (!target_properties_sp)
-// {
-// Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
-// if (target)
-// target_properties_sp = target->GetProperties();
-// }
-//
-// if (target_properties_sp)
-// {
-// var_name_begin += ::strlen ("target.");
-// const char *end_property = strchr(var_name_begin, '}');
-// if (end_property)
-// {
-// ConstString property_name(var_name_begin, end_property - var_name_begin);
-// std::string property_value (target_properties_sp->GetPropertyValue(property_name));
-// if (!property_value.empty())
-// {
-// s.PutCString (property_value.c_str());
-// var_success = true;
-// }
-// }
-// }
- Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
- if (target)
- {
- var_name_begin += ::strlen ("target.");
- if (IsToken (var_name_begin, "arch}"))
- {
- ArchSpec arch (target->GetArchitecture ());
- if (arch.IsValid())
- {
- s.PutCString (arch.GetArchitectureName());
- var_success = true;
- }
- }
- else if (IsToken (var_name_begin, "script:"))
- {
- var_name_begin += ::strlen("script:");
- std::string script_name(var_name_begin,var_name_end);
- ScriptInterpreter* script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
- if (RunScriptFormatKeyword (s, script_interpreter, target, script_name))
- var_success = true;
- }
- }
- }
- break;
-
- case 'm':
- if (IsToken (var_name_begin, "module."))
- {
- if (sc && sc->module_sp.get())
- {
- Module *module = sc->module_sp.get();
- var_name_begin += ::strlen ("module.");
-
- if (IsToken (var_name_begin, "file."))
- {
- if (module->GetFileSpec())
- {
- var_name_begin += ::strlen ("file.");
-
- if (IsToken (var_name_begin, "basename}"))
- {
- format_file_spec.GetFilename() = module->GetFileSpec().GetFilename();
- var_success = (bool)format_file_spec;
- }
- else if (IsToken (var_name_begin, "fullpath}"))
- {
- format_file_spec = module->GetFileSpec();
- var_success = (bool)format_file_spec;
- }
- }
- }
- }
- }
- break;
-
-
- case 'f':
- if (IsToken (var_name_begin, "file."))
- {
- if (sc && sc->comp_unit != NULL)
- {
- var_name_begin += ::strlen ("file.");
-
- if (IsToken (var_name_begin, "basename}"))
- {
- format_file_spec.GetFilename() = sc->comp_unit->GetFilename();
- var_success = (bool)format_file_spec;
- }
- else if (IsToken (var_name_begin, "fullpath}"))
- {
- format_file_spec = *sc->comp_unit;
- var_success = (bool)format_file_spec;
- }
- }
- }
- else if (IsToken (var_name_begin, "frame."))
- {
- if (exe_ctx)
- {
- StackFrame *frame = exe_ctx->GetFramePtr();
- if (frame)
- {
- var_name_begin += ::strlen ("frame.");
- if (IsToken (var_name_begin, "index}"))
- {
- s.Printf("%u", frame->GetFrameIndex());
- var_success = true;
- }
- else if (IsToken (var_name_begin, "pc}"))
- {
- reg_kind = eRegisterKindGeneric;
- reg_num = LLDB_REGNUM_GENERIC_PC;
- var_success = true;
- }
- else if (IsToken (var_name_begin, "sp}"))
- {
- reg_kind = eRegisterKindGeneric;
- reg_num = LLDB_REGNUM_GENERIC_SP;
- var_success = true;
- }
- else if (IsToken (var_name_begin, "fp}"))
- {
- reg_kind = eRegisterKindGeneric;
- reg_num = LLDB_REGNUM_GENERIC_FP;
- var_success = true;
- }
- else if (IsToken (var_name_begin, "flags}"))
- {
- reg_kind = eRegisterKindGeneric;
- reg_num = LLDB_REGNUM_GENERIC_FLAGS;
- var_success = true;
- }
- else if (IsToken (var_name_begin, "reg."))
- {
- reg_ctx = frame->GetRegisterContext().get();
- if (reg_ctx)
- {
- var_name_begin += ::strlen ("reg.");
- if (var_name_begin < var_name_end)
- {
- std::string reg_name (var_name_begin, var_name_end);
- reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str());
- if (reg_info)
- var_success = true;
- }
- }
- }
- else if (IsToken (var_name_begin, "script:"))
- {
- var_name_begin += ::strlen("script:");
- std::string script_name(var_name_begin,var_name_end);
- ScriptInterpreter* script_interpreter = frame->GetThread()->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
- if (RunScriptFormatKeyword (s, script_interpreter, frame, script_name))
- var_success = true;
- }
- }
- }
- }
- else if (IsToken (var_name_begin, "function."))
- {
- if (sc && (sc->function != NULL || sc->symbol != NULL))
- {
- var_name_begin += ::strlen ("function.");
- if (IsToken (var_name_begin, "id}"))
- {
- if (sc->function)
- s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
- else
- s.Printf("symbol[%u]", sc->symbol->GetID());
-
- var_success = true;
- }
- if (IsToken (var_name_begin, "changed}") && function_changed)
- {
- var_success = true;
- }
- if (IsToken (var_name_begin, "initial-function}") && initial_function)
- {
- var_success = true;
- }
- else if (IsToken (var_name_begin, "name}"))
- {
- if (sc->function)
- cstr = sc->function->GetName().AsCString (NULL);
- else if (sc->symbol)
- cstr = sc->symbol->GetName().AsCString (NULL);
- if (cstr)
- {
- s.PutCString(cstr);
-
- if (sc->block)
- {
- Block *inline_block = sc->block->GetContainingInlinedBlock ();
- if (inline_block)
- {
- const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo();
- if (inline_info)
- {
- s.PutCString(" [inlined] ");
- inline_info->GetName().Dump(&s);
- }
- }
- }
- var_success = true;
- }
- }
- else if (IsToken (var_name_begin, "name-without-args}"))
- {
- ConstString name;
- if (sc->function)
- name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments);
- else if (sc->symbol)
- name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments);
- if (name)
- {
- s.PutCString(name.GetCString());
- var_success = true;
- }
- }
- else if (IsToken (var_name_begin, "name-with-args}"))
- {
- // Print the function name with arguments in it
-
- if (sc->function)
- {
- var_success = true;
- ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL;
- cstr = sc->function->GetName().AsCString (NULL);
- if (cstr)
- {
- const InlineFunctionInfo *inline_info = NULL;
- VariableListSP variable_list_sp;
- bool get_function_vars = true;
- if (sc->block)
- {
- Block *inline_block = sc->block->GetContainingInlinedBlock ();
-
- if (inline_block)
- {
- get_function_vars = false;
- inline_info = sc->block->GetInlinedFunctionInfo();
- if (inline_info)
- variable_list_sp = inline_block->GetBlockVariableList (true);
- }
- }
-
- if (get_function_vars)
- {
- variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true);
- }
-
- if (inline_info)
- {
- s.PutCString (cstr);
- s.PutCString (" [inlined] ");
- cstr = inline_info->GetName().GetCString();
- }
-
- VariableList args;
- if (variable_list_sp)
- variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args);
- if (args.GetSize() > 0)
- {
- const char *open_paren = strchr (cstr, '(');
- const char *close_paren = nullptr;
- const char *generic = strchr(cstr, '<');
- // if before the arguments list begins there is a template sign
- // then scan to the end of the generic args before you try to find
- // the arguments list
- if (generic && open_paren && generic < open_paren)
- {
- int generic_depth = 1;
- ++generic;
- for (;
- *generic && generic_depth > 0;
- generic++)
- {
- if (*generic == '<')
- generic_depth++;
- if (*generic == '>')
- generic_depth--;
- }
- if (*generic)
- open_paren = strchr(generic, '(');
- else
- open_paren = nullptr;
- }
- if (open_paren)
- {
- if (IsToken (open_paren, "(anonymous namespace)"))
- {
- open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '(');
- if (open_paren)
- close_paren = strchr (open_paren, ')');
- }
- else
- close_paren = strchr (open_paren, ')');
- }
-
- if (open_paren)
- s.Write(cstr, open_paren - cstr + 1);
- else
- {
- s.PutCString (cstr);
- s.PutChar ('(');
- }
- const size_t num_args = args.GetSize();
- for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx)
- {
- std::string buffer;
-
- VariableSP var_sp (args.GetVariableAtIndex (arg_idx));
- ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp));
- const char *var_representation = nullptr;
- const char *var_name = var_value_sp->GetName().GetCString();
- if (var_value_sp->GetClangType().IsAggregateType() &&
- DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get()))
- {
- static StringSummaryFormat format(TypeSummaryImpl::Flags()
- .SetHideItemNames(false)
- .SetShowMembersOneLiner(true),
- "");
- format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
- var_representation = buffer.c_str();
- }
- else
- var_representation = var_value_sp->GetValueAsCString();
- if (arg_idx > 0)
- s.PutCString (", ");
- if (var_value_sp->GetError().Success())
- {
- if (var_representation)
- s.Printf ("%s=%s", var_name, var_representation);
- else
- s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString());
- }
- else
- s.Printf ("%s=<unavailable>", var_name);
- }
-
- if (close_paren)
- s.PutCString (close_paren);
- else
- s.PutChar(')');
-
- }
- else
- {
- s.PutCString(cstr);
- }
- }
- }
- else if (sc->symbol)
- {
- cstr = sc->symbol->GetName().AsCString (NULL);
- if (cstr)
- {
- s.PutCString(cstr);
- var_success = true;
- }
- }
- }
- else if (IsToken (var_name_begin, "addr-offset}")
- || IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}"))
- {
- if (IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}"))
- {
- addr_offset_print_with_no_padding = true;
- addr_offset_concrete_func_only = true;
- }
- var_success = addr != NULL;
- if (var_success)
- {
- format_addr = *addr;
- calculate_format_addr_function_offset = true;
- }
- }
- else if (IsToken (var_name_begin, "line-offset}"))
- {
- var_success = sc->line_entry.range.GetBaseAddress().IsValid();
- if (var_success)
- {
- format_addr = sc->line_entry.range.GetBaseAddress();
- calculate_format_addr_function_offset = true;
- }
- }
- else if (IsToken (var_name_begin, "pc-offset}"))
- {
- StackFrame *frame = exe_ctx->GetFramePtr();
- var_success = frame != NULL;
- if (var_success)
- {
- format_addr = frame->GetFrameCodeAddress();
- calculate_format_addr_function_offset = true;
- }
- }
- }
- }
- break;
-
- case 'l':
- if (IsToken (var_name_begin, "line."))
- {
- if (sc && sc->line_entry.IsValid())
- {
- var_name_begin += ::strlen ("line.");
- if (IsToken (var_name_begin, "file."))
- {
- var_name_begin += ::strlen ("file.");
-
- if (IsToken (var_name_begin, "basename}"))
- {
- format_file_spec.GetFilename() = sc->line_entry.file.GetFilename();
- var_success = (bool)format_file_spec;
- }
- else if (IsToken (var_name_begin, "fullpath}"))
- {
- format_file_spec = sc->line_entry.file;
- var_success = (bool)format_file_spec;
- }
- }
- else if (IsTokenWithFormat (var_name_begin, "number", token_format, "%" PRIu64, exe_ctx, sc))
- {
- var_success = true;
- s.Printf(token_format.c_str(), (uint64_t)sc->line_entry.line);
- }
- else if ((IsToken (var_name_begin, "start-addr}")) ||
- (IsToken (var_name_begin, "end-addr}")))
- {
- var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid();
- if (var_success)
- {
- format_addr = sc->line_entry.range.GetBaseAddress();
- if (var_name_begin[0] == 'e')
- format_addr.Slide (sc->line_entry.range.GetByteSize());
- }
- }
- }
- }
- break;
- case 'c':
- if (IsToken (var_name_begin, "current-pc-arrow"))
- {
- if (addr && exe_ctx && exe_ctx->GetFramePtr())
- {
- RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP();
- if (reg_ctx.get())
- {
- addr_t pc_loadaddr = reg_ctx->GetPC();
- if (pc_loadaddr != LLDB_INVALID_ADDRESS)
- {
- Address pc;
- pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr());
- if (pc == *addr)
- {
- s.Printf ("-> ");
- var_success = true;
- }
- }
- }
- if (var_success == false)
- {
- s.Printf(" ");
- var_success = true;
- }
- }
- var_success = true;
- }
- break;
- }
-
- if (var_success)
- {
- // If format addr is valid, then we need to print an address
- if (reg_num != LLDB_INVALID_REGNUM)
- {
- StackFrame *frame = exe_ctx->GetFramePtr();
- // We have a register value to display...
- if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric)
- {
- format_addr = frame->GetFrameCodeAddress();
- }
- else
- {
- if (reg_ctx == NULL)
- reg_ctx = frame->GetRegisterContext().get();
-
- if (reg_ctx)
- {
- if (reg_kind != kNumRegisterKinds)
- reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
- reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num);
- var_success = reg_info != NULL;
- }
- }
- }
-
- if (reg_info != NULL)
- {
- RegisterValue reg_value;
- var_success = reg_ctx->ReadRegister (reg_info, reg_value);
- if (var_success)
- {
- reg_value.Dump(&s, reg_info, false, false, eFormatDefault);
- }
- }
-
- if (format_file_spec)
- {
- s << format_file_spec;
- }
-
- // If format addr is valid, then we need to print an address
- if (format_addr.IsValid())
- {
- var_success = false;
-
- if (calculate_format_addr_function_offset)
- {
- Address func_addr;
-
- if (sc)
- {
- if (sc->function)
- {
- func_addr = sc->function->GetAddressRange().GetBaseAddress();
- if (sc->block && addr_offset_concrete_func_only == false)
- {
- // Check to make sure we aren't in an inline
- // function. If we are, use the inline block
- // range that contains "format_addr" since
- // blocks can be discontiguous.
- Block *inline_block = sc->block->GetContainingInlinedBlock ();
- AddressRange inline_range;
- if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range))
- func_addr = inline_range.GetBaseAddress();
- }
- }
- else if (sc->symbol && sc->symbol->ValueIsAddress())
- func_addr = sc->symbol->GetAddress();
- }
-
- if (func_addr.IsValid())
- {
- const char *addr_offset_padding = " ";
- if (addr_offset_print_with_no_padding)
- {
- addr_offset_padding = "";
- }
- if (func_addr.GetSection() == format_addr.GetSection())
- {
- addr_t func_file_addr = func_addr.GetFileAddress();
- addr_t addr_file_addr = format_addr.GetFileAddress();
- if (addr_file_addr > func_file_addr)
- s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr);
- else if (addr_file_addr < func_file_addr)
- s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr);
- var_success = true;
- }
- else
- {
- Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
- if (target)
- {
- addr_t func_load_addr = func_addr.GetLoadAddress (target);
- addr_t addr_load_addr = format_addr.GetLoadAddress (target);
- if (addr_load_addr > func_load_addr)
- s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr);
- else if (addr_load_addr < func_load_addr)
- s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr);
- var_success = true;
- }
- }
- }
- }
- else
- {
- Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
- addr_t vaddr = LLDB_INVALID_ADDRESS;
- if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
- vaddr = format_addr.GetLoadAddress (target);
- if (vaddr == LLDB_INVALID_ADDRESS)
- vaddr = format_addr.GetFileAddress ();
-
- if (vaddr != LLDB_INVALID_ADDRESS)
- {
- int addr_width = 0;
- if (exe_ctx && target)
- {
- addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
- }
- if (addr_width == 0)
- addr_width = 16;
- if (print_file_addr_or_load_addr)
- {
- format_addr.Dump (&s, exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0);
- }
- else
- {
- s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
- }
- var_success = true;
- }
- }
- }
- }
-
- if (var_success == false)
- success = false;
- }
- p = var_name_end;
- }
- else
- break;
- }
- else
- {
- // We got a dollar sign with no '{' after it, it must just be a dollar sign
- s.PutChar(*p);
- }
- }
- else if (*p == '\\')
- {
- ++p; // skip the slash
- switch (*p)
- {
- case 'a': s.PutChar ('\a'); break;
- case 'b': s.PutChar ('\b'); break;
- case 'f': s.PutChar ('\f'); break;
- case 'n': s.PutChar ('\n'); break;
- case 'r': s.PutChar ('\r'); break;
- case 't': s.PutChar ('\t'); break;
- case 'v': s.PutChar ('\v'); break;
- case '\'': s.PutChar ('\''); break;
- case '\\': s.PutChar ('\\'); break;
- case '0':
- // 1 to 3 octal chars
- {
- // Make a string that can hold onto the initial zero char,
- // up to 3 octal digits, and a terminating NULL.
- char oct_str[5] = { 0, 0, 0, 0, 0 };
-
- int i;
- for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i)
- oct_str[i] = p[i];
-
- // We don't want to consume the last octal character since
- // the main for loop will do this for us, so we advance p by
- // one less than i (even if i is zero)
- p += i - 1;
- unsigned long octal_value = ::strtoul (oct_str, NULL, 8);
- if (octal_value <= UINT8_MAX)
- {
- s.PutChar((char)octal_value);
- }
- }
- break;
-
- case 'x':
- // hex number in the format
- if (isxdigit(p[1]))
- {
- ++p; // Skip the 'x'
-
- // Make a string that can hold onto two hex chars plus a
- // NULL terminator
- char hex_str[3] = { 0,0,0 };
- hex_str[0] = *p;
- if (isxdigit(p[1]))
- {
- ++p; // Skip the first of the two hex chars
- hex_str[1] = *p;
- }
-
- unsigned long hex_value = strtoul (hex_str, NULL, 16);
- if (hex_value <= UINT8_MAX)
- s.PutChar ((char)hex_value);
- }
- else
- {
- s.PutChar('x');
- }
- break;
-
- default:
- // Just desensitize any other character by just printing what
- // came after the '\'
- s << *p;
- break;
-
- }
-
- }
- }
- if (end)
- *end = p;
- return success;
-}
-
bool
-Debugger::FormatPrompt
-(
- const char *format,
- const SymbolContext *sc,
- const ExecutionContext *exe_ctx,
- const Address *addr,
- Stream &s,
- ValueObject* valobj
-)
-{
- bool use_color = exe_ctx ? exe_ctx->GetTargetRef().GetDebugger().GetUseColor() : true;
- std::string format_str = lldb_utility::ansi::FormatAnsiTerminalCodes (format, use_color);
- if (format_str.length())
- format = format_str.c_str();
- return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, valobj, false, false);
-}
-
-bool
-Debugger::FormatDisassemblerAddress (const char *format,
+Debugger::FormatDisassemblerAddress (const FormatEntity::Entry *format,
const SymbolContext *sc,
const SymbolContext *prev_sc,
const ExecutionContext *exe_ctx,
const Address *addr,
Stream &s)
{
- if (format == NULL && exe_ctx != NULL && exe_ctx->HasTargetScope())
+ FormatEntity::Entry format_entry;
+
+ if (format == NULL)
{
- format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
+ if (exe_ctx != NULL && exe_ctx->HasTargetScope())
+ format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
+ if (format == NULL)
+ {
+ FormatEntity::Parse("${addr}: ", format_entry);
+ format = &format_entry;
+ }
}
bool function_changed = false;
bool initial_function = false;
@@ -2942,7 +1276,7 @@ Debugger::FormatDisassemblerAddress (con
{
initial_function = true;
}
- return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, NULL, function_changed, initial_function);
+ return FormatEntity::Format(*format, s, sc, exe_ctx, addr, NULL, function_changed, initial_function);
}
Modified: lldb/trunk/source/Core/Disassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Disassembler.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/Core/Disassembler.cpp (original)
+++ lldb/trunk/source/Core/Disassembler.cpp Wed Feb 4 16:00:53 2015
@@ -471,12 +471,7 @@ Disassembler::PrintInstructions
}
const bool show_bytes = (options & eOptionShowBytes) != 0;
- const char *disassembly_format = "${addr-file-or-load}: ";
- if (exe_ctx.HasTargetScope())
- {
- disassembly_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat ();
- }
- inst->Dump (&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, &prev_sc, disassembly_format);
+ inst->Dump (&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, &prev_sc, NULL);
strm.EOL();
}
else
@@ -566,7 +561,7 @@ Instruction::Dump (lldb_private::Stream
const ExecutionContext* exe_ctx,
const SymbolContext *sym_ctx,
const SymbolContext *prev_sym_ctx,
- const char *disassembly_addr_format_spec)
+ const FormatEntity::Entry *disassembly_addr_format)
{
size_t opcode_column_width = 7;
const size_t operand_column_width = 25;
@@ -577,7 +572,7 @@ Instruction::Dump (lldb_private::Stream
if (show_address)
{
- Debugger::FormatDisassemblerAddress (disassembly_addr_format_spec, sym_ctx, prev_sym_ctx, exe_ctx, &m_address, ss);
+ Debugger::FormatDisassemblerAddress (disassembly_addr_format, sym_ctx, prev_sym_ctx, exe_ctx, &m_address, ss);
}
if (show_bytes)
@@ -985,18 +980,26 @@ InstructionList::Dump (Stream *s,
{
const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize();
collection::const_iterator pos, begin, end;
- const char *disassemble_format = "${addr-file-or-load}: ";
- if (exe_ctx)
+
+ const FormatEntity::Entry *disassembly_format = NULL;
+ FormatEntity::Entry format;
+ if (exe_ctx && exe_ctx->HasTargetScope())
{
- disassemble_format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat ();
+ disassembly_format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat ();
}
+ else
+ {
+ FormatEntity::Parse("${addr}: ", format);
+ disassembly_format = &format;
+ }
+
for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin;
pos != end;
++pos)
{
if (pos != begin)
s->EOL();
- (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, NULL, NULL, disassemble_format);
+ (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, NULL, NULL, disassembly_format);
}
}
Added: lldb/trunk/source/Core/FormatEntity.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FormatEntity.cpp?rev=228207&view=auto
==============================================================================
--- lldb/trunk/source/Core/FormatEntity.cpp (added)
+++ lldb/trunk/source/Core/FormatEntity.cpp Wed Feb 4 16:00:53 2015
@@ -0,0 +1,2511 @@
+//===-- FormatEntity.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringRef.h"
+
+#include "lldb/Core/FormatEntity.h"
+
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/LineEntry.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/AnsiTerminal.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+enum FileKind
+{
+ FileError = 0,
+ Basename,
+ Dirname,
+ Fullpath
+};
+
+#define ENTRY(n,t,f) { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0,0,NULL, false}
+#define ENTRY_VALUE(n,t,f,v) { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, v,0,NULL, false}
+#define ENTRY_CHILDREN(n,t,f,c) { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0,llvm::array_lengthof(c),c, false}
+#define ENTRY_CHILDREN_KEEP_SEP(n,t,f,c) { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0,llvm::array_lengthof(c),c, true}
+#define ENTRY_STRING(n,s) { n, s, FormatEntity::Entry::Type::InsertString, FormatEntity::Entry::FormatType::None, 0,0, NULL, false}
+static FormatEntity::Entry::Definition g_string_entry[] =
+{
+ ENTRY("*", ParentString, None)
+};
+
+static FormatEntity::Entry::Definition g_addr_entries[] =
+{
+ ENTRY ("load", AddressLoad , UInt64),
+ ENTRY ("file", AddressFile , UInt64),
+ ENTRY ("load", AddressLoadOrFile, UInt64),
+};
+
+static FormatEntity::Entry::Definition g_file_child_entries[] =
+{
+ ENTRY_VALUE("basename", ParentNumber, CString, FileKind::Basename),
+ ENTRY_VALUE("dirname", ParentNumber, CString, FileKind::Dirname),
+ ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath)
+};
+
+static FormatEntity::Entry::Definition g_frame_child_entries[] =
+{
+
+ ENTRY ("index", FrameIndex , UInt32),
+ ENTRY ("pc" , FrameRegisterPC , UInt64),
+ ENTRY ("fp" , FrameRegisterFP , UInt64),
+ ENTRY ("sp" , FrameRegisterSP , UInt64),
+ ENTRY ("flags", FrameRegisterFlags, UInt64),
+ ENTRY_CHILDREN ("reg", FrameRegisterByName, UInt64, g_string_entry),
+};
+
+static FormatEntity::Entry::Definition g_function_child_entries[] =
+{
+ ENTRY ("id" , FunctionID , UInt64),
+ ENTRY ("name" , FunctionName , CString),
+ ENTRY ("name-without-args" , FunctionNameNoArgs , CString),
+ ENTRY ("name-with-args" , FunctionNameWithArgs , CString),
+ ENTRY ("addr-offset" , FunctionAddrOffset , UInt64),
+ ENTRY ("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete, UInt64),
+ ENTRY ("line-offset" , FunctionLineOffset , UInt64),
+ ENTRY ("pc-offset" , FunctionPCOffset , UInt64)
+};
+
+static FormatEntity::Entry::Definition g_line_child_entries[] =
+{
+ ENTRY_CHILDREN("file", LineEntryFile , None , g_file_child_entries),
+ ENTRY("number" , LineEntryLineNumber , UInt32),
+ ENTRY("start-addr" , LineEntryStartAddress, UInt64),
+ ENTRY("end-addr" , LineEntryEndAddress , UInt64),
+};
+
+static FormatEntity::Entry::Definition g_module_child_entries[] =
+{
+ ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries),
+};
+
+static FormatEntity::Entry::Definition g_process_child_entries[] =
+{
+ ENTRY ( "id" , ProcessID , UInt64 ),
+ ENTRY_VALUE ( "name" , ProcessFile , CString , FileKind::Basename),
+ ENTRY_CHILDREN ( "file" , ProcessFile , None , g_file_child_entries),
+};
+
+static FormatEntity::Entry::Definition g_svar_child_entries[] =
+{
+ ENTRY ( "*" , ParentString , None)
+};
+
+static FormatEntity::Entry::Definition g_var_child_entries[] =
+{
+ ENTRY ( "*" , ParentString , None)
+};
+
+static FormatEntity::Entry::Definition g_thread_child_entries[] =
+{
+ ENTRY ( "id" , ThreadID , UInt64 ),
+ ENTRY ( "protocol_id" , ThreadProtocolID , UInt64 ),
+ ENTRY ( "index" , ThreadIndexID , UInt32 ),
+ ENTRY_CHILDREN ( "info" , ThreadInfo , None , g_string_entry),
+ ENTRY ( "queue" , ThreadQueue , CString ),
+ ENTRY ( "name" , ThreadName , CString ),
+ ENTRY ( "stop-reason" , ThreadStopReason , CString ),
+ ENTRY ( "return-value" , ThreadReturnValue , CString ),
+ ENTRY ( "completed-expression", ThreadCompletedExpression , CString ),
+};
+
+static FormatEntity::Entry::Definition g_target_child_entries[] =
+{
+ ENTRY ( "arch" , TargetArch , CString ),
+};
+
+#define _TO_STR2(_val) #_val
+#define _TO_STR(_val) _TO_STR2(_val)
+
+static FormatEntity::Entry::Definition g_ansi_fg_entries[] =
+{
+ ENTRY_STRING ("black" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END),
+ ENTRY_STRING ("red" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END),
+ ENTRY_STRING ("green" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END),
+ ENTRY_STRING ("yellow" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END),
+ ENTRY_STRING ("blue" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END),
+ ENTRY_STRING ("purple" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END),
+ ENTRY_STRING ("cyan" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END),
+ ENTRY_STRING ("white" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END),
+};
+
+static FormatEntity::Entry::Definition g_ansi_bg_entries[] =
+{
+ ENTRY_STRING ("black" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END),
+ ENTRY_STRING ("red" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END),
+ ENTRY_STRING ("green" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END),
+ ENTRY_STRING ("yellow" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END),
+ ENTRY_STRING ("blue" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END),
+ ENTRY_STRING ("purple" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END),
+ ENTRY_STRING ("cyan" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END),
+ ENTRY_STRING ("white" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END),
+};
+
+static FormatEntity::Entry::Definition g_ansi_entries[] =
+{
+ ENTRY_CHILDREN ( "fg" , Invalid , None , g_ansi_fg_entries),
+ ENTRY_CHILDREN ( "bg" , Invalid , None , g_ansi_bg_entries),
+ ENTRY_STRING ( "normal" , ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END),
+ ENTRY_STRING ( "bold" , ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END),
+ ENTRY_STRING ( "faint" , ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END),
+ ENTRY_STRING ( "italic" , ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END),
+ ENTRY_STRING ( "underline" , ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END),
+ ENTRY_STRING ( "slow-blink" , ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END),
+ ENTRY_STRING ( "fast-blink" , ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END),
+ ENTRY_STRING ( "negative" , ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
+ ENTRY_STRING ( "conceal" , ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END),
+ ENTRY_STRING ( "crossed-out" , ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END),
+
+};
+
+static FormatEntity::Entry::Definition g_script_child_entries[] =
+{
+ ENTRY ( "frame" , ScriptFrame , None),
+ ENTRY ( "process" , ScriptProcess , None),
+ ENTRY ( "target" , ScriptTarget , None),
+ ENTRY ( "thread" , ScriptThread , None),
+ ENTRY ( "var" , ScriptVariable , None),
+ ENTRY ( "svar" , ScriptVariableSynthetic , None),
+ ENTRY ( "thread" , ScriptThread , None),
+};
+
+static FormatEntity::Entry::Definition g_top_level_entries[] =
+{
+ ENTRY_CHILDREN ("addr" , AddressLoadOrFile , UInt64 , g_addr_entries),
+ ENTRY ("addr-file-or-load" , AddressLoadOrFile , UInt64 ),
+ ENTRY_CHILDREN ("ansi" , Invalid , None , g_ansi_entries),
+ ENTRY ("current-pc-arrow" , CurrentPCArrow , CString ),
+ ENTRY_CHILDREN ("file" , File , CString , g_file_child_entries),
+ ENTRY_CHILDREN ("frame" , Invalid , None , g_frame_child_entries),
+ ENTRY_CHILDREN ("function" , Invalid , None , g_function_child_entries),
+ ENTRY_CHILDREN ("line" , Invalid , None , g_line_child_entries),
+ ENTRY_CHILDREN ("module" , Invalid , None , g_module_child_entries),
+ ENTRY_CHILDREN ("process" , Invalid , None , g_process_child_entries),
+ ENTRY_CHILDREN ("script" , Invalid , None , g_script_child_entries),
+ ENTRY_CHILDREN_KEEP_SEP ("svar" , VariableSynthetic , None , g_svar_child_entries),
+ ENTRY_CHILDREN ("thread" , Invalid , None , g_thread_child_entries),
+ ENTRY_CHILDREN ("target" , Invalid , None , g_target_child_entries),
+ ENTRY_CHILDREN_KEEP_SEP ("var" , Variable , None , g_var_child_entries),
+};
+
+static FormatEntity::Entry::Definition g_root = ENTRY_CHILDREN ("<root>", Root, None, g_top_level_entries);
+
+
+FormatEntity::Entry::Entry (llvm::StringRef s) :
+ string (s.data(), s.size()),
+ printf_format (),
+ children (),
+ definition (NULL),
+ type (Type::String),
+ fmt (lldb::eFormatDefault),
+ number (0),
+ deref (false)
+{
+}
+
+FormatEntity::Entry::Entry (char ch) :
+ string (1, ch),
+ printf_format (),
+ children (),
+ definition (NULL),
+ type (Type::String),
+ fmt (lldb::eFormatDefault),
+ number (0),
+ deref (false)
+{
+}
+
+void
+FormatEntity::Entry::AppendChar (char ch)
+{
+ if (children.empty() || children.back().type != Entry::Type::String)
+ children.push_back(Entry(ch));
+ else
+ children.back().string.append(1, ch);
+}
+
+void
+FormatEntity::Entry::AppendText (const llvm::StringRef &s)
+{
+ if (children.empty() || children.back().type != Entry::Type::String)
+ children.push_back(Entry(s));
+ else
+ children.back().string.append(s.data(), s.size());
+}
+
+void
+FormatEntity::Entry::AppendText (const char *cstr)
+{
+ return AppendText (llvm::StringRef(cstr));
+}
+
+
+Error
+FormatEntity::Parse (const llvm::StringRef &format_str, Entry &entry)
+{
+ entry.Clear();
+ entry.type = Entry::Type::Root;
+ llvm::StringRef modifiable_format (format_str);
+ return ParseInternal (modifiable_format, entry, 0);
+}
+
+#define ENUM_TO_CSTR(eee) case FormatEntity::Entry::Type::eee: return #eee
+
+const char *
+FormatEntity::Entry::TypeToCString (Type t)
+{
+ switch (t)
+ {
+ ENUM_TO_CSTR(Invalid);
+ ENUM_TO_CSTR(ParentNumber);
+ ENUM_TO_CSTR(ParentString);
+ ENUM_TO_CSTR(InsertString);
+ ENUM_TO_CSTR(Root);
+ ENUM_TO_CSTR(String);
+ ENUM_TO_CSTR(Scope);
+ ENUM_TO_CSTR(Variable);
+ ENUM_TO_CSTR(VariableSynthetic);
+ ENUM_TO_CSTR(ScriptVariable);
+ ENUM_TO_CSTR(ScriptVariableSynthetic);
+ ENUM_TO_CSTR(AddressLoad);
+ ENUM_TO_CSTR(AddressFile);
+ ENUM_TO_CSTR(AddressLoadOrFile);
+ ENUM_TO_CSTR(ProcessID);
+ ENUM_TO_CSTR(ProcessFile);
+ ENUM_TO_CSTR(ScriptProcess);
+ ENUM_TO_CSTR(ThreadID);
+ ENUM_TO_CSTR(ThreadProtocolID);
+ ENUM_TO_CSTR(ThreadIndexID);
+ ENUM_TO_CSTR(ThreadName);
+ ENUM_TO_CSTR(ThreadQueue);
+ ENUM_TO_CSTR(ThreadStopReason);
+ ENUM_TO_CSTR(ThreadReturnValue);
+ ENUM_TO_CSTR(ThreadCompletedExpression);
+ ENUM_TO_CSTR(ScriptThread);
+ ENUM_TO_CSTR(ThreadInfo);
+ ENUM_TO_CSTR(TargetArch);
+ ENUM_TO_CSTR(ScriptTarget);
+ ENUM_TO_CSTR(ModuleFile);
+ ENUM_TO_CSTR(File);
+ ENUM_TO_CSTR(FrameIndex);
+ ENUM_TO_CSTR(FrameRegisterPC);
+ ENUM_TO_CSTR(FrameRegisterSP);
+ ENUM_TO_CSTR(FrameRegisterFP);
+ ENUM_TO_CSTR(FrameRegisterFlags);
+ ENUM_TO_CSTR(FrameRegisterByName);
+ ENUM_TO_CSTR(ScriptFrame);
+ ENUM_TO_CSTR(FunctionID);
+ ENUM_TO_CSTR(FunctionDidChange);
+ ENUM_TO_CSTR(FunctionInitialFunction);
+ ENUM_TO_CSTR(FunctionName);
+ ENUM_TO_CSTR(FunctionNameWithArgs);
+ ENUM_TO_CSTR(FunctionNameNoArgs);
+ ENUM_TO_CSTR(FunctionAddrOffset);
+ ENUM_TO_CSTR(FunctionAddrOffsetConcrete);
+ ENUM_TO_CSTR(FunctionLineOffset);
+ ENUM_TO_CSTR(FunctionPCOffset);
+ ENUM_TO_CSTR(LineEntryFile);
+ ENUM_TO_CSTR(LineEntryLineNumber);
+ ENUM_TO_CSTR(LineEntryStartAddress);
+ ENUM_TO_CSTR(LineEntryEndAddress);
+ ENUM_TO_CSTR(CurrentPCArrow);
+ }
+ return "???";
+}
+
+#undef ENUM_TO_CSTR
+
+void
+FormatEntity::Entry::Dump (Stream &s, int depth) const
+{
+ s.Printf ("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type));
+ if (fmt != eFormatDefault)
+ s.Printf ("lldb-format = %s, ", FormatManager::GetFormatAsCString (fmt));
+ if (!string.empty())
+ s.Printf ("string = \"%s\"", string.c_str());
+ if (!printf_format.empty())
+ s.Printf ("printf_format = \"%s\"", printf_format.c_str());
+ if (number != 0)
+ s.Printf ("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
+ if (deref)
+ s.Printf ("deref = true, ");
+ s.EOL();
+ for (const auto &child : children)
+ {
+ child.Dump(s, depth + 1);
+ }
+}
+
+
+template <typename T>
+static bool RunScriptFormatKeyword(Stream &s,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ T t,
+ const char *script_function_name)
+{
+ Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
+
+ if (target)
+ {
+ ScriptInterpreter *script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ if (script_interpreter)
+ {
+ Error error;
+ std::string script_output;
+
+ if (script_interpreter->RunScriptFormatKeyword(script_function_name, t, script_output, error) && error.Success())
+ {
+ s.Printf("%s", script_output.c_str());
+ return true;
+ }
+ else
+ {
+ s.Printf("<error: %s>",error.AsCString());
+ }
+ }
+ }
+ return false;
+}
+
+static bool
+DumpAddress (Stream &s,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ const Address &addr,
+ bool print_file_addr_or_load_addr)
+{
+ Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
+ addr_t vaddr = LLDB_INVALID_ADDRESS;
+ if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
+ vaddr = addr.GetLoadAddress (target);
+ if (vaddr == LLDB_INVALID_ADDRESS)
+ vaddr = addr.GetFileAddress ();
+
+ if (vaddr != LLDB_INVALID_ADDRESS)
+ {
+ int addr_width = 0;
+ if (exe_ctx && target)
+ {
+ addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
+ }
+ if (addr_width == 0)
+ addr_width = 16;
+ if (print_file_addr_or_load_addr)
+ {
+ ExecutionContextScope *exe_scope = NULL;
+ if (exe_ctx)
+ exe_scope = exe_ctx->GetBestExecutionContextScope();
+ addr.Dump (&s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0);
+ }
+ else
+ {
+ s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
+ }
+ return true;
+ }
+ return false;
+}
+
+static bool
+DumpAddressOffsetFromFunction (Stream &s,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ const Address &format_addr,
+ bool concrete_only,
+ bool no_padding)
+{
+ if (format_addr.IsValid())
+ {
+ Address func_addr;
+
+ if (sc)
+ {
+ if (sc->function)
+ {
+ func_addr = sc->function->GetAddressRange().GetBaseAddress();
+ if (sc->block && !concrete_only)
+ {
+ // Check to make sure we aren't in an inline
+ // function. If we are, use the inline block
+ // range that contains "format_addr" since
+ // blocks can be discontiguous.
+ Block *inline_block = sc->block->GetContainingInlinedBlock ();
+ AddressRange inline_range;
+ if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range))
+ func_addr = inline_range.GetBaseAddress();
+ }
+ }
+ else if (sc->symbol && sc->symbol->ValueIsAddress())
+ func_addr = sc->symbol->GetAddress();
+ }
+
+ if (func_addr.IsValid())
+ {
+ const char *addr_offset_padding = no_padding ? "" : " ";
+
+ if (func_addr.GetSection() == format_addr.GetSection())
+ {
+ addr_t func_file_addr = func_addr.GetFileAddress();
+ addr_t addr_file_addr = format_addr.GetFileAddress();
+ if (addr_file_addr > func_file_addr)
+ s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr);
+ else if (addr_file_addr < func_file_addr)
+ s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr);
+ return true;
+ }
+ else
+ {
+ Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
+ if (target)
+ {
+ addr_t func_load_addr = func_addr.GetLoadAddress (target);
+ addr_t addr_load_addr = format_addr.GetLoadAddress (target);
+ if (addr_load_addr > func_load_addr)
+ s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr);
+ else if (addr_load_addr < func_load_addr)
+ s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+static bool
+ScanBracketedRange (llvm::StringRef subpath,
+ size_t& close_bracket_index,
+ const char*& var_name_final_if_array_range,
+ int64_t& index_lower,
+ int64_t& index_higher)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+ close_bracket_index = llvm::StringRef::npos;
+ const size_t open_bracket_index = subpath.find('[');
+ if (open_bracket_index == llvm::StringRef::npos)
+ {
+ if (log)
+ log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
+ return false;
+ }
+
+ close_bracket_index = subpath.find(']', open_bracket_index + 1);
+
+ if (close_bracket_index == llvm::StringRef::npos)
+ {
+ if (log)
+ log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
+ return false;
+ }
+ else
+ {
+ var_name_final_if_array_range = subpath.data() + open_bracket_index;
+
+ if (close_bracket_index - open_bracket_index == 1)
+ {
+ if (log)
+ log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
+ index_lower = 0;
+ }
+ else
+ {
+ const size_t separator_index = subpath.find('-', open_bracket_index + 1);
+
+ if (separator_index == llvm::StringRef::npos)
+ {
+ const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
+ index_lower = ::strtoul (index_lower_cstr, NULL, 0);
+ index_higher = index_lower;
+ if (log)
+ log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", index_lower);
+ }
+ else
+ {
+ const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
+ const char *index_higher_cstr = subpath.data() + separator_index + 1;
+ index_lower = ::strtoul (index_lower_cstr, NULL, 0);
+ index_higher = ::strtoul (index_higher_cstr, NULL, 0);
+ if (log)
+ log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", index_lower, index_higher);
+ }
+ if (index_lower > index_higher && index_higher > 0)
+ {
+ if (log)
+ log->Printf("[ScanBracketedRange] swapping indices");
+ const int64_t temp = index_lower;
+ index_lower = index_higher;
+ index_higher = temp;
+ }
+ }
+ }
+ return true;
+}
+
+static bool
+DumpFile (Stream &s, const FileSpec &file, FileKind file_kind)
+{
+ switch (file_kind)
+ {
+ case FileKind::FileError:
+ break;
+
+ case FileKind::Basename:
+ if (file.GetFilename())
+ {
+ s << file.GetFilename();
+ return true;
+ }
+ break;
+
+ case FileKind::Dirname:
+ if (file.GetDirectory())
+ {
+ s << file.GetDirectory();
+ return true;
+ }
+ break;
+
+ case FileKind::Fullpath:
+ if (file)
+ {
+ s << file;
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+static bool
+DumpRegister (Stream &s,
+ StackFrame *frame,
+ RegisterKind reg_kind,
+ uint32_t reg_num,
+ Format format)
+
+{
+ if (frame)
+ {
+ RegisterContext *reg_ctx = frame->GetRegisterContext().get();
+
+ if (reg_ctx)
+ {
+ const uint32_t lldb_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
+ if (lldb_reg_num != LLDB_INVALID_REGNUM)
+ {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (lldb_reg_num);
+ if (reg_info)
+ {
+ RegisterValue reg_value;
+ if (reg_ctx->ReadRegister (reg_info, reg_value))
+ {
+ reg_value.Dump(&s, reg_info, false, false, format);
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+static ValueObjectSP
+ExpandIndexedExpression (ValueObject* valobj,
+ size_t index,
+ StackFrame* frame,
+ bool deref_pointer)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+ const char* ptr_deref_format = "[%d]";
+ std::string ptr_deref_buffer(10,0);
+ ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index);
+ if (log)
+ log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str());
+ const char* first_unparsed;
+ ValueObject::GetValueForExpressionPathOptions options;
+ ValueObject::ExpressionPathEndResultType final_value_type;
+ ValueObject::ExpressionPathScanEndReason reason_to_stop;
+ ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing);
+ ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(),
+ &first_unparsed,
+ &reason_to_stop,
+ &final_value_type,
+ options,
+ &what_next);
+ if (!item)
+ {
+ if (log)
+ log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d,"
+ " final_value_type %d",
+ first_unparsed, reason_to_stop, final_value_type);
+ }
+ else
+ {
+ if (log)
+ log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d,"
+ " final_value_type %d",
+ first_unparsed, reason_to_stop, final_value_type);
+ }
+ return item;
+}
+
+static char
+ConvertValueObjectStyleToChar(ValueObject::ValueObjectRepresentationStyle style)
+{
+ switch (style)
+ {
+ case ValueObject::eValueObjectRepresentationStyleLanguageSpecific: return '@';
+ case ValueObject::eValueObjectRepresentationStyleValue: return 'V';
+ case ValueObject::eValueObjectRepresentationStyleLocation: return 'L';
+ case ValueObject::eValueObjectRepresentationStyleSummary: return 'S';
+ case ValueObject::eValueObjectRepresentationStyleChildrenCount: return '#';
+ case ValueObject::eValueObjectRepresentationStyleType: return 'T';
+ case ValueObject::eValueObjectRepresentationStyleName: return 'N';
+ case ValueObject::eValueObjectRepresentationStyleExpressionPath: return '>';
+ }
+ return '\0';
+}
+
+static bool
+DumpValue (Stream &s,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ const FormatEntity::Entry &entry,
+ ValueObject *valobj)
+{
+ if (valobj == NULL)
+ return false;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+ Format custom_format = eFormatInvalid;
+ ValueObject::ValueObjectRepresentationStyle val_obj_display = entry.string.empty() ? ValueObject::eValueObjectRepresentationStyleValue : ValueObject::eValueObjectRepresentationStyleSummary;
+
+ bool do_deref_pointer = entry.deref;
+ bool is_script = false;
+ switch (entry.type)
+ {
+ case FormatEntity::Entry::Type::ScriptVariable:
+ is_script = true;
+ break;
+
+ case FormatEntity::Entry::Type::Variable:
+ custom_format = entry.fmt;
+ val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
+ break;
+
+ case FormatEntity::Entry::Type::ScriptVariableSynthetic:
+ is_script = true;
+ // Fall through
+ case FormatEntity::Entry::Type::VariableSynthetic:
+ custom_format = entry.fmt;
+ val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
+ if (!valobj->IsSynthetic())
+ {
+ valobj = valobj->GetSyntheticValue().get();
+ if (valobj == nullptr)
+ return false;
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ if (valobj == NULL)
+ return false;
+
+ ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ?
+ ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing);
+ ValueObject::GetValueForExpressionPathOptions options;
+ options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren();
+ ValueObject* target = NULL;
+ const char* var_name_final_if_array_range = NULL;
+ size_t close_bracket_index = llvm::StringRef::npos;
+ int64_t index_lower = -1;
+ int64_t index_higher = -1;
+ bool is_array_range = false;
+ const char* first_unparsed;
+ bool was_plain_var = false;
+ bool was_var_format = false;
+ bool was_var_indexed = false;
+ ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
+ ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain;
+
+ if (is_script)
+ {
+ return RunScriptFormatKeyword (s, sc, exe_ctx, valobj, entry.string.c_str());
+ }
+
+ llvm::StringRef subpath (entry.string);
+ // simplest case ${var}, just print valobj's value
+ if (entry.string.empty())
+ {
+ if (entry.printf_format.empty() && entry.fmt == eFormatDefault && entry.number == ValueObject::eValueObjectRepresentationStyleValue)
+ was_plain_var = true;
+ else
+ was_var_format = true;
+ target = valobj;
+ }
+ else // this is ${var.something} or multiple .something nested
+ {
+ if (entry.string[0] == '[')
+ was_var_indexed = true;
+ ScanBracketedRange (subpath,
+ close_bracket_index,
+ var_name_final_if_array_range,
+ index_lower,
+ index_higher);
+
+ Error error;
+
+ const std::string &expr_path = entry.string;
+
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str());
+
+ target = valobj->GetValueForExpressionPath(expr_path.c_str(),
+ &first_unparsed,
+ &reason_to_stop,
+ &final_value_type,
+ options,
+ &what_next).get();
+
+ if (!target)
+ {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d,"
+ " final_value_type %d",
+ first_unparsed, reason_to_stop, final_value_type);
+ return false;
+ }
+ else
+ {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d,"
+ " final_value_type %d",
+ first_unparsed, reason_to_stop, final_value_type);
+ target = target->GetQualifiedRepresentationIfAvailable(target->GetDynamicValueType(), true).get();
+ }
+ }
+
+
+ is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange ||
+ final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange);
+
+ do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference);
+
+ if (do_deref_pointer && !is_array_range)
+ {
+ // I have not deref-ed yet, let's do it
+ // this happens when we are not going through GetValueForVariableExpressionPath
+ // to get to the target ValueObject
+ Error error;
+ target = target->Dereference(error).get();
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \
+ return false;
+ }
+ do_deref_pointer = false;
+ }
+
+ if (!target)
+ {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression");
+ return false;
+ }
+
+ // we do not want to use the summary for a bitfield of type T:n
+ // if we were originally dealing with just a T - that would get
+ // us into an endless recursion
+ if (target->IsBitfield() && was_var_indexed)
+ {
+ // TODO: check for a (T:n)-specific summary - we should still obey that
+ StreamString bitfield_name;
+ bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize());
+ lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false));
+ if (val_obj_display == ValueObject::eValueObjectRepresentationStyleSummary && !DataVisualization::GetSummaryForType(type_sp))
+ val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
+ }
+
+ // TODO use flags for these
+ const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL);
+ bool is_array = (type_info_flags & eTypeIsArray) != 0;
+ bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
+ bool is_aggregate = target->GetClangType().IsAggregateType();
+
+ if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions
+ {
+ StreamString str_temp;
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range");
+
+ if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format))
+ {
+ // try to use the special cases
+ bool success = target->DumpPrintableRepresentation(str_temp,
+ val_obj_display,
+ custom_format);
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] special cases did%s match", success ? "" : "n't");
+
+ // should not happen
+ if (success)
+ s << str_temp.GetData();
+ return true;
+ }
+ else
+ {
+ if (was_plain_var) // if ${var}
+ {
+ s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
+ }
+ else if (is_pointer) // if pointer, value is the address stored
+ {
+ target->DumpPrintableRepresentation (s,
+ val_obj_display,
+ custom_format,
+ ValueObject::ePrintableRepresentationSpecialCasesDisable);
+ }
+ return true;
+ }
+ }
+
+ // if directly trying to print ${var}, and this is an aggregate, display a nice
+ // type @ location message
+ if (is_aggregate && was_plain_var)
+ {
+ s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
+ return true;
+ }
+
+ // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it
+ if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue)))
+ {
+ s << "<invalid use of aggregate type>";
+ return true;
+ }
+
+ if (!is_array_range)
+ {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output");
+ return target->DumpPrintableRepresentation(s,val_obj_display, custom_format);
+ }
+ else
+ {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] checking if I can handle as array");
+ if (!is_array && !is_pointer)
+ return false;
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] handle as array");
+ llvm::StringRef special_directions;
+ if (close_bracket_index != llvm::StringRef::npos && subpath.size() > close_bracket_index)
+ {
+ ConstString additional_data (subpath.drop_front(close_bracket_index+1));
+ StreamString special_directions_stream;
+ special_directions_stream.Printf("${%svar%s",
+ do_deref_pointer ? "*" : "",
+ additional_data.GetCString());
+
+ if (entry.fmt != eFormatDefault)
+ {
+ const char format_char = FormatManager::GetFormatAsFormatChar(entry.fmt);
+ if (format_char != '\0')
+ special_directions_stream.Printf("%%%c", format_char);
+ else
+ {
+ const char *format_cstr = FormatManager::GetFormatAsCString(entry.fmt);
+ special_directions_stream.Printf("%%%s", format_cstr);
+ }
+ }
+ else if (entry.number != 0)
+ {
+ const char style_char = ConvertValueObjectStyleToChar ((ValueObject::ValueObjectRepresentationStyle)entry.number);
+ if (style_char)
+ special_directions_stream.Printf("%%%c", style_char);
+ }
+ special_directions_stream.PutChar('}');
+ special_directions = llvm::StringRef(special_directions_stream.GetString());
+ }
+
+ // let us display items index_lower thru index_higher of this array
+ s.PutChar('[');
+
+ if (index_higher < 0)
+ index_higher = valobj->GetNumChildren() - 1;
+
+ uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
+
+ bool success = true;
+ for (int64_t index = index_lower;index<=index_higher; ++index)
+ {
+ ValueObject* item = ExpandIndexedExpression (target,
+ index,
+ exe_ctx->GetFramePtr(),
+ false).get();
+
+ if (!item)
+ {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index);
+ }
+ else
+ {
+ if (log)
+ log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions.data() ? special_directions.data() : "");
+ }
+
+ if (special_directions.empty())
+ {
+ success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format);
+ }
+ else
+ {
+ success &= FormatEntity::FormatStringRef(special_directions, s, sc, exe_ctx, NULL, item, false, false);
+ }
+
+ if (--max_num_children == 0)
+ {
+ s.PutCString(", ...");
+ break;
+ }
+
+ if (index < index_higher)
+ s.PutChar(',');
+ }
+ s.PutChar(']');
+ return success;
+ }
+
+}
+
+static bool
+DumpRegister (Stream &s,
+ StackFrame *frame,
+ const char *reg_name,
+ Format format)
+
+{
+ if (frame)
+ {
+ RegisterContext *reg_ctx = frame->GetRegisterContext().get();
+
+ if (reg_ctx)
+ {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
+ if (reg_info)
+ {
+ RegisterValue reg_value;
+ if (reg_ctx->ReadRegister (reg_info, reg_value))
+ {
+ reg_value.Dump(&s, reg_info, false, false, format);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+static bool
+FormatThreadExtendedInfoRecurse(const FormatEntity::Entry &entry,
+ const StructuredData::ObjectSP &thread_info_dictionary,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ Stream &s)
+{
+ llvm::StringRef path(entry.string);
+
+ StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path);
+
+ if (value.get())
+ {
+ if (value->GetType() == StructuredData::Type::eTypeInteger)
+ {
+ const char *token_format = "0x%4.4" PRIx64;
+ if (!entry.printf_format.empty())
+ token_format = entry.printf_format.c_str();
+ s.Printf(token_format, value->GetAsInteger()->GetValue());
+ return true;
+ }
+ else if (value->GetType() == StructuredData::Type::eTypeFloat)
+ {
+ s.Printf ("%f", value->GetAsFloat()->GetValue());
+ return true;
+ }
+ else if (value->GetType() == StructuredData::Type::eTypeString)
+ {
+ s.Printf("%s", value->GetAsString()->GetValue().c_str());
+ return true;
+ }
+ else if (value->GetType() == StructuredData::Type::eTypeArray)
+ {
+ if (value->GetAsArray()->GetSize() > 0)
+ {
+ s.Printf ("%zu", value->GetAsArray()->GetSize());
+ return true;
+ }
+ }
+ else if (value->GetType() == StructuredData::Type::eTypeDictionary)
+ {
+ s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+static inline bool
+IsToken(const char *var_name_begin, const char *var)
+{
+ return (::strncmp (var_name_begin, var, strlen(var)) == 0);
+}
+
+bool
+FormatEntity::FormatStringRef (const llvm::StringRef &format_str,
+ Stream &s,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ const Address *addr,
+ ValueObject* valobj,
+ bool function_changed,
+ bool initial_function)
+{
+ if (!format_str.empty())
+ {
+ FormatEntity::Entry root;
+ Error error = FormatEntity::Parse(format_str, root);
+ if (error.Success())
+ {
+ return FormatEntity::Format (root,
+ s,
+ sc,
+ exe_ctx,
+ addr,
+ valobj,
+ function_changed,
+ initial_function);
+ }
+ }
+ return false;
+
+}
+bool
+FormatEntity::FormatCString (const char *format,
+ Stream &s,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ const Address *addr,
+ ValueObject* valobj,
+ bool function_changed,
+ bool initial_function)
+{
+ if (format && format[0])
+ {
+ FormatEntity::Entry root;
+ llvm::StringRef format_str(format);
+ Error error = FormatEntity::Parse(format_str, root);
+ if (error.Success())
+ {
+ return FormatEntity::Format (root,
+ s,
+ sc,
+ exe_ctx,
+ addr,
+ valobj,
+ function_changed,
+ initial_function);
+ }
+ }
+ return false;
+}
+
+bool
+FormatEntity::Format (const Entry &entry,
+ Stream &s,
+ const SymbolContext *sc,
+ const ExecutionContext *exe_ctx,
+ const Address *addr,
+ ValueObject* valobj,
+ bool function_changed,
+ bool initial_function)
+{
+ switch (entry.type)
+ {
+ case Entry::Type::Invalid:
+ case Entry::Type::ParentNumber: // Only used for FormatEntity::Entry::Definition encoding
+ case Entry::Type::ParentString: // Only used for FormatEntity::Entry::Definition encoding
+ case Entry::Type::InsertString: // Only used for FormatEntity::Entry::Definition encoding
+ return false;
+
+ case Entry::Type::Root:
+ for (const auto &child : entry.children)
+ {
+ if (Format (child,
+ s,
+ sc,
+ exe_ctx,
+ addr,
+ valobj,
+ function_changed,
+ initial_function) == false)
+ {
+ return false; // If any item of root fails, then the formatting fails
+ }
+ }
+ return true; // Only return true if all items succeeded
+
+ case Entry::Type::String:
+ s.PutCString(entry.string.c_str());
+ return true;
+
+ case Entry::Type::Scope:
+ {
+ StreamString scope_stream;
+ bool success = false;
+ for (const auto &child : entry.children)
+ {
+ success = Format (child, scope_stream, sc, exe_ctx, addr, valobj, function_changed, initial_function);
+ if (!success)
+ break;
+ }
+ // Only if all items in a scope succeed, then do we
+ // print the output into the main stream
+ if (success)
+ s.Write(scope_stream.GetString().data(), scope_stream.GetString().size());
+ }
+ return true; // Scopes always successfully print themselves
+
+ case Entry::Type::Variable:
+ case Entry::Type::VariableSynthetic:
+ case Entry::Type::ScriptVariable:
+ case Entry::Type::ScriptVariableSynthetic:
+ if (DumpValue(s, sc, exe_ctx, entry, valobj))
+ return true;
+ return false;
+
+ case Entry::Type::AddressFile:
+ case Entry::Type::AddressLoad:
+ case Entry::Type::AddressLoadOrFile:
+ if (addr && addr->IsValid() && DumpAddress(s, sc, exe_ctx, *addr, entry.type == Entry::Type::AddressLoadOrFile))
+ return true;
+ return false;
+
+ case Entry::Type::ProcessID:
+ if (exe_ctx)
+ {
+ Process *process = exe_ctx->GetProcessPtr();
+ if (process)
+ {
+ const char *format = "%" PRIu64;
+ if (!entry.printf_format.empty())
+ format = entry.printf_format.c_str();
+ s.Printf(format, process->GetID());
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::ProcessFile:
+ if (exe_ctx)
+ {
+ Process *process = exe_ctx->GetProcessPtr();
+ if (process)
+ {
+ Module *exe_module = process->GetTarget().GetExecutableModulePointer();
+ if (exe_module)
+ {
+ if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
+ return true;
+ }
+ }
+ }
+ return false;
+
+ case Entry::Type::ScriptProcess:
+ if (exe_ctx)
+ {
+ Process *process = exe_ctx->GetProcessPtr();
+ if (process)
+ return RunScriptFormatKeyword (s, sc, exe_ctx, process, entry.string.c_str());
+ }
+ return false;
+
+
+ case Entry::Type::ThreadID:
+ if (exe_ctx)
+ {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread)
+ {
+ const char *format = "0x%4.4" PRIx64;
+ if (!entry.printf_format.empty())
+ {
+ // Watch for the special "tid" format...
+ if (entry.printf_format == "tid")
+ {
+ bool handled = false;
+ Target &target = thread->GetProcess()->GetTarget();
+ ArchSpec arch (target.GetArchitecture ());
+ llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS;
+ if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux))
+ {
+ handled = true;
+ format = "%" PRIu64;
+ }
+ }
+ else
+ {
+ format = entry.printf_format.c_str();
+ }
+ }
+ s.Printf(format, thread->GetID());
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::ThreadProtocolID:
+ if (exe_ctx)
+ {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread)
+ {
+ const char *format = "0x%4.4" PRIx64;
+ if (!entry.printf_format.empty())
+ format = entry.printf_format.c_str();
+ s.Printf(format, thread->GetProtocolID());
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::ThreadIndexID:
+ if (exe_ctx)
+ {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread)
+ {
+ const char *format = "%" PRIu32;
+ if (!entry.printf_format.empty())
+ format = entry.printf_format.c_str();
+ s.Printf(format, thread->GetIndexID());
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::ThreadName:
+ if (exe_ctx)
+ {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread)
+ {
+ const char *cstr = thread->GetName();
+ if (cstr && cstr[0])
+ {
+ s.PutCString(cstr);
+ return true;
+ }
+ }
+ }
+ return false;
+
+ case Entry::Type::ThreadQueue:
+ if (exe_ctx)
+ {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread)
+ {
+ const char *cstr = thread->GetQueueName();
+ if (cstr && cstr[0])
+ {
+ s.PutCString(cstr);
+ return true;
+ }
+ }
+ }
+ return false;
+
+ case Entry::Type::ThreadStopReason:
+ if (exe_ctx)
+ {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread)
+ {
+ StopInfoSP stop_info_sp = thread->GetStopInfo ();
+ if (stop_info_sp && stop_info_sp->IsValid())
+ {
+ const char *cstr = stop_info_sp->GetDescription();
+ if (cstr && cstr[0])
+ {
+ s.PutCString(cstr);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+
+ case Entry::Type::ThreadReturnValue:
+ if (exe_ctx)
+ {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread)
+ {
+ StopInfoSP stop_info_sp = thread->GetStopInfo ();
+ if (stop_info_sp && stop_info_sp->IsValid())
+ {
+ ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
+ if (return_valobj_sp)
+ {
+ return_valobj_sp->Dump(s);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+
+ case Entry::Type::ThreadCompletedExpression:
+ if (exe_ctx)
+ {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread)
+ {
+ StopInfoSP stop_info_sp = thread->GetStopInfo ();
+ if (stop_info_sp && stop_info_sp->IsValid())
+ {
+ ClangExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp);
+ if (expression_var_sp && expression_var_sp->GetValueObject())
+ {
+ expression_var_sp->GetValueObject()->Dump(s);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+
+ case Entry::Type::ScriptThread:
+ if (exe_ctx)
+ {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread)
+ return RunScriptFormatKeyword (s, sc, exe_ctx, thread, entry.string.c_str());
+ }
+ return false;
+
+ case Entry::Type::ThreadInfo:
+ if (exe_ctx)
+ {
+ Thread *thread = exe_ctx->GetThreadPtr();
+ if (thread)
+ {
+ StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
+ if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary)
+ {
+ if (FormatThreadExtendedInfoRecurse (entry, object_sp, sc, exe_ctx, s))
+ return true;
+ }
+ }
+ }
+ return false;
+
+ case Entry::Type::TargetArch:
+ if (exe_ctx)
+ {
+ Target *target = exe_ctx->GetTargetPtr();
+ if (target)
+ {
+ const ArchSpec &arch = target->GetArchitecture ();
+ if (arch.IsValid())
+ {
+ s.PutCString (arch.GetArchitectureName());
+ return true;
+ }
+ }
+ }
+ return false;
+
+ case Entry::Type::ScriptTarget:
+ if (exe_ctx)
+ {
+ Target *target = exe_ctx->GetTargetPtr();
+ if (target)
+ return RunScriptFormatKeyword (s, sc, exe_ctx, target, entry.string.c_str());
+ }
+ return false;
+
+ case Entry::Type::ModuleFile:
+ if (sc)
+ {
+ Module *module = sc->module_sp.get();
+ if (module)
+ {
+ if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::File:
+ if (sc)
+ {
+ CompileUnit *cu = sc->comp_unit;
+ if (cu)
+ {
+ // CompileUnit is a FileSpec
+ if (DumpFile(s, *cu, (FileKind)entry.number))
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::FrameIndex:
+ if (exe_ctx)
+ {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame)
+ {
+ const char *format = "%" PRIu32;
+ if (!entry.printf_format.empty())
+ format = entry.printf_format.c_str();
+ s.Printf(format, frame->GetFrameIndex());
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::FrameRegisterPC:
+ if (exe_ctx)
+ {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame)
+ {
+ const Address &pc_addr = frame->GetFrameCodeAddress();
+ if (pc_addr.IsValid())
+ {
+ if (DumpAddress(s, sc, exe_ctx, pc_addr, false))
+ return true;
+ }
+ }
+ }
+ return false;
+
+ case Entry::Type::FrameRegisterSP:
+ if (exe_ctx)
+ {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame)
+ {
+ if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, (lldb::Format)entry.number))
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::FrameRegisterFP:
+ if (exe_ctx)
+ {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame)
+ {
+ if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, (lldb::Format)entry.number))
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::FrameRegisterFlags:
+ if (exe_ctx)
+ {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame)
+ {
+ if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number))
+ return true;
+ }
+ }
+ return false;
+
+
+ case Entry::Type::FrameRegisterByName:
+ if (exe_ctx)
+ {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame)
+ {
+ if (DumpRegister (s, frame, entry.string.c_str(), (lldb::Format)entry.number))
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::ScriptFrame:
+ if (exe_ctx)
+ {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame)
+ return RunScriptFormatKeyword (s, sc, exe_ctx, frame, entry.string.c_str());
+ }
+ return false;
+
+ case Entry::Type::FunctionID:
+ if (sc)
+ {
+ if (sc->function)
+ {
+ s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
+ return true;
+ }
+ else if (sc->symbol)
+ {
+ s.Printf("symbol[%u]", sc->symbol->GetID());
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::FunctionDidChange:
+ return function_changed;
+
+ case Entry::Type::FunctionInitialFunction:
+ return initial_function;
+
+ case Entry::Type::FunctionName:
+ {
+ const char *name = NULL;
+ if (sc->function)
+ name = sc->function->GetName().AsCString (NULL);
+ else if (sc->symbol)
+ name = sc->symbol->GetName().AsCString (NULL);
+ if (name)
+ {
+ s.PutCString(name);
+
+ if (sc->block)
+ {
+ Block *inline_block = sc->block->GetContainingInlinedBlock ();
+ if (inline_block)
+ {
+ const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo();
+ if (inline_info)
+ {
+ s.PutCString(" [inlined] ");
+ inline_info->GetName().Dump(&s);
+ }
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::FunctionNameNoArgs:
+ {
+ ConstString name;
+ if (sc->function)
+ name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments);
+ else if (sc->symbol)
+ name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments);
+ if (name)
+ {
+ s.PutCString(name.GetCString());
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::FunctionNameWithArgs:
+ {
+ // Print the function name with arguments in it
+ if (sc->function)
+ {
+ ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL;
+ const char *cstr = sc->function->GetName().AsCString (NULL);
+ if (cstr)
+ {
+ const InlineFunctionInfo *inline_info = NULL;
+ VariableListSP variable_list_sp;
+ bool get_function_vars = true;
+ if (sc->block)
+ {
+ Block *inline_block = sc->block->GetContainingInlinedBlock ();
+
+ if (inline_block)
+ {
+ get_function_vars = false;
+ inline_info = sc->block->GetInlinedFunctionInfo();
+ if (inline_info)
+ variable_list_sp = inline_block->GetBlockVariableList (true);
+ }
+ }
+
+ if (get_function_vars)
+ {
+ variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true);
+ }
+
+ if (inline_info)
+ {
+ s.PutCString (cstr);
+ s.PutCString (" [inlined] ");
+ cstr = inline_info->GetName().GetCString();
+ }
+
+ VariableList args;
+ if (variable_list_sp)
+ variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args);
+ if (args.GetSize() > 0)
+ {
+ const char *open_paren = strchr (cstr, '(');
+ const char *close_paren = nullptr;
+ const char *generic = strchr(cstr, '<');
+ // if before the arguments list begins there is a template sign
+ // then scan to the end of the generic args before you try to find
+ // the arguments list
+ if (generic && open_paren && generic < open_paren)
+ {
+ int generic_depth = 1;
+ ++generic;
+ for (;
+ *generic && generic_depth > 0;
+ generic++)
+ {
+ if (*generic == '<')
+ generic_depth++;
+ if (*generic == '>')
+ generic_depth--;
+ }
+ if (*generic)
+ open_paren = strchr(generic, '(');
+ else
+ open_paren = nullptr;
+ }
+ if (open_paren)
+ {
+ if (IsToken (open_paren, "(anonymous namespace)"))
+ {
+ open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '(');
+ if (open_paren)
+ close_paren = strchr (open_paren, ')');
+ }
+ else
+ close_paren = strchr (open_paren, ')');
+ }
+
+ if (open_paren)
+ s.Write(cstr, open_paren - cstr + 1);
+ else
+ {
+ s.PutCString (cstr);
+ s.PutChar ('(');
+ }
+ const size_t num_args = args.GetSize();
+ for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx)
+ {
+ std::string buffer;
+
+ VariableSP var_sp (args.GetVariableAtIndex (arg_idx));
+ ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp));
+ const char *var_representation = nullptr;
+ const char *var_name = var_value_sp->GetName().GetCString();
+ if (var_value_sp->GetClangType().IsAggregateType() &&
+ DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get()))
+ {
+ static StringSummaryFormat format(TypeSummaryImpl::Flags()
+ .SetHideItemNames(false)
+ .SetShowMembersOneLiner(true),
+ "");
+ format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
+ var_representation = buffer.c_str();
+ }
+ else
+ var_representation = var_value_sp->GetValueAsCString();
+ if (arg_idx > 0)
+ s.PutCString (", ");
+ if (var_value_sp->GetError().Success())
+ {
+ if (var_representation)
+ s.Printf ("%s=%s", var_name, var_representation);
+ else
+ s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString());
+ }
+ else
+ s.Printf ("%s=<unavailable>", var_name);
+ }
+
+ if (close_paren)
+ s.PutCString (close_paren);
+ else
+ s.PutChar(')');
+
+ }
+ else
+ {
+ s.PutCString(cstr);
+ }
+ return true;
+ }
+ }
+ else if (sc->symbol)
+ {
+ const char *cstr = sc->symbol->GetName().AsCString (NULL);
+ if (cstr)
+ {
+ s.PutCString(cstr);
+ return true;
+ }
+ }
+ }
+ return false;
+
+ case Entry::Type::FunctionAddrOffset:
+ if (addr)
+ {
+ if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, *addr, false, false))
+ return true;
+ }
+ return false;
+
+ case Entry::Type::FunctionAddrOffsetConcrete:
+ if (addr)
+ {
+ if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, *addr, true, true))
+ return true;
+ }
+ return false;
+
+ case Entry::Type::FunctionLineOffset:
+ if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, sc->line_entry.range.GetBaseAddress(), false, false))
+ return true;
+ return false;
+
+ case Entry::Type::FunctionPCOffset:
+ if (exe_ctx)
+ {
+ StackFrame *frame = exe_ctx->GetFramePtr();
+ if (frame)
+ {
+ if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, frame->GetFrameCodeAddress(), false, false))
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::LineEntryFile:
+ if (sc && sc->line_entry.IsValid())
+ {
+ Module *module = sc->module_sp.get();
+ if (module)
+ {
+ if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number))
+ return true;
+ }
+ }
+ return false;
+
+ case Entry::Type::LineEntryLineNumber:
+ if (sc && sc->line_entry.IsValid())
+ {
+ const char *format = "%" PRIu32;
+ if (!entry.printf_format.empty())
+ format = entry.printf_format.c_str();
+ s.Printf(format, sc->line_entry.line);
+ return true;
+ }
+ return false;
+
+ case Entry::Type::LineEntryStartAddress:
+ case Entry::Type::LineEntryEndAddress:
+ if (sc && sc->line_entry.range.GetBaseAddress().IsValid())
+ {
+ Address addr = sc->line_entry.range.GetBaseAddress();
+
+ if (entry.type == Entry::Type::LineEntryEndAddress)
+ addr.Slide(sc->line_entry.range.GetByteSize());
+ if (DumpAddress(s, sc, exe_ctx, addr, false))
+ return true;
+ }
+ return false;
+
+ case Entry::Type::CurrentPCArrow:
+ if (addr && exe_ctx && exe_ctx->GetFramePtr())
+ {
+ RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP();
+ if (reg_ctx.get())
+ {
+ addr_t pc_loadaddr = reg_ctx->GetPC();
+ if (pc_loadaddr != LLDB_INVALID_ADDRESS)
+ {
+ Address pc;
+ pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr());
+ if (pc == *addr)
+ {
+ s.Printf ("-> ");
+ return true;
+ }
+ }
+ }
+ s.Printf(" ");
+ return true;
+ }
+ return false;
+ }
+ return false;
+}
+
+static bool
+DumpCommaSeparatedChildEntryNames (Stream &s, const FormatEntity::Entry::Definition *parent)
+{
+ if (parent->children)
+ {
+ const size_t n = parent->num_children;
+ for (size_t i=0; i<n; ++i)
+ {
+ if (i > 0)
+ s.PutCString(", ");
+ s.Printf ("\"%s\"", parent->children[i].name);
+ }
+ return true;
+ }
+ return false;
+}
+
+
+static Error
+ParseEntry (const llvm::StringRef &format_str,
+ const FormatEntity::Entry::Definition *parent,
+ FormatEntity::Entry &entry)
+{
+ Error error;
+
+ const size_t sep_pos = format_str.find_first_of(".[:");
+ const char sep_char = (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
+ llvm::StringRef key = format_str.substr(0, sep_pos);
+
+ const size_t n = parent->num_children;
+ for (size_t i=0; i<n; ++i)
+ {
+ const FormatEntity::Entry::Definition *entry_def = parent->children + i;
+ if (key.equals(entry_def->name) || entry_def->name[0] == '*')
+ {
+ llvm::StringRef value;
+ if (sep_char)
+ value = format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
+ switch (entry_def->type)
+ {
+ case FormatEntity::Entry::Type::ParentString:
+ entry.string = std::move(format_str.str());
+ return error; // Success
+
+ case FormatEntity::Entry::Type::ParentNumber:
+ entry.number = entry_def->data;
+ return error; // Success
+
+ case FormatEntity::Entry::Type::InsertString:
+ entry.type = entry_def->type;
+ entry.string = entry_def->string;
+ return error; // Success
+
+ default:
+ entry.type = entry_def->type;
+ break;
+ }
+
+ if (value.empty())
+ {
+ if (entry_def->type == FormatEntity::Entry::Type::Invalid)
+ {
+ if (entry_def->children)
+ {
+ StreamString error_strm;
+ error_strm.Printf("'%s' can't be specified on its own, you must access one of its children: ", entry_def->name);
+ DumpCommaSeparatedChildEntryNames (error_strm, entry_def);
+ error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str());
+ }
+ else if (sep_char == ':')
+ {
+ // Any value whose separator is a with a ':' means this value has a string argument
+ // that needs to be stored in the entry (like "${script.var:}").
+ // In this case the string value is the empty string which is ok.
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("%s", "invalid entry definitions");
+ }
+ }
+ }
+ else
+ {
+ if (entry_def->children)
+ {
+ error = ParseEntry (value, entry_def, entry);
+ }
+ else if (sep_char == ':')
+ {
+ // Any value whose separator is a with a ':' means this value has a string argument
+ // that needs to be stored in the entry (like "${script.var:modulename.function}")
+ entry.string = std::move(value.str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'%s' followed by '%s' but it has no children",
+ key.str().c_str(),
+ value.str().c_str());
+ }
+ }
+ return error;
+ }
+ }
+ StreamString error_strm;
+ if (parent->type == FormatEntity::Entry::Type::Root)
+ error_strm.Printf("invalid top level item '%s'. Valid top level items are: ", key.str().c_str());
+ else
+ error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ", key.str().c_str(), parent->name);
+ DumpCommaSeparatedChildEntryNames (error_strm, parent);
+ error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str());
+ return error;
+}
+
+
+static const FormatEntity::Entry::Definition *
+FindEntry (const llvm::StringRef &format_str, const FormatEntity::Entry::Definition *parent, llvm::StringRef &remainder)
+{
+ Error error;
+
+ std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
+ const size_t n = parent->num_children;
+ for (size_t i=0; i<n; ++i)
+ {
+ const FormatEntity::Entry::Definition *entry_def = parent->children + i;
+ if (p.first.equals(entry_def->name) || entry_def->name[0] == '*')
+ {
+ if (p.second.empty())
+ {
+ if (format_str.back() == '.')
+ remainder = format_str.drop_front(format_str.size() - 1);
+ else
+ remainder = llvm::StringRef(); // Exact match
+ return entry_def;
+ }
+ else
+ {
+ if (entry_def->children)
+ {
+ return FindEntry (p.second, entry_def, remainder);
+ }
+ else
+ {
+ remainder = p.second;
+ return entry_def;
+ }
+ }
+ }
+ }
+ remainder = format_str;
+ return parent;
+}
+
+Error
+FormatEntity::ParseInternal (llvm::StringRef &format, Entry &parent_entry, uint32_t depth)
+{
+ Error error;
+ while (!format.empty() && error.Success())
+ {
+ const size_t non_special_chars = format.find_first_of("${}\\");
+
+ if (non_special_chars == llvm::StringRef::npos)
+ {
+ // No special characters, just string bytes so add them and we are done
+ parent_entry.AppendText(format);
+ return error;
+ }
+
+ if (non_special_chars > 0)
+ {
+ // We have a special character, so add all characters before these as a plain string
+ parent_entry.AppendText(format.substr(0,non_special_chars));
+ format = format.drop_front(non_special_chars);
+ }
+
+ switch (format[0])
+ {
+ case '\0':
+ return error;
+
+ case '{':
+ {
+ format = format.drop_front(); // Skip the '{'
+ Entry scope_entry(Entry::Type::Scope);
+ error = FormatEntity::ParseInternal (format, scope_entry, depth+1);
+ if (error.Fail())
+ return error;
+ parent_entry.AppendEntry(std::move(scope_entry));
+ }
+ break;
+
+ case '}':
+ if (depth == 0)
+ error.SetErrorString("unmatched '}' character");
+ else
+ format = format.drop_front(); // Skip the '}' as we are at the end of the scope
+ return error;
+
+ case '\\':
+ {
+ format = format.drop_front(); // Skip the '\' character
+ if (format.empty())
+ {
+ error.SetErrorString("'\\' character was not followed by another character");
+ return error;
+ }
+
+ const char desens_char = format[0];
+ format = format.drop_front(); // Skip the desensitized char character
+ switch (desens_char)
+ {
+ case 'a': parent_entry.AppendChar('\a'); break;
+ case 'b': parent_entry.AppendChar('\b'); break;
+ case 'f': parent_entry.AppendChar('\f'); break;
+ case 'n': parent_entry.AppendChar('\n'); break;
+ case 'r': parent_entry.AppendChar('\r'); break;
+ case 't': parent_entry.AppendChar('\t'); break;
+ case 'v': parent_entry.AppendChar('\v'); break;
+ case '\'': parent_entry.AppendChar('\''); break;
+ case '\\': parent_entry.AppendChar('\\'); break;
+ case '0':
+ // 1 to 3 octal chars
+ {
+ // Make a string that can hold onto the initial zero char,
+ // up to 3 octal digits, and a terminating NULL.
+ char oct_str[5] = { 0, 0, 0, 0, 0 };
+
+ int i;
+ for (i=0; (format[i] >= '0' && format[i] <= '7') && i<4; ++i)
+ oct_str[i] = format[i];
+
+ // We don't want to consume the last octal character since
+ // the main for loop will do this for us, so we advance p by
+ // one less than i (even if i is zero)
+ format = format.drop_front(i);
+ unsigned long octal_value = ::strtoul (oct_str, NULL, 8);
+ if (octal_value <= UINT8_MAX)
+ {
+ parent_entry.AppendChar((char)octal_value);
+ }
+ else
+ {
+ error.SetErrorString("octal number is larger than a single byte");
+ return error;
+ }
+ }
+ break;
+
+ case 'x':
+ // hex number in the format
+ if (isxdigit(format[0]))
+ {
+ // Make a string that can hold onto two hex chars plus a
+ // NULL terminator
+ char hex_str[3] = { 0,0,0 };
+ hex_str[0] = format[0];
+
+ format = format.drop_front();
+
+ if (isxdigit(format[0]))
+ {
+ hex_str[1] = format[0];
+ format = format.drop_front();
+ }
+
+ unsigned long hex_value = strtoul (hex_str, NULL, 16);
+ if (hex_value <= UINT8_MAX)
+ {
+ parent_entry.AppendChar((char)hex_value);
+ }
+ else
+ {
+ error.SetErrorString("hex number is larger than a single byte");
+ return error;
+ }
+ }
+ else
+ {
+ parent_entry.AppendChar(desens_char);
+ }
+ break;
+
+ default:
+ // Just desensitize any other character by just printing what
+ // came after the '\'
+ parent_entry.AppendChar(desens_char);
+ break;
+ }
+ }
+ break;
+
+ case '$':
+ if (format.size() == 1)
+ {
+ // '$' at the end of a format string, just print the '$'
+ parent_entry.AppendText("$");
+ }
+ else
+ {
+ format = format.drop_front(); // Skip the '$'
+
+ if (format[0] == '{')
+ {
+ format = format.drop_front(); // Skip the '{'
+
+ llvm::StringRef variable, variable_format;
+ error = FormatEntity::ExtractVariableInfo (format, variable, variable_format);
+ if (error.Fail())
+ return error;
+ bool verify_is_thread_id = false;
+ Entry entry;
+ if (!variable_format.empty())
+ {
+ entry.printf_format = std::move(variable_format.str());
+
+ // If the format contains a '%' we are going to assume this is
+ // a printf style format. So if you want to format your thread ID
+ // using "0x%llx" you can use:
+ // ${thread.id%0x%llx}
+ //
+ // If there is no '%' in the format, then it is assumed to be a
+ // LLDB format name, or one of the extended formats specified in
+ // the switch statement below.
+
+ if (entry.printf_format.find('%') == std::string::npos)
+ {
+ bool clear_printf = false;
+
+ if (FormatManager::GetFormatFromCString(entry.printf_format.c_str(),
+ false,
+ entry.fmt))
+ {
+ // We have an LLDB format, so clear the printf format
+ clear_printf = true;
+ }
+ else if (entry.printf_format.size() == 1)
+ {
+ switch (entry.printf_format[0])
+ {
+ case '@': // if this is an @ sign, print ObjC description
+ entry.number = ValueObject::eValueObjectRepresentationStyleLanguageSpecific;
+ clear_printf = true;
+ break;
+ case 'V': // if this is a V, print the value using the default format
+ entry.number = ValueObject::eValueObjectRepresentationStyleValue;
+ clear_printf = true;
+ break;
+ case 'L': // if this is an L, print the location of the value
+ entry.number = ValueObject::eValueObjectRepresentationStyleLocation;
+ clear_printf = true;
+ break;
+ case 'S': // if this is an S, print the summary after all
+ entry.number = ValueObject::eValueObjectRepresentationStyleSummary;
+ clear_printf = true;
+ break;
+ case '#': // if this is a '#', print the number of children
+ entry.number = ValueObject::eValueObjectRepresentationStyleChildrenCount;
+ clear_printf = true;
+ break;
+ case 'T': // if this is a 'T', print the type
+ entry.number = ValueObject::eValueObjectRepresentationStyleType;
+ clear_printf = true;
+ break;
+ case 'N': // if this is a 'N', print the name
+ entry.number = ValueObject::eValueObjectRepresentationStyleName;
+ clear_printf = true;
+ break;
+ case '>': // if this is a '>', print the name
+ entry.number = ValueObject::eValueObjectRepresentationStyleExpressionPath;
+ clear_printf = true;
+ break;
+ default:
+ error.SetErrorStringWithFormat("invalid format: '%s'", entry.printf_format.c_str());
+ return error;
+ }
+ }
+ else if (FormatManager::GetFormatFromCString(entry.printf_format.c_str(),
+ true,
+ entry.fmt))
+ {
+ clear_printf = true;
+ }
+ else if (entry.printf_format == "tid")
+ {
+ verify_is_thread_id = true;
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("invalid format: '%s'", entry.printf_format.c_str());
+ return error;
+ }
+
+ // Our format string turned out to not be a printf style format
+ // so lets clear the string
+ if (clear_printf)
+ entry.printf_format.clear();
+ }
+ }
+
+ // Check for dereferences
+ if (variable[0] == '*')
+ {
+ entry.deref = true;
+ variable = variable.drop_front();
+ }
+
+ error = ParseEntry (variable, &g_root, entry);
+ if (error.Fail())
+ return error;
+
+ if (verify_is_thread_id)
+ {
+ if (entry.type != Entry::Type::ThreadID &&
+ entry.type != Entry::Type::ThreadProtocolID)
+ {
+ error.SetErrorString("the 'tid' format can only be used on ${thread.id} and ${thread.protocol_id}");
+ }
+ }
+
+ switch (entry.type)
+ {
+ case Entry::Type::Variable:
+ case Entry::Type::VariableSynthetic:
+ if (entry.number == 0)
+ {
+ if (entry.string.empty())
+ entry.number = ValueObject::eValueObjectRepresentationStyleValue;
+ else
+ entry.number = ValueObject::eValueObjectRepresentationStyleSummary;
+ }
+ break;
+ default:
+ // Make sure someone didn't try to dereference anything but ${var} or ${svar}
+ if (entry.deref)
+ {
+ error.SetErrorStringWithFormat("${%s} can't be dereferenced, only ${var} and ${svar} can.", variable.str().c_str());
+ return error;
+ }
+ }
+ // Check if this entry just wants to insert a constant string
+ // value into the parent_entry, if so, insert the string with
+ // AppendText, else append the entry to the parent_entry.
+ if (entry.type == Entry::Type::InsertString)
+ parent_entry.AppendText(entry.string.c_str());
+ else
+ parent_entry.AppendEntry(std::move(entry));
+ }
+ }
+ break;
+ }
+ }
+ return error;
+}
+
+
+Error
+FormatEntity::ExtractVariableInfo (llvm::StringRef &format_str, llvm::StringRef &variable_name, llvm::StringRef &variable_format)
+{
+ Error error;
+ variable_name = llvm::StringRef();
+ variable_format = llvm::StringRef();
+
+ const size_t paren_pos = format_str.find_first_of('}');
+ if (paren_pos != llvm::StringRef::npos)
+ {
+ const size_t percent_pos = format_str.find_first_of('%');
+ if (percent_pos < paren_pos)
+ {
+ if (percent_pos > 0)
+ {
+ if (percent_pos > 1)
+ variable_name = format_str.substr(0, percent_pos);
+ variable_format = format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
+ }
+ }
+ else
+ {
+ variable_name = format_str.substr(0, paren_pos);
+ }
+ // Strip off elements and the formatting and the trailing '}'
+ format_str = format_str.substr(paren_pos + 1);
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("missing terminating '}' character for '${%s'", format_str.str().c_str());
+ }
+ return error;
+}
+
+bool
+FormatEntity::FormatFileSpec (const FileSpec &file_spec, Stream &s, llvm::StringRef variable_name, llvm::StringRef variable_format)
+{
+ if (variable_name.empty() || variable_name.equals(".fullpath"))
+ {
+ file_spec.Dump(&s);
+ return true;
+ }
+ else if (variable_name.equals(".basename"))
+ {
+ s.PutCString(file_spec.GetFilename().AsCString(""));
+ return true;
+ }
+ else if (variable_name.equals(".dirname"))
+ {
+ s.PutCString(file_spec.GetFilename().AsCString(""));
+ return true;
+ }
+ return false;
+}
+
+static std::string
+MakeMatch (const llvm::StringRef &prefix, const char *suffix)
+{
+ std::string match(prefix.str());
+ match.append(suffix);
+ return std::move(match);
+}
+
+static void
+AddMatches (const FormatEntity::Entry::Definition *def,
+ const llvm::StringRef &prefix,
+ const llvm::StringRef &match_prefix,
+ StringList &matches)
+{
+ const size_t n = def->num_children;
+ if (n > 0)
+ {
+ for (size_t i=0; i<n; ++i)
+ {
+ std::string match = std::move(prefix.str());
+ if (match_prefix.empty())
+ matches.AppendString(MakeMatch (prefix, def->children[i].name));
+ else if (strncmp(def->children[i].name, match_prefix.data(), match_prefix.size()) == 0)
+ matches.AppendString(MakeMatch (prefix, def->children[i].name + match_prefix.size()));
+ }
+ }
+}
+size_t
+FormatEntity::AutoComplete (const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+{
+ word_complete = false;
+ llvm::StringRef str(s + match_start_point);
+ matches.Clear();
+
+ const size_t dollar_pos = str.rfind('$');
+ if (dollar_pos != llvm::StringRef::npos)
+ {
+ // Hitting TAB after $ at the end of the string add a "{"
+ if (dollar_pos == str.size() - 1)
+ {
+ std::string match = std::move(str.str());
+ match.append("{");
+ matches.AppendString(std::move(match));
+ }
+ else if (str[dollar_pos + 1] == '{')
+ {
+ const size_t close_pos = str.find('}', dollar_pos + 2);
+ if (close_pos == llvm::StringRef::npos)
+ {
+ const size_t format_pos = str.find('%', dollar_pos + 2);
+ if (format_pos == llvm::StringRef::npos)
+ {
+ llvm::StringRef partial_variable (str.substr(dollar_pos + 2));
+ if (partial_variable.empty())
+ {
+ // Suggest all top level entites as we are just past "${"
+ AddMatches(&g_root, str, llvm::StringRef(), matches);
+ }
+ else
+ {
+ // We have a partially specified variable, find it
+ llvm::StringRef remainder;
+ const FormatEntity::Entry::Definition* entry_def = FindEntry (partial_variable, &g_root, remainder);
+ if (entry_def)
+ {
+ const size_t n = entry_def->num_children;
+
+ if (remainder.empty())
+ {
+ // Exact match
+ if (n > 0)
+ {
+ // "${thread.info" <TAB>
+ matches.AppendString(std::move(MakeMatch (str, ".")));
+ }
+ else
+ {
+ // "${thread.id" <TAB>
+ matches.AppendString(std::move(MakeMatch (str, "}")));
+ word_complete = true;
+ }
+ }
+ else if (remainder.equals("."))
+ {
+ // "${thread." <TAB>
+ AddMatches(entry_def, str, llvm::StringRef(), matches);
+ }
+ else
+ {
+ // We have a partial match
+ // "${thre" <TAB>
+ AddMatches(entry_def, str, remainder, matches);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return matches.GetSize();
+}
Modified: lldb/trunk/source/Core/IOHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/IOHandler.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/Core/IOHandler.cpp (original)
+++ lldb/trunk/source/Core/IOHandler.cpp Wed Feb 4 16:00:53 2015
@@ -3217,6 +3217,8 @@ public:
FrameTreeDelegate () :
TreeDelegate()
{
+ FormatEntity::Parse ("frame #${frame.index}: {${function.name}${function.pc-offset}}}",
+ m_format);
}
virtual ~FrameTreeDelegate()
@@ -3236,9 +3238,7 @@ public:
StreamString strm;
const SymbolContext &sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
ExecutionContext exe_ctx (frame_sp);
- //const char *frame_format = "frame #${frame.index}: ${module.file.basename}{`${function.name}${function.pc-offset}}}";
- const char *frame_format = "frame #${frame.index}: {${function.name}${function.pc-offset}}}";
- if (Debugger::FormatPrompt (frame_format, &sc, &exe_ctx, NULL, strm))
+ if (FormatEntity::Format(m_format, strm, &sc, &exe_ctx, NULL, NULL, false, false))
{
int right_pad = 1;
window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
@@ -3265,6 +3265,8 @@ public:
}
return false;
}
+protected:
+ FormatEntity::Entry m_format;
};
class ThreadTreeDelegate : public TreeDelegate
@@ -3276,6 +3278,8 @@ public:
m_tid (LLDB_INVALID_THREAD_ID),
m_stop_id (UINT32_MAX)
{
+ FormatEntity::Parse ("thread #${thread.index}: tid = ${thread.id}{, stop reason = ${thread.stop-reason}}",
+ m_format);
}
virtual
@@ -3306,8 +3310,7 @@ public:
{
StreamString strm;
ExecutionContext exe_ctx (thread_sp);
- const char *format = "thread #${thread.index}: tid = ${thread.id}{, stop reason = ${thread.stop-reason}}";
- if (Debugger::FormatPrompt (format, NULL, &exe_ctx, NULL, strm))
+ if (FormatEntity::Format (m_format, strm, NULL, &exe_ctx, NULL, NULL, false, false))
{
int right_pad = 1;
window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
@@ -3383,6 +3386,8 @@ protected:
std::shared_ptr<FrameTreeDelegate> m_frame_delegate_sp;
lldb::user_id_t m_tid;
uint32_t m_stop_id;
+ FormatEntity::Entry m_format;
+
};
class ThreadsTreeDelegate : public TreeDelegate
@@ -3394,6 +3399,8 @@ public:
m_debugger (debugger),
m_stop_id (UINT32_MAX)
{
+ FormatEntity::Parse("process ${process.id}{, name = ${process.name}}",
+ m_format);
}
virtual
@@ -3415,8 +3422,7 @@ public:
{
StreamString strm;
ExecutionContext exe_ctx (process_sp);
- const char *format = "process ${process.id}{, name = ${process.name}}";
- if (Debugger::FormatPrompt (format, NULL, &exe_ctx, NULL, strm))
+ if (FormatEntity::Format (m_format, strm, NULL, &exe_ctx, NULL, NULL, false, false))
{
int right_pad = 1;
window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
@@ -3472,6 +3478,8 @@ protected:
std::shared_ptr<ThreadTreeDelegate> m_thread_delegate_sp;
Debugger &m_debugger;
uint32_t m_stop_id;
+ FormatEntity::Entry m_format;
+
};
class ValueObjectListDelegate : public WindowDelegate
@@ -4635,6 +4643,8 @@ public:
StatusBarWindowDelegate (Debugger &debugger) :
m_debugger (debugger)
{
+ FormatEntity::Parse("Thread: ${thread.id%tid}",
+ m_format);
}
virtual
@@ -4659,8 +4669,7 @@ public:
if (StateIsStoppedState(state, true))
{
StreamString strm;
- const char *format = "Thread: ${thread.id%tid}";
- if (thread && Debugger::FormatPrompt (format, NULL, &exe_ctx, NULL, strm))
+ if (thread && FormatEntity::Format (m_format, strm, NULL, &exe_ctx, NULL, NULL, false, false))
{
window.MoveCursor (40, 0);
window.PutCStringTruncated(strm.GetString().c_str(), 1);
@@ -4686,6 +4695,7 @@ public:
protected:
Debugger &m_debugger;
+ FormatEntity::Entry m_format;
};
class SourceFileWindowDelegate : public WindowDelegate
Modified: lldb/trunk/source/DataFormatters/LibCxx.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/DataFormatters/LibCxx.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/DataFormatters/LibCxx.cpp (original)
+++ lldb/trunk/source/DataFormatters/LibCxx.cpp Wed Feb 4 16:00:53 2015
@@ -14,6 +14,7 @@
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Error.h"
+#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
@@ -460,5 +461,5 @@ lldb_private::formatters::LibcxxContaine
return false;
stream.Printf("0x%016" PRIx64 " ", value);
}
- return Debugger::FormatPrompt("size=${svar%#}", NULL, NULL, NULL, stream, &valobj);
+ return FormatEntity::FormatStringRef("size=${svar%#}", stream, NULL, NULL, NULL, &valobj, false, false);
}
Modified: lldb/trunk/source/DataFormatters/TypeSummary.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/DataFormatters/TypeSummary.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/DataFormatters/TypeSummary.cpp (original)
+++ lldb/trunk/source/DataFormatters/TypeSummary.cpp Wed Feb 4 16:00:53 2015
@@ -86,13 +86,30 @@ m_flags(flags)
StringSummaryFormat::StringSummaryFormat (const TypeSummaryImpl::Flags& flags,
const char *format_cstr) :
-TypeSummaryImpl(flags),
-m_format()
+ TypeSummaryImpl(flags),
+ m_format_str()
{
- if (format_cstr)
- m_format.assign(format_cstr);
+ SetSummaryString (format_cstr);
}
+void
+StringSummaryFormat::SetSummaryString (const char* format_cstr)
+{
+ m_format.Clear();
+ if (format_cstr && format_cstr[0])
+ {
+ m_format_str = format_cstr;
+ m_error = FormatEntity::Parse(format_cstr, m_format);
+ }
+ else
+ {
+ m_format_str.clear();
+ m_error.Clear();
+ }
+}
+
+
+
bool
StringSummaryFormat::FormatObject (ValueObject *valobj,
std::string& retval,
@@ -120,7 +137,7 @@ StringSummaryFormat::FormatObject (Value
}
else
{
- if (Debugger::FormatPrompt(m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, valobj))
+ if (FormatEntity::Format(m_format, s, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), valobj, false, false))
{
retval.assign(s.GetString());
return true;
@@ -138,7 +155,10 @@ StringSummaryFormat::GetDescription ()
{
StreamString sstr;
- sstr.Printf ("`%s`%s%s%s%s%s%s%s", m_format.c_str(),
+ sstr.Printf ("`%s`%s%s%s%s%s%s%s%s%s",
+ m_format_str.c_str(),
+ m_error.Fail() ? " error: " : "",
+ m_error.Fail() ? m_error.AsCString() : "",
Cascades() ? "" : " (not cascading)",
!DoesPrintChildren(nullptr) ? "" : " (show children)",
!DoesPrintValue(nullptr) ? " (hide value)" : "",
@@ -153,8 +173,8 @@ CXXFunctionSummaryFormat::CXXFunctionSum
Callback impl,
const char* description) :
TypeSummaryImpl(flags),
-m_impl(impl),
-m_description(description ? description : "")
+ m_impl(impl),
+ m_description(description ? description : "")
{
}
Modified: lldb/trunk/source/Expression/IRExecutionUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRExecutionUnit.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRExecutionUnit.cpp (original)
+++ lldb/trunk/source/Expression/IRExecutionUnit.cpp Wed Feb 4 16:00:53 2015
@@ -199,28 +199,8 @@ IRExecutionUnit::DisassembleFunction (St
disassembler_sp->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false);
InstructionList &instruction_list = disassembler_sp->GetInstructionList();
- const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
- const char *disassemble_format = "${addr-file-or-load}: ";
- if (exe_ctx.HasTargetScope())
- {
- disassemble_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat();
- }
-
- for (size_t instruction_index = 0, num_instructions = instruction_list.GetSize();
- instruction_index < num_instructions;
- ++instruction_index)
- {
- Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get();
- instruction->Dump (&stream,
- max_opcode_byte_size,
- true,
- true,
- &exe_ctx,
- NULL,
- NULL,
- disassemble_format);
- stream.PutChar('\n');
- }
+ instruction_list.Dump(&stream, true, true, &exe_ctx);
+
// FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions.
// I'll fix that but for now, just clear the list and it will go away nicely.
disassembler_sp->GetInstructionList().Clear();
Modified: lldb/trunk/source/Interpreter/OptionValue.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionValue.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionValue.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionValue.cpp Wed Feb 4 16:00:53 2015
@@ -222,6 +222,22 @@ OptionValue::GetAsFormat () const
return nullptr;
}
+OptionValueFormatEntity *
+OptionValue::GetAsFormatEntity ()
+{
+ if (GetType () == OptionValue::eTypeFormatEntity)
+ return static_cast<OptionValueFormatEntity *>(this);
+ return nullptr;
+}
+
+const OptionValueFormatEntity *
+OptionValue::GetAsFormatEntity () const
+{
+ if (GetType () == OptionValue::eTypeFormatEntity)
+ return static_cast<const OptionValueFormatEntity *>(this);
+ return nullptr;
+}
+
OptionValuePathMappings *
OptionValue::GetAsPathMappings ()
{
@@ -452,6 +468,15 @@ OptionValue::SetFormatValue (lldb::Forma
return false;
}
+const FormatEntity::Entry *
+OptionValue::GetFormatEntity () const
+{
+ const OptionValueFormatEntity *option_value = GetAsFormatEntity();
+ if (option_value)
+ return &option_value->GetCurrentValue();
+ return nullptr;
+}
+
const RegularExpression *
OptionValue::GetRegexValue () const
{
@@ -563,6 +588,7 @@ OptionValue::GetBuiltinTypeAsCString (Ty
case eTypeFileSpec: return "file";
case eTypeFileSpecList: return "file-list";
case eTypeFormat: return "format";
+ case eTypeFormatEntity: return "format-string";
case eTypePathMap: return "path-map";
case eTypeProperties: return "properties";
case eTypeRegex: return "regex";
@@ -583,15 +609,16 @@ OptionValue::CreateValueFromCStringForTy
lldb::OptionValueSP value_sp;
switch (type_mask)
{
- case 1u << eTypeArch: value_sp.reset(new OptionValueArch()); break;
- case 1u << eTypeBoolean: value_sp.reset(new OptionValueBoolean(false)); break;
- case 1u << eTypeChar: value_sp.reset(new OptionValueChar('\0')); break;
- case 1u << eTypeFileSpec: value_sp.reset(new OptionValueFileSpec()); break;
- case 1u << eTypeFormat: value_sp.reset(new OptionValueFormat(eFormatInvalid)); break;
- case 1u << eTypeSInt64: value_sp.reset(new OptionValueSInt64()); break;
- case 1u << eTypeString: value_sp.reset(new OptionValueString()); break;
- case 1u << eTypeUInt64: value_sp.reset(new OptionValueUInt64()); break;
- case 1u << eTypeUUID: value_sp.reset(new OptionValueUUID()); break;
+ case 1u << eTypeArch: value_sp.reset(new OptionValueArch()); break;
+ case 1u << eTypeBoolean: value_sp.reset(new OptionValueBoolean(false)); break;
+ case 1u << eTypeChar: value_sp.reset(new OptionValueChar('\0')); break;
+ case 1u << eTypeFileSpec: value_sp.reset(new OptionValueFileSpec()); break;
+ case 1u << eTypeFormat: value_sp.reset(new OptionValueFormat(eFormatInvalid)); break;
+ case 1u << eTypeFormatEntity: value_sp.reset(new OptionValueFormatEntity(NULL)); break;
+ case 1u << eTypeSInt64: value_sp.reset(new OptionValueSInt64()); break;
+ case 1u << eTypeString: value_sp.reset(new OptionValueString()); break;
+ case 1u << eTypeUInt64: value_sp.reset(new OptionValueUInt64()); break;
+ case 1u << eTypeUUID: value_sp.reset(new OptionValueUUID()); break;
}
if (value_sp)
Added: lldb/trunk/source/Interpreter/OptionValueFormatEntity.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionValueFormatEntity.cpp?rev=228207&view=auto
==============================================================================
--- lldb/trunk/source/Interpreter/OptionValueFormatEntity.cpp (added)
+++ lldb/trunk/source/Interpreter/OptionValueFormatEntity.cpp Wed Feb 4 16:00:53 2015
@@ -0,0 +1,124 @@
+//===-- OptionValueFormatEntity.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Interpreter/OptionValueFormatEntity.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+using namespace lldb;
+using namespace lldb_private;
+
+
+OptionValueFormatEntity::OptionValueFormatEntity (const char *default_format) :
+ OptionValue(),
+ m_current_format (),
+ m_default_format (),
+ m_current_entry (),
+ m_default_entry ()
+{
+ if (default_format && default_format[0])
+ {
+ llvm::StringRef default_format_str(default_format);
+ Error error = FormatEntity::Parse(default_format_str, m_default_entry);
+ if (error.Success())
+ {
+ m_default_format = default_format;
+ m_current_format = default_format;
+ m_current_entry = m_default_entry;
+ }
+ }
+}
+
+bool
+OptionValueFormatEntity::Clear ()
+{
+ m_current_entry = m_default_entry;
+ m_current_format = m_default_format;
+ m_value_was_set = false;
+ return true;
+}
+
+
+void
+OptionValueFormatEntity::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ if (dump_mask & eDumpOptionType)
+ strm.Printf ("(%s)", GetTypeAsCString ());
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.PutCString (" = \"");
+ strm << m_current_format.c_str() << '"';
+ }
+}
+
+Error
+OptionValueFormatEntity::SetValueFromCString (const char *value_cstr,
+ VarSetOperationType op)
+{
+ Error error;
+ switch (op)
+ {
+ case eVarSetOperationClear:
+ Clear();
+ NotifyValueChanged();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign:
+ {
+ FormatEntity::Entry entry;
+ llvm::StringRef value_str(value_cstr);
+ error = FormatEntity::Parse(value_str, entry);
+ if (error.Success())
+ {
+ m_current_entry = std::move(entry);
+ m_current_format = value_cstr;
+ m_value_was_set = true;
+ NotifyValueChanged();
+ }
+ }
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationRemove:
+ case eVarSetOperationAppend:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromCString (value_cstr, op);
+ break;
+ }
+ return error;
+}
+
+lldb::OptionValueSP
+OptionValueFormatEntity::DeepCopy () const
+{
+ return OptionValueSP(new OptionValueFormatEntity(*this));
+}
+
+size_t
+OptionValueFormatEntity::AutoComplete (CommandInterpreter &interpreter,
+ const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+{
+ return FormatEntity::AutoComplete (s, match_start_point, max_return_elements, word_complete, matches);
+}
+
Modified: lldb/trunk/source/Interpreter/OptionValueProperties.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionValueProperties.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/OptionValueProperties.cpp (original)
+++ lldb/trunk/source/Interpreter/OptionValueProperties.cpp Wed Feb 4 16:00:53 2015
@@ -421,6 +421,18 @@ OptionValueProperties::SetPropertyAtInde
return false;
}
+const FormatEntity::Entry *
+OptionValueProperties::GetPropertyAtIndexAsFormatEntity (const ExecutionContext *exe_ctx, uint32_t idx)
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->GetFormatEntity();
+ }
+ return nullptr;
+}
OptionValueFileSpec *
OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
Modified: lldb/trunk/source/Interpreter/Property.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/Property.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/Property.cpp (original)
+++ lldb/trunk/source/Interpreter/Property.cpp Wed Feb 4 16:00:53 2015
@@ -109,16 +109,21 @@ Property::Property (const PropertyDefini
// "definition.default_cstr_value" is NULL, otherwise interpret
// "definition.default_cstr_value" as a string value that represents the default
// value.
- {
- Format new_format = eFormatInvalid;
- if (definition.default_cstr_value)
- Args::StringToFormat (definition.default_cstr_value, new_format, nullptr);
- else
- new_format = (Format)definition.default_uint_value;
- m_value_sp.reset (new OptionValueFormat(new_format));
- }
+ {
+ Format new_format = eFormatInvalid;
+ if (definition.default_cstr_value)
+ Args::StringToFormat (definition.default_cstr_value, new_format, nullptr);
+ else
+ new_format = (Format)definition.default_uint_value;
+ m_value_sp.reset (new OptionValueFormat(new_format));
+ }
break;
+ case OptionValue::eTypeFormatEntity:
+ // "definition.default_cstr_value" as a string value that represents the default
+ m_value_sp.reset (new OptionValueFormatEntity(definition.default_cstr_value));
+ break;
+
case OptionValue::eTypePathMap:
// "definition.default_uint_value" tells us if notifications should occur for
// path mappings
@@ -151,12 +156,12 @@ Property::Property (const PropertyDefini
case OptionValue::eTypeUUID:
// "definition.default_uint_value" is not used for a OptionValue::eTypeUUID
// "definition.default_cstr_value" can contain a default UUID value
- {
- UUID uuid;
- if (definition.default_cstr_value)
- uuid.SetFromCString (definition.default_cstr_value);
- m_value_sp.reset (new OptionValueUUID(uuid));
- }
+ {
+ UUID uuid;
+ if (definition.default_cstr_value)
+ uuid.SetFromCString (definition.default_cstr_value);
+ m_value_sp.reset (new OptionValueUUID(uuid));
+ }
break;
case OptionValue::eTypeString:
Modified: lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp (original)
+++ lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp Wed Feb 4 16:00:53 2015
@@ -15,6 +15,7 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Error.h"
+#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamString.h"
@@ -146,8 +147,9 @@ UnwindAssemblyInstEmulation::GetNonCallS
if (log && log->GetVerbose ())
{
StreamString strm;
- const char *disassemble_format = "${frame.pc}: ";
- inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL, NULL, NULL, disassemble_format);
+ lldb_private::FormatEntity::Entry format;
+ FormatEntity::Parse("${frame.pc}: ", format);
+ inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL, NULL, NULL, &format);
log->PutCString (strm.GetData());
}
Modified: lldb/trunk/source/Target/StackFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StackFrame.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/Target/StackFrame.cpp (original)
+++ lldb/trunk/source/Target/StackFrame.cpp Wed Feb 4 16:00:53 2015
@@ -18,6 +18,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Core/ValueObjectConstResult.h"
@@ -1373,11 +1374,11 @@ StackFrame::DumpUsingSettingsFormat (Str
if (frame_marker)
s.PutCString(frame_marker);
- const char *frame_format = NULL;
+ const FormatEntity::Entry *frame_format = NULL;
Target *target = exe_ctx.GetTargetPtr();
if (target)
frame_format = target->GetDebugger().GetFrameFormat();
- if (frame_format && Debugger::FormatPrompt (frame_format, &m_sc, &exe_ctx, NULL, s))
+ if (frame_format && FormatEntity::Format(*frame_format, s, &m_sc, &exe_ctx, NULL, NULL, false, false))
{
strm->Write(s.GetData(), s.GetSize());
}
Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Wed Feb 4 16:00:53 2015
@@ -13,6 +13,7 @@
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamString.h"
@@ -2043,13 +2044,17 @@ Thread::DumpUsingSettingsFormat (Stream
}
}
- const char *thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat();
+ const FormatEntity::Entry *thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat();
assert (thread_format);
- Debugger::FormatPrompt (thread_format,
- frame_sp ? &frame_sc : NULL,
- &exe_ctx,
- NULL,
- strm);
+
+ FormatEntity::Format(*thread_format,
+ strm,
+ frame_sp ? &frame_sc : NULL,
+ &exe_ctx,
+ NULL,
+ NULL,
+ false,
+ false);
}
void
Modified: lldb/trunk/source/Target/ThreadPlanTracer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanTracer.cpp?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanTracer.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanTracer.cpp Wed Feb 4 16:00:53 2015
@@ -212,7 +212,7 @@ ThreadPlanAssemblyTracer::Log ()
const bool show_bytes = true;
const bool show_address = true;
Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get();
- const char *disassemble_format = "${addr-file-or-load}: ";
+ const FormatEntity::Entry *disassemble_format = m_thread.GetProcess()->GetTarget().GetDebugger().GetDisassemblyFormat();
instruction->Dump (stream,
max_opcode_byte_size,
show_address,
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py Wed Feb 4 16:00:53 2015
@@ -57,7 +57,7 @@ class SmartArrayDataFormatterTestCase(Te
self.runCmd("type summary add --summary-string \"${var%V}\" SomeData")
self.expect("frame variable data",
- substrs = ['invalid use of aggregate type'])
+ substrs = ['SomeData @ 0x'])
# ${var%s}
self.runCmd("type summary add --summary-string \"ptr = ${var%s}\" \"char *\"")
Modified: lldb/trunk/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py Wed Feb 4 16:00:53 2015
@@ -58,7 +58,7 @@ class PythonSynthDataFormatterTestCase(T
self.addTearDownHook(cleanup)
self.runCmd("command script import helperfunc.py")
- self.runCmd('type summary add -x "^something<.*>$" -s "T is a ${var.script:helperfunc.f}"')
+ self.runCmd('type summary add -x "^something<.*>$" -s "T is a ${script.var:helperfunc.f}"')
self.expect("frame variable x", substrs = ['T is a non-pointer type']);
Added: lldb/trunk/test/functionalities/format/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/format/Makefile?rev=228207&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/format/Makefile (added)
+++ lldb/trunk/test/functionalities/format/Makefile Wed Feb 4 16:00:53 2015
@@ -0,0 +1,5 @@
+LEVEL = ../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules
Added: lldb/trunk/test/functionalities/format/TestFormats.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/format/TestFormats.py?rev=228207&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/format/TestFormats.py (added)
+++ lldb/trunk/test/functionalities/format/TestFormats.py Wed Feb 4 16:00:53 2015
@@ -0,0 +1,62 @@
+"""
+Test the command history mechanism
+"""
+
+import os
+import unittest2
+import lldb
+from lldbtest import *
+
+class TestFormats(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
+ def test_formats(self):
+ """Test format string functionality."""
+ self.buildDwarf ()
+ import pexpect
+ prompt = "(lldb) "
+ child = pexpect.spawn('%s %s -x -o "b main" -o r a.out' % (self.lldbHere, self.lldbOption))
+ # Turn on logging for what the child sends back.
+ if self.TraceOn():
+ child.logfile_read = sys.stdout
+ # So that the spawned lldb session gets shutdown durng teardown.
+ self.child = child
+
+ # Substitute 'Help!' for 'help' using the 'commands regex' mechanism.
+ child.expect_exact(prompt + 'target create "a.out"')
+ child.expect_exact(prompt + 'b main')
+ child.expect_exact(prompt + 'r')
+ child.expect_exact(prompt)
+ child.sendline()
+ # child.expect_exact(prompt + "target create")
+ #
+ # child.sendline("command regex 'Help__'")
+ # child.expect_exact(regex_prompt)
+ # child.sendline('s/^$/help/')
+ # child.expect_exact(regex_prompt1)
+ # child.sendline('')
+ # child.expect_exact(prompt)
+ # # Help!
+ # child.sendline('Help__')
+ # # If we see the familiar 'help' output, the test is done.
+ # child.expect('Debugger commands:')
+ # # Try and incorrectly remove "Help__" using "command unalias" and verify we fail
+ # child.sendline('command unalias Help__')
+ # child.expect_exact("error: 'Help__' is not an alias, it is a debugger command which can be removed using the 'command delete' command")
+ # child.expect_exact(prompt)
+ #
+ # # Delete the regex command using "command delete"
+ # child.sendline('command delete Help__')
+ # child.expect_exact(prompt)
+ # # Verify the command was removed
+ # child.sendline('Help__')
+ # child.expect_exact("error: 'Help__' is not a valid command")
+ # child.expect_exact(prompt)
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
Added: lldb/trunk/test/functionalities/format/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/format/main.c?rev=228207&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/format/main.c (added)
+++ lldb/trunk/test/functionalities/format/main.c Wed Feb 4 16:00:53 2015
@@ -0,0 +1,15 @@
+//===-- main.c --------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+int main (int argc, char const *argv[])
+{
+ printf("testing\n");
+ return 0;
+}
Modified: lldb/trunk/test/settings/TestSettings.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/settings/TestSettings.py?rev=228207&r1=228206&r2=228207&view=diff
==============================================================================
--- lldb/trunk/test/settings/TestSettings.py (original)
+++ lldb/trunk/test/settings/TestSettings.py Wed Feb 4 16:00:53 2015
@@ -123,7 +123,7 @@ class SettingsCommandTestCase(TestBase):
self.runCmd("settings show frame-format")
m = re.match(
- '^frame-format \(string\) = "(.*)\"$',
+ '^frame-format \(format-string\) = "(.*)\"$',
self.res.GetOutput())
self.assertTrue(m, "Bad settings string")
self.format_string = m.group(1)
More information about the lldb-commits
mailing list