70 changes: 69 additions & 1 deletion lldb/include/lldb/Target/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,18 @@ class EvaluateExpressionOptions
m_generate_debug_info = b;
}

bool
GetColorizeErrors () const
{
return m_ansi_color_errors;
}

void
SetColorizeErrors (bool b)
{
m_ansi_color_errors = b;
}

bool
GetTrapExceptions() const
{
Expand All @@ -453,6 +465,18 @@ class EvaluateExpressionOptions
m_trap_exceptions = b;
}

bool
GetREPLEnabled() const
{
return m_repl;
}

void
SetREPLEnabled (bool b)
{
m_repl = b;
}

void
SetCancelCallback (lldb::ExpressionCancelCallback callback, void *baton)
{
Expand All @@ -468,6 +492,37 @@ class EvaluateExpressionOptions
else
return m_cancel_callback (phase, m_cancel_callback_baton);
}

// Allows the expression contents to be remapped to point to the specified file and line
// using #line directives.
void
SetPoundLine (const char *path, uint32_t line) const
{
if (path && path[0])
{
m_pound_line_file = path;
m_pound_line_line = line;
}
else
{
m_pound_line_file.clear();
m_pound_line_line = 0;
}
}

const char *
GetPoundLineFilePath () const
{
if (m_pound_line_file.empty())
return NULL;
return m_pound_line_file.c_str();
}

uint32_t
GetPoundLineLine () const
{
return m_pound_line_line;
}

void
SetResultIsInternal (bool b)
Expand All @@ -493,13 +548,20 @@ class EvaluateExpressionOptions
bool m_stop_others;
bool m_debug;
bool m_trap_exceptions;
bool m_repl;
bool m_generate_debug_info;
bool m_ansi_color_errors;
bool m_result_is_internal;
lldb::DynamicValueType m_use_dynamic;
uint32_t m_timeout_usec;
uint32_t m_one_thread_timeout_usec;
lldb::ExpressionCancelCallback m_cancel_callback;
void *m_cancel_callback_baton;
// If m_pound_line_file is not empty and m_pound_line_line is non-zero,
// use #line %u "%s" before the expression content to remap where the source
// originates
mutable std::string m_pound_line_file;
mutable uint32_t m_pound_line_line;
};

//----------------------------------------------------------------------
Expand Down Expand Up @@ -1504,8 +1566,11 @@ class Target :

lldb::SearchFilterSP
GetSearchFilterForModuleAndCUList (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles);

lldb::REPLSP
GetREPL (lldb::LanguageType, bool can_create);

protected:
protected:
//------------------------------------------------------------------
// Member variables.
//------------------------------------------------------------------
Expand All @@ -1528,6 +1593,9 @@ class Target :
PathMappingList m_image_search_paths;
TypeSystemMap m_scratch_type_system_map;

typedef std::map<lldb::LanguageType, lldb::REPLSP> REPLMap;
REPLMap m_repl_map;

lldb::ClangASTImporterUP m_ast_importer_ap;
lldb::ClangModulesDeclVendorUP m_clang_modules_decl_vendor_ap;

Expand Down
9 changes: 7 additions & 2 deletions lldb/include/lldb/Utility/AnsiTerminal.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,13 @@
#define ANSI_CTRL_CONCEAL 8
#define ANSI_CTRL_CROSSED_OUT 9

#define ANSI_ESC_START "\033["
#define ANSI_ESC_END "m"
#define ANSI_ESC_START "\033["
#define ANSI_ESC_END "m"

#define ANSI_STR(s) #s
#define ANSI_DEF_STR(s) ANSI_STR(s)

#define ANSI_ESCAPE1(s) ANSI_ESC_START ANSI_DEF_STR(s) ANSI_ESC_END

#define ANSI_1_CTRL(ctrl1) "\033["##ctrl1 ANSI_ESC_END
#define ANSI_2_CTRL(ctrl1,ctrl2) "\033["##ctrl1";"##ctrl2 ANSI_ESC_END
Expand Down
2 changes: 2 additions & 0 deletions lldb/include/lldb/lldb-forward.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ class RegisterLocation;
class RegisterLocationList;
class RegisterValue;
class RegularExpression;
class REPL;
class Scalar;
class ScriptInterpreter;
class ScriptInterpreterLocker;
Expand Down Expand Up @@ -382,6 +383,7 @@ namespace lldb {
typedef std::shared_ptr<lldb_private::Queue> QueueSP;
typedef std::weak_ptr<lldb_private::Queue> QueueWP;
typedef std::shared_ptr<lldb_private::QueueItem> QueueItemSP;
typedef std::shared_ptr<lldb_private::REPL> REPLSP;
typedef std::shared_ptr<lldb_private::ScriptSummaryFormat> ScriptSummaryFormatSP;
typedef std::shared_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterSP;
typedef std::unique_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterUP;
Expand Down
1 change: 1 addition & 0 deletions lldb/include/lldb/lldb-private-interfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ namespace lldb_private
typedef lldb::InstrumentationRuntimeType (*InstrumentationRuntimeGetType) ();
typedef lldb::InstrumentationRuntimeSP (*InstrumentationRuntimeCreateInstance) (const lldb::ProcessSP &process_sp);
typedef lldb::TypeSystemSP (*TypeSystemCreateInstance) (lldb::LanguageType language, Module *module, Target *target);
typedef lldb::REPLSP (*REPLCreateInstance) (lldb::LanguageType language, Target *target);
typedef void (*TypeSystemEnumerateSupportedLanguages) (std::set<lldb::LanguageType> &languages_for_types, std::set<lldb::LanguageType> &languages_for_expressions);
typedef int (*ComparisonFunction)(const void *, const void *);
typedef void (*DebuggerInitializeCallback)(Debugger &debugger);
Expand Down
6 changes: 6 additions & 0 deletions lldb/lldb.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@
449ACC98197DEA0B008D175E /* FastDemangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 449ACC96197DE9EC008D175E /* FastDemangle.cpp */; };
490A36C0180F0E6F00BA31F8 /* PlatformWindows.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 490A36BD180F0E6F00BA31F8 /* PlatformWindows.cpp */; };
490A966B1628C3BF00F0002E /* SBDeclaration.h in Headers */ = {isa = PBXBuildFile; fileRef = 9452573816262CEF00325455 /* SBDeclaration.h */; settings = {ATTRIBUTES = (Public, ); }; };
4939EA8D1BD56B6D00084382 /* REPL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4939EA8C1BD56B6D00084382 /* REPL.cpp */; };
494260DA14579144003C1C78 /* VerifyDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 494260D914579144003C1C78 /* VerifyDecl.cpp */; };
4959511F1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4959511E1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp */; };
4966DCC4148978A10028481B /* ClangExternalASTSourceCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4966DCC3148978A10028481B /* ClangExternalASTSourceCommon.cpp */; };
Expand Down Expand Up @@ -2254,6 +2255,8 @@
491193501226386000578B7F /* ASTStructExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTStructExtractor.cpp; path = ExpressionParser/Clang/ASTStructExtractor.cpp; sourceTree = "<group>"; };
49307AAD11DEA4D90081F992 /* IRForTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRForTarget.cpp; path = ExpressionParser/Clang/IRForTarget.cpp; sourceTree = "<group>"; };
49307AB111DEA4F20081F992 /* IRForTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRForTarget.h; path = ExpressionParser/Clang/IRForTarget.h; sourceTree = "<group>"; };
4939EA8B1BD56B3700084382 /* REPL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = REPL.h; path = include/lldb/Expression/REPL.h; sourceTree = "<group>"; };
4939EA8C1BD56B6D00084382 /* REPL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = REPL.cpp; path = source/Expression/REPL.cpp; sourceTree = "<group>"; };
494260D7145790D5003C1C78 /* VerifyDecl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VerifyDecl.h; path = include/lldb/Symbol/VerifyDecl.h; sourceTree = "<group>"; };
494260D914579144003C1C78 /* VerifyDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VerifyDecl.cpp; path = source/Symbol/VerifyDecl.cpp; sourceTree = "<group>"; };
49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExpressionParser.cpp; path = ExpressionParser/Clang/ClangExpressionParser.cpp; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4447,6 +4450,8 @@
496B01581406DE8900F830D5 /* IRInterpreter.cpp */,
49DCF6FF170E6FD90092F75E /* Materializer.h */,
49DCF700170E70120092F75E /* Materializer.cpp */,
4939EA8B1BD56B3700084382 /* REPL.h */,
4939EA8C1BD56B6D00084382 /* REPL.cpp */,
);
name = Expression;
sourceTree = "<group>";
Expand Down Expand Up @@ -6371,6 +6376,7 @@
2689005F13353E0E00698AC0 /* ClangFunctionCaller.cpp in Sources */,
2689006013353E0E00698AC0 /* ClangExpressionDeclMap.cpp in Sources */,
2689006113353E0E00698AC0 /* ClangExpressionParser.cpp in Sources */,
4939EA8D1BD56B6D00084382 /* REPL.cpp in Sources */,
B5EFAE861AE53B1D007059F3 /* RegisterContextFreeBSD_arm.cpp in Sources */,
2689006313353E0E00698AC0 /* ClangPersistentVariables.cpp in Sources */,
2689006413353E0E00698AC0 /* ClangUserExpression.cpp in Sources */,
Expand Down
72 changes: 72 additions & 0 deletions lldb/source/Core/Debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ g_properties[] =
{ "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)." },
{ "auto-indent", OptionValue::eTypeBoolean , true, true , NULL, NULL, "If true, LLDB will auto indent/outdent code. Currently only supported in the REPL (default: true)." },
{ "print-decls", OptionValue::eTypeBoolean , true, true , NULL, NULL, "If true, LLDB will print the values of variables declared in an expression. Currently only supported in the REPL (default: true)." },
{ "tab-size", OptionValue::eTypeUInt64 , true, 4 , NULL, NULL, "The tab size to use when indenting code in multi-line input mode (default: 4)." },
{ "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 }
};
Expand All @@ -177,6 +180,9 @@ enum
ePropertyUseExternalEditor,
ePropertyUseColor,
ePropertyAutoOneLineSummaries,
ePropertyAutoIndent,
ePropertyPrintDecls,
ePropertyTabSize,
ePropertyEscapeNonPrintables
};

Expand Down Expand Up @@ -392,6 +398,49 @@ Debugger::GetEscapeNonPrintables () const
return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true);
}

bool
Debugger::GetAutoIndent () const
{
const uint32_t idx = ePropertyAutoIndent;
return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true);
}

bool
Debugger::SetAutoIndent (bool b)
{
const uint32_t idx = ePropertyAutoIndent;
return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
}

bool
Debugger::GetPrintDecls () const
{
const uint32_t idx = ePropertyPrintDecls;
return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true);
}

bool
Debugger::SetPrintDecls (bool b)
{
const uint32_t idx = ePropertyPrintDecls;
return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
}

uint32_t
Debugger::GetTabSize () const
{
const uint32_t idx = ePropertyTabSize;
return m_collection_sp->GetPropertyAtIndexAsUInt64 (NULL, idx, g_properties[idx].default_uint_value);
}

bool
Debugger::SetTabSize (uint32_t tab_size)
{
const uint32_t idx = ePropertyTabSize;
return m_collection_sp->SetPropertyAtIndexAsUInt64 (NULL, idx, tab_size);
}


#pragma mark Debugger

//const DebuggerPropertiesSP &
Expand Down Expand Up @@ -919,6 +968,12 @@ Debugger::IsTopIOHandler (const lldb::IOHandlerSP& reader_sp)
return m_input_reader_stack.IsTop (reader_sp);
}

bool
Debugger::CheckTopIOHandlerTypes (IOHandler::Type top_type, IOHandler::Type second_top_type)
{
return m_input_reader_stack.CheckTopIOHandlerTypes (top_type, second_top_type);
}

void
Debugger::PrintAsync (const char *s, size_t len, bool is_stdout)
{
Expand Down Expand Up @@ -1683,6 +1738,12 @@ Debugger::IOHandlerThread (lldb::thread_arg_t arg)
return NULL;
}

bool
Debugger::HasIOHandlerThread()
{
return m_io_handler_thread.IsJoinable();
}

bool
Debugger::StartIOHandlerThread()
{
Expand All @@ -1706,6 +1767,17 @@ Debugger::StopIOHandlerThread()
}
}

void
Debugger::JoinIOHandlerThread()
{
if (HasIOHandlerThread())
{
thread_result_t result;
m_io_handler_thread.Join(&result);
m_io_handler_thread = LLDB_INVALID_HOST_THREAD;
}
}

Target *
Debugger::GetDummyTarget()
{
Expand Down
100 changes: 100 additions & 0 deletions lldb/source/Core/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2648,6 +2648,106 @@ PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackForPluginName (co
return NULL;
}

#pragma mark REPL

struct REPLInstance
{
REPLInstance() :
name(),
description(),
create_callback(NULL)
{
}

ConstString name;
std::string description;
REPLCreateInstance create_callback;
};

typedef std::vector<REPLInstance> REPLInstances;

static Mutex &
GetREPLMutex ()
{
static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive);
return g_instances_mutex;
}

static REPLInstances &
GetREPLInstances ()
{
static REPLInstances g_instances;
return g_instances;
}

bool
PluginManager::RegisterPlugin (const ConstString &name,
const char *description,
REPLCreateInstance create_callback)
{
if (create_callback)
{
REPLInstance instance;
assert ((bool)name);
instance.name = name;
if (description && description[0])
instance.description = description;
instance.create_callback = create_callback;
Mutex::Locker locker (GetREPLMutex ());
GetREPLInstances ().push_back (instance);
}
return false;
}

bool
PluginManager::UnregisterPlugin (REPLCreateInstance create_callback)
{
if (create_callback)
{
Mutex::Locker locker (GetREPLMutex ());
REPLInstances &instances = GetREPLInstances ();

REPLInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++ pos)
{
if (pos->create_callback == create_callback)
{
instances.erase(pos);
return true;
}
}
}
return false;
}

REPLCreateInstance
PluginManager::GetREPLCreateCallbackAtIndex (uint32_t idx)
{
Mutex::Locker locker (GetREPLMutex ());
REPLInstances &instances = GetREPLInstances ();
if (idx < instances.size())
return instances[idx].create_callback;
return NULL;
}

REPLCreateInstance
PluginManager::GetREPLCreateCallbackForPluginName (const ConstString &name)
{
if (name)
{
Mutex::Locker locker (GetREPLMutex ());
REPLInstances &instances = GetREPLInstances ();

REPLInstances::iterator pos, end = instances.end();
for (pos = instances.begin(); pos != end; ++ pos)
{
if (name == pos->name)
return pos->create_callback;
}
}
return NULL;
}

#pragma mark PluginManager

void
Expand Down
650 changes: 650 additions & 0 deletions lldb/source/Expression/REPL.cpp

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion lldb/source/Expression/UserExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,9 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp,
Error &error)
Error &error,
uint32_t line_offset,
lldb::ModuleSP *jit_module_sp_ptr)
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));

Expand Down Expand Up @@ -567,6 +569,10 @@ UserExpression::Evaluate (ExecutionContext &exe_ctx,
}
else
{
// If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created
if (jit_module_sp_ptr && user_expression_sp->m_execution_unit_sp)
*jit_module_sp_ptr = user_expression_sp->m_execution_unit_sp->GetJITModule();

lldb::ExpressionVariableSP expr_result;

if (execution_policy == eExecutionPolicyNever &&
Expand Down
14 changes: 14 additions & 0 deletions lldb/source/Host/common/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include <sys/ioctl.h>
#endif

#include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors()

#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
Expand Down Expand Up @@ -1051,7 +1053,11 @@ File::CalculateInteractiveAndTerminal ()
if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0)
{
if (window_size.ws_col > 0)
{
m_is_real_terminal = eLazyBoolYes;
if (llvm::sys::Process::FileDescriptorHasColors(fd))
m_supports_colors = eLazyBoolYes;
}
}
}
#endif
Expand All @@ -1074,3 +1080,11 @@ File::GetIsRealTerminal ()
return m_is_real_terminal == eLazyBoolYes;
}

bool
File::GetIsTerminalWithColors ()
{
if (m_supports_colors == eLazyBoolCalculate)
CalculateInteractiveAndTerminal();
return m_supports_colors == eLazyBoolYes;
}

11 changes: 10 additions & 1 deletion lldb/source/Interpreter/CommandInterpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,16 @@ g_properties[] =
{ "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." },
{ "prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." },
{ "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will stop running a 'command source' script upon encountering an error." },
{ "space-repl-prompts", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, blank lines will be printed between between REPL submissions." },
{ nullptr , OptionValue::eTypeInvalid, true, 0 , nullptr, nullptr, nullptr }
};

enum
{
ePropertyExpandRegexAliases = 0,
ePropertyPromptOnQuit = 1,
ePropertyStopCmdSourceOnError = 2
ePropertyStopCmdSourceOnError = 2,
eSpaceReplPrompts = 3
};

ConstString &
Expand Down Expand Up @@ -167,6 +169,13 @@ CommandInterpreter::GetStopCmdSourceOnError () const
return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
}

bool
CommandInterpreter::GetSpaceReplPrompts () const
{
const uint32_t idx = eSpaceReplPrompts;
return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
}

void
CommandInterpreter::Initialize ()
{
Expand Down
32 changes: 32 additions & 0 deletions lldb/source/Target/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/REPL.h"
#include "lldb/Expression/UserExpression.h"
#include "Plugins/ExpressionParser/Clang/ClangASTSource.h"
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
Expand Down Expand Up @@ -211,6 +212,37 @@ Target::GetProcessSP () const
return m_process_sp;
}

lldb::REPLSP
Target::GetREPL (lldb::LanguageType language, bool can_create)
{
if (language == eLanguageTypeUnknown)
{
return REPLSP(); // must provide a language
}

REPLMap::iterator pos = m_repl_map.find(language);

if (pos != m_repl_map.end())
{
return pos->second;
}

if (!can_create)
{
return lldb::REPLSP();
}

lldb::REPLSP ret = REPL::Create(language, this);

if (ret)
{
m_repl_map[language] = ret;
return m_repl_map[language];
}

return nullptr;
}

void
Target::Destroy()
{
Expand Down