summaryrefslogtreecommitdiffstats
path: root/lldb/source/Interpreter
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Interpreter')
-rw-r--r--lldb/source/Interpreter/CommandCompletions.cpp414
-rw-r--r--lldb/source/Interpreter/CommandContext.cpp77
-rw-r--r--lldb/source/Interpreter/CommandInterpreter.cpp1300
-rw-r--r--lldb/source/Interpreter/CommandObject.cpp448
-rw-r--r--lldb/source/Interpreter/CommandObjectCrossref.cpp92
-rw-r--r--lldb/source/Interpreter/CommandObjectMultiword.cpp263
-rw-r--r--lldb/source/Interpreter/CommandObjectRegexCommand.cpp123
-rw-r--r--lldb/source/Interpreter/CommandReturnObject.cpp175
-rw-r--r--lldb/source/Interpreter/ScriptInterpreter.cpp66
-rw-r--r--lldb/source/Interpreter/ScriptInterpreterNone.cpp38
-rw-r--r--lldb/source/Interpreter/ScriptInterpreterPython.cpp830
-rw-r--r--lldb/source/Interpreter/StateVariable.cpp320
-rw-r--r--lldb/source/Interpreter/embedded_interpreter.py90
13 files changed, 4236 insertions, 0 deletions
diff --git a/lldb/source/Interpreter/CommandCompletions.cpp b/lldb/source/Interpreter/CommandCompletions.cpp
new file mode 100644
index 00000000000..a299ffb098f
--- /dev/null
+++ b/lldb/source/Interpreter/CommandCompletions.cpp
@@ -0,0 +1,414 @@
+//===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Core/FileSpecList.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+
+
+using namespace lldb_private;
+
+CommandCompletions::CommonCompletionElement
+CommandCompletions::g_common_completions[] =
+{
+ {eCustomCompletion, NULL},
+ {eSourceFileCompletion, CommandCompletions::SourceFiles},
+ {eDiskFileCompletion, NULL},
+ {eSymbolCompletion, CommandCompletions::Symbols},
+ {eModuleCompletion, CommandCompletions::Modules},
+ {eNoCompletion, NULL} // This one has to be last in the list.
+};
+
+bool
+CommandCompletions::InvokeCommonCompletionCallbacks (uint32_t completion_mask,
+ const char *completion_str,
+ int match_start_point,
+ int max_return_elements,
+ lldb_private::CommandInterpreter *interpreter,
+ SearchFilter *searcher,
+ lldb_private::StringList &matches)
+{
+ bool handled = false;
+
+ if (completion_mask & eCustomCompletion)
+ return false;
+
+ for (int i = 0; ; i++)
+ {
+ if (g_common_completions[i].type == eNoCompletion)
+ break;
+ else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
+ && g_common_completions[i].callback != NULL)
+ {
+ handled = true;
+ g_common_completions[i].callback (completion_str,
+ match_start_point,
+ max_return_elements,
+ interpreter,
+ searcher,
+ matches);
+ }
+ }
+ return handled;
+}
+
+int
+CommandCompletions::SourceFiles (const char *partial_file_name,
+ int match_start_point,
+ int max_return_elements,
+ lldb_private::CommandInterpreter *interpreter,
+ SearchFilter *searcher,
+ lldb_private::StringList &matches)
+{
+ // Find some way to switch "include support files..."
+ SourceFileCompleter completer (false, partial_file_name, match_start_point, max_return_elements, interpreter,
+ matches);
+
+ if (searcher == NULL)
+ {
+ lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
+ SearchFilter null_searcher (target_sp);
+ completer.DoCompletion (&null_searcher);
+ }
+ else
+ {
+ completer.DoCompletion (searcher);
+ }
+ return matches.GetSize();
+}
+
+int
+CommandCompletions::Modules (const char *partial_file_name,
+ int match_start_point,
+ int max_return_elements,
+ lldb_private::CommandInterpreter *interpreter,
+ SearchFilter *searcher,
+ lldb_private::StringList &matches)
+{
+ ModuleCompleter completer(partial_file_name, match_start_point, max_return_elements, interpreter, matches);
+
+ if (searcher == NULL)
+ {
+ lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
+ SearchFilter null_searcher (target_sp);
+ completer.DoCompletion (&null_searcher);
+ }
+ else
+ {
+ completer.DoCompletion (searcher);
+ }
+ return matches.GetSize();
+}
+
+int
+CommandCompletions::Symbols (const char *partial_file_name,
+ int match_start_point,
+ int max_return_elements,
+ lldb_private::CommandInterpreter *interpreter,
+ SearchFilter *searcher,
+ lldb_private::StringList &matches)
+{
+ SymbolCompleter completer(partial_file_name, match_start_point, max_return_elements, interpreter, matches);
+
+ if (searcher == NULL)
+ {
+ lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
+ SearchFilter null_searcher (target_sp);
+ completer.DoCompletion (&null_searcher);
+ }
+ else
+ {
+ completer.DoCompletion (searcher);
+ }
+ return matches.GetSize();
+}
+
+CommandCompletions::Completer::Completer (
+ const char *completion_str,
+ int match_start_point,
+ int max_return_elements,
+ CommandInterpreter *interpreter,
+ StringList &matches
+) :
+ m_completion_str (completion_str),
+ m_match_start_point (match_start_point),
+ m_max_return_elements (max_return_elements),
+ m_interpreter (interpreter),
+ m_matches (matches)
+{
+}
+
+CommandCompletions::Completer::~Completer ()
+{
+
+}
+
+//----------------------------------------------------------------------
+// SourceFileCompleter
+//----------------------------------------------------------------------
+
+CommandCompletions::SourceFileCompleter::SourceFileCompleter (
+ bool include_support_files,
+ const char *completion_str,
+ int match_start_point,
+ int max_return_elements,
+ CommandInterpreter *interpreter,
+ StringList &matches
+) :
+ CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches),
+ m_include_support_files (include_support_files),
+ m_matching_files()
+{
+ FileSpec partial_spec (m_completion_str.c_str());
+ m_file_name = partial_spec.GetFilename().GetCString();
+ m_dir_name = partial_spec.GetDirectory().GetCString();
+}
+
+Searcher::Depth
+CommandCompletions::SourceFileCompleter::GetDepth()
+{
+ return eDepthCompUnit;
+}
+
+Searcher::CallbackReturn
+CommandCompletions::SourceFileCompleter::SearchCallback (
+ SearchFilter &filter,
+ SymbolContext &context,
+ Address *addr,
+ bool complete
+)
+{
+ if (context.comp_unit != NULL)
+ {
+ if (m_include_support_files)
+ {
+ FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
+ for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
+ {
+ const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
+ const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
+ const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
+ bool match = false;
+ if (m_file_name && sfile_file_name
+ && strstr (sfile_file_name, m_file_name) == sfile_file_name)
+ match = true;
+ if (match && m_dir_name && sfile_dir_name
+ && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
+ match = false;
+
+ if (match)
+ {
+ m_matching_files.AppendIfUnique(sfile_spec);
+ }
+ }
+
+ }
+ else
+ {
+ const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
+ const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
+
+ bool match = false;
+ if (m_file_name && cur_file_name
+ && strstr (cur_file_name, m_file_name) == cur_file_name)
+ match = true;
+
+ if (match && m_dir_name && cur_dir_name
+ && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
+ match = false;
+
+ if (match)
+ {
+ m_matching_files.AppendIfUnique(context.comp_unit);
+ }
+ }
+ }
+ return Searcher::eCallbackReturnContinue;
+}
+
+size_t
+CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
+{
+ filter->Search (*this);
+ // Now convert the filelist to completions:
+ for (size_t i = 0; i < m_matching_files.GetSize(); i++)
+ {
+ m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
+ }
+ return m_matches.GetSize();
+
+}
+
+//----------------------------------------------------------------------
+// SymbolCompleter
+//----------------------------------------------------------------------
+
+static bool
+regex_chars (const char comp)
+{
+ if (comp == '[' || comp == ']' || comp == '(' || comp == ')')
+ return true;
+ else
+ return false;
+}
+CommandCompletions::SymbolCompleter::SymbolCompleter (
+ const char *completion_str,
+ int match_start_point,
+ int max_return_elements,
+ CommandInterpreter *interpreter,
+ StringList &matches
+) :
+ CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches)
+{
+ std::string regex_str ("^");
+ regex_str.append(completion_str);
+ regex_str.append(".*");
+ std::string::iterator pos;
+
+ pos = find_if(regex_str.begin(), regex_str.end(), regex_chars);
+ while (pos < regex_str.end()) {
+ pos = regex_str.insert(pos, '\\');
+ pos += 2;
+ pos = find_if(pos, regex_str.end(), regex_chars);
+ }
+ m_regex.Compile(regex_str.c_str());
+}
+
+Searcher::Depth
+CommandCompletions::SymbolCompleter::GetDepth()
+{
+ return eDepthModule;
+}
+
+Searcher::CallbackReturn
+CommandCompletions::SymbolCompleter::SearchCallback (
+ SearchFilter &filter,
+ SymbolContext &context,
+ Address *addr,
+ bool complete
+)
+{
+ SymbolContextList func_list;
+ SymbolContextList sym_list;
+
+ if (context.module_sp != NULL)
+ {
+ if (context.module_sp)
+ {
+ context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, lldb::eSymbolTypeCode, sym_list);
+ context.module_sp->FindFunctions (m_regex, true, func_list);
+ }
+
+ SymbolContext sc;
+ // Now add the functions & symbols to the list - only add if unique:
+ for (int i = 0; i < func_list.GetSize(); i++)
+ {
+ if (func_list.GetContextAtIndex(i, sc))
+ {
+ if (sc.function)
+ {
+ m_match_set.insert (sc.function->GetMangled().GetDemangledName());
+ }
+ }
+ }
+
+ for (int i = 0; i < sym_list.GetSize(); i++)
+ {
+ if (sym_list.GetContextAtIndex(i, sc))
+ {
+ if (sc.symbol && sc.symbol->GetAddressRangePtr())
+ {
+ m_match_set.insert (sc.symbol->GetMangled().GetDemangledName());
+ }
+ }
+ }
+ }
+ return Searcher::eCallbackReturnContinue;
+}
+
+size_t
+CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
+{
+ filter->Search (*this);
+ collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
+ for (pos = m_match_set.begin(); pos != end; pos++)
+ m_matches.AppendString((*pos).GetCString());
+
+ return m_matches.GetSize();
+}
+
+//----------------------------------------------------------------------
+// ModuleCompleter
+//----------------------------------------------------------------------
+CommandCompletions::ModuleCompleter::ModuleCompleter (
+ const char *completion_str,
+ int match_start_point,
+ int max_return_elements,
+ CommandInterpreter *interpreter,
+ StringList &matches
+) :
+ CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches)
+{
+ FileSpec partial_spec (m_completion_str.c_str());
+ m_file_name = partial_spec.GetFilename().GetCString();
+ m_dir_name = partial_spec.GetDirectory().GetCString();
+}
+
+Searcher::Depth
+CommandCompletions::ModuleCompleter::GetDepth()
+{
+ return eDepthModule;
+}
+
+Searcher::CallbackReturn
+CommandCompletions::ModuleCompleter::SearchCallback (
+ SearchFilter &filter,
+ SymbolContext &context,
+ Address *addr,
+ bool complete
+)
+{
+ if (context.module_sp != NULL)
+ {
+ const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
+ const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
+
+ bool match = false;
+ if (m_file_name && cur_file_name
+ && strstr (cur_file_name, m_file_name) == cur_file_name)
+ match = true;
+
+ if (match && m_dir_name && cur_dir_name
+ && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
+ match = false;
+
+ if (match)
+ {
+ m_matches.AppendString (cur_file_name);
+ }
+ }
+ return Searcher::eCallbackReturnContinue;
+}
+
+size_t
+CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
+{
+ filter->Search (*this);
+ return m_matches.GetSize();
+}
+
+
+
diff --git a/lldb/source/Interpreter/CommandContext.cpp b/lldb/source/Interpreter/CommandContext.cpp
new file mode 100644
index 00000000000..012611c5262
--- /dev/null
+++ b/lldb/source/Interpreter/CommandContext.cpp
@@ -0,0 +1,77 @@
+//===-- CommandContext.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/Interpreter/CommandContext.h"
+
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandContext::CommandContext () :
+ m_exe_ctx ()
+{
+}
+
+CommandContext::~CommandContext ()
+{
+}
+
+Target *
+CommandContext::GetTarget()
+{
+ return Debugger::GetSharedInstance().GetCurrentTarget().get();
+}
+
+
+ExecutionContext &
+CommandContext::GetExecutionContext()
+{
+ return m_exe_ctx;
+}
+
+void
+CommandContext::Update (ExecutionContext *override_context)
+{
+ m_exe_ctx.Clear();
+
+ if (override_context != NULL)
+ {
+ m_exe_ctx.target = override_context->target;
+ m_exe_ctx.process = override_context->process;
+ m_exe_ctx.thread = override_context->thread;
+ m_exe_ctx.frame = override_context->frame;
+ }
+ else
+ {
+ TargetSP target_sp (Debugger::GetSharedInstance().GetCurrentTarget());
+ if (target_sp)
+ {
+ m_exe_ctx.process = target_sp->GetProcessSP().get();
+ if (m_exe_ctx.process && m_exe_ctx.process->IsRunning() == false)
+ {
+ m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetCurrentThread().get();
+ if (m_exe_ctx.thread == NULL)
+ m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
+ if (m_exe_ctx.thread)
+ {
+ m_exe_ctx.frame = m_exe_ctx.thread->GetCurrentFrame().get();
+ if (m_exe_ctx.frame == NULL)
+ m_exe_ctx.frame = m_exe_ctx.thread->GetStackFrameAtIndex (0).get();
+ }
+ }
+ }
+ }
+}
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
new file mode 100644
index 00000000000..ed85b33bab3
--- /dev/null
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -0,0 +1,1300 @@
+//===-- CommandInterpreter.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string>
+
+#include <getopt.h>
+#include <stdlib.h>
+
+#include "CommandObjectAdd.h"
+#include "CommandObjectAlias.h"
+#include "CommandObjectAppend.h"
+#include "CommandObjectApropos.h"
+#include "CommandObjectArgs.h"
+#include "CommandObjectBreakpoint.h"
+#include "CommandObjectCall.h"
+#include "CommandObjectDelete.h"
+#include "CommandObjectDisassemble.h"
+#include "CommandObjectExpression.h"
+#include "CommandObjectFile.h"
+#include "CommandObjectFrame.h"
+#include "CommandObjectHelp.h"
+#include "CommandObjectImage.h"
+#include "CommandObjectInfo.h"
+#include "CommandObjectLog.h"
+#include "CommandObjectMemory.h"
+#include "CommandObjectProcess.h"
+#include "CommandObjectQuit.h"
+#include "CommandObjectRegexCommand.h"
+#include "CommandObjectRegister.h"
+#include "CommandObjectRemove.h"
+#include "CommandObjectScript.h"
+#include "CommandObjectSelect.h"
+#include "CommandObjectSet.h"
+#include "CommandObjectSettings.h"
+#include "CommandObjectShow.h"
+#include "CommandObjectSource.h"
+#include "CommandObjectSourceFile.h"
+#include "CommandObjectStatus.h"
+#include "CommandObjectSyntax.h"
+#include "CommandObjectTarget.h"
+#include "CommandObjectThread.h"
+#include "CommandObjectTranslate.h"
+#include "CommandObjectUnalias.h"
+#include "CommandObjectVariable.h"
+
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/TargetList.h"
+
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandInterpreter::CommandInterpreter
+(
+ ScriptLanguage script_language,
+ bool synchronous_execution,
+ Listener *listener,
+ SourceManager& source_manager
+) :
+ Broadcaster ("CommandInterpreter"),
+ m_script_language (script_language),
+ m_synchronous_execution (synchronous_execution),
+ m_listener (listener),
+ m_source_manager (source_manager)
+{
+}
+
+void
+CommandInterpreter::Initialize ()
+{
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+ CommandReturnObject result;
+
+ LoadCommandDictionary ();
+
+ InitializeVariables ();
+
+ // Set up some initial aliases.
+ result.Clear(); HandleCommand ("alias q quit", false, result);
+ result.Clear(); HandleCommand ("alias run process launch", false, result);
+ result.Clear(); HandleCommand ("alias r process launch", false, result);
+ result.Clear(); HandleCommand ("alias c process continue", false, result);
+ result.Clear(); HandleCommand ("alias continue process continue", false, result);
+ result.Clear(); HandleCommand ("alias expr expression", false, result);
+ result.Clear(); HandleCommand ("alias exit quit", false, result);
+ result.Clear(); HandleCommand ("alias bt thread backtrace", false, result);
+ result.Clear(); HandleCommand ("alias si thread step-inst", false, result);
+ result.Clear(); HandleCommand ("alias step thread step-in", false, result);
+ result.Clear(); HandleCommand ("alias s thread step-in", false, result);
+ result.Clear(); HandleCommand ("alias next thread step-over", false, result);
+ result.Clear(); HandleCommand ("alias n thread step-over", false, result);
+ result.Clear(); HandleCommand ("alias finish thread step-out", false, result);
+ result.Clear(); HandleCommand ("alias x memory read", false, result);
+ result.Clear(); HandleCommand ("alias l source-file", false, result);
+ result.Clear(); HandleCommand ("alias list source-file", false, result);
+}
+
+void
+CommandInterpreter::InitializeVariables ()
+{
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+ m_variables["prompt"] =
+ StateVariableSP (new StateVariable ("prompt",
+ "(lldb) ",
+ false,
+ "The debugger prompt displayed for the user.",
+ StateVariable::BroadcastPromptChange));
+
+ m_variables["run-args"] =
+ StateVariableSP (new StateVariable ("run-args",
+ (Args*)NULL,
+ "An argument list containing the arguments to be passed to the executable when it is launched."));
+
+
+ m_variables["env-vars"] =
+ StateVariableSP (new StateVariable ("env-vars",
+ (Args*)NULL,
+ "A list of strings containing the environment variables to be passed to the executable's environment."));
+
+ m_variables["input-path"] =
+ StateVariableSP (new StateVariable ("input-path",
+ "/dev/stdin",
+ false,
+ "The file/path to be used by the executable program for reading its input."));
+
+ m_variables["output-path"] =
+ StateVariableSP (new StateVariable ( "output-path",
+ "/dev/stdout",
+ false,
+ "The file/path to be used by the executable program for writing its output."));
+
+ m_variables["error-path"] =
+ StateVariableSP (new StateVariable ("error-path",
+ "/dev/stderr",
+ false,
+ "The file/path to be used by the executable program for writing its error messages."));
+
+ m_variables["arch"] =
+ StateVariableSP (new StateVariable ("arch",
+ "",
+ false,
+ "The architecture to be used for running the executable (e.g. i386, x86_64, etc)."));
+
+ m_variables["script-lang"] =
+ StateVariableSP (new StateVariable ("script-lang",
+ "Python",
+ false,
+ "The script language to be used for evaluating user-written scripts.",
+ StateVariable::VerifyScriptLanguage));
+
+ m_variables["term-width"] =
+ StateVariableSP (new StateVariable ("term-width",
+ 80,
+ "The maximum number of columns to use for displaying text."));
+
+}
+
+const char *
+CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg)
+{
+ // This function has not yet been implemented.
+
+ // Look for any embedded script command
+ // If found,
+ // get interpreter object from the command dictionary,
+ // call execute_one_command on it,
+ // get the results as a string,
+ // substitute that string for current stuff.
+
+ return arg;
+}
+
+
+void
+CommandInterpreter::LoadCommandDictionary ()
+{
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+ // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT ***
+ //
+ // Command objects that are used as cross reference objects (i.e. they inherit from CommandObjectCrossref)
+ // *MUST* be created and put into the command dictionary *BEFORE* any multi-word commands (which may use
+ // the cross-referencing stuff) are created!!!
+ //
+ // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT ***
+
+
+ // Command objects that inherit from CommandObjectCrossref must be created before other command objects
+ // are created. This is so that when another command is created that needs to go into a crossref object,
+ // the crossref object exists and is ready to take the cross reference. Put the cross referencing command
+ // objects into the CommandDictionary now, so they are ready for use when the other commands get created.
+
+ m_command_dict["select"] = CommandObjectSP (new CommandObjectSelect ());
+ m_command_dict["info"] = CommandObjectSP (new CommandObjectInfo ());
+ m_command_dict["delete"] = CommandObjectSP (new CommandObjectDelete ());
+
+ // Non-CommandObjectCrossref commands can now be created.
+
+ //m_command_dict["add"] = CommandObjectSP (new CommandObjectAdd ());
+ m_command_dict["alias"] = CommandObjectSP (new CommandObjectAlias ());
+ m_command_dict["append"] = CommandObjectSP (new CommandObjectAppend ());
+ m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos ());
+ //m_command_dict["args"] = CommandObjectSP (new CommandObjectArgs ());
+ m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (this));
+ m_command_dict["call"] = CommandObjectSP (new CommandObjectCall ());
+ m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble ());
+ m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression ());
+ m_command_dict["file"] = CommandObjectSP (new CommandObjectFile ());
+ m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (this));
+ m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp ());
+ m_command_dict["image"] = CommandObjectSP (new CommandObjectImage (this));
+ m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (this));
+ m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (this));
+ m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (this));
+ m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit ());
+ m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (this));
+ //m_command_dict["remove"] = CommandObjectSP (new CommandObjectRemove ());
+ m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (m_script_language));
+ m_command_dict["set"] = CommandObjectSP (new CommandObjectSet ());
+ m_command_dict["settings"] = CommandObjectSP (new CommandObjectSettings ());
+ m_command_dict["show"] = CommandObjectSP (new CommandObjectShow ());
+ m_command_dict["source"] = CommandObjectSP (new CommandObjectSource ());
+ m_command_dict["source-file"] = CommandObjectSP (new CommandObjectSourceFile ());
+ //m_command_dict["syntax"] = CommandObjectSP (new CommandObjectSyntax ());
+ m_command_dict["status"] = CommandObjectSP (new CommandObjectStatus ());
+ m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (this));
+ m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (this));
+ //m_command_dict["translate"] = CommandObjectSP (new CommandObjectTranslate ());
+ m_command_dict["unalias"] = CommandObjectSP (new CommandObjectUnalias ());
+ m_command_dict["variable"] = CommandObjectSP (new CommandObjectVariable (this));
+
+ std::auto_ptr<CommandObjectRegexCommand>
+ break_regex_cmd_ap(new CommandObjectRegexCommand ("regexp-break",
+ "Smart breakpoint command (using regular expressions).",
+ "regexp-break [<file>:<line>]\nregexp-break [<address>]\nregexp-break <...>", 2));
+ if (break_regex_cmd_ap.get())
+ {
+ if (break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2") &&
+ break_regex_cmd_ap->AddRegexCommand("^(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1") &&
+ break_regex_cmd_ap->AddRegexCommand("^[\"']?([-+]\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'") &&
+ break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list") &&
+ break_regex_cmd_ap->AddRegexCommand("^(-.*)$", "breakpoint set %1") &&
+ break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"))
+ {
+ CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
+ m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
+ }
+ }
+}
+
+int
+CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases,
+ StringList &matches)
+{
+ CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches);
+
+ if (include_aliases)
+ {
+ CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches);
+ }
+
+ return matches.GetSize();
+}
+
+CommandObjectSP
+CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
+{
+ CommandObject::CommandMap::iterator pos;
+ CommandObjectSP ret_val;
+
+ std::string cmd(cmd_cstr);
+
+ if (HasCommands())
+ {
+ pos = m_command_dict.find(cmd);
+ if (pos != m_command_dict.end())
+ ret_val = pos->second;
+ }
+
+ if (include_aliases && HasAliases())
+ {
+ pos = m_alias_dict.find(cmd);
+ if (pos != m_alias_dict.end())
+ ret_val = pos->second;
+ }
+
+ if (HasUserCommands())
+ {
+ pos = m_user_dict.find(cmd);
+ if (pos != m_user_dict.end())
+ ret_val = pos->second;
+ }
+
+ if (!exact && ret_val == NULL)
+ {
+ StringList local_matches;
+ if (matches == NULL)
+ matches = &local_matches;
+
+ int num_cmd_matches = 0;
+ int num_alias_matches = 0;
+ int num_user_matches = 0;
+ if (HasCommands())
+ {
+ num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
+ }
+
+ if (num_cmd_matches == 1)
+ {
+ cmd.assign(matches->GetStringAtIndex(0));
+ pos = m_command_dict.find(cmd);
+ if (pos != m_command_dict.end())
+ ret_val = pos->second;
+ }
+
+ if (num_cmd_matches != 1 && include_aliases && HasAliases())
+ {
+ num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);
+
+ }
+
+ if (num_alias_matches == 1)
+ {
+ cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
+ pos = m_alias_dict.find(cmd);
+ if (pos != m_alias_dict.end())
+ {
+ matches->Clear();
+ matches->AppendString (cmd.c_str());
+
+ ret_val = pos->second;
+ }
+ }
+
+ if (num_cmd_matches != 1 && num_alias_matches != 1 && HasUserCommands())
+ {
+ num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
+ }
+
+ if (num_user_matches == 1)
+ {
+ cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches));
+
+ pos = m_user_dict.find (cmd);
+ if (pos != m_user_dict.end())
+ {
+ matches->Clear();
+ matches->AppendString (cmd.c_str());
+
+ ret_val = pos->second;
+ }
+ }
+ }
+ else {
+ if (matches)
+ matches->AppendString (cmd_cstr);
+ }
+
+
+ return ret_val;
+}
+
+CommandObject *
+CommandInterpreter::GetCommandObject (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
+{
+ return GetCommandSP (cmd_cstr, include_aliases, exact, matches).get();
+}
+
+bool
+CommandInterpreter::CommandExists (const char *cmd)
+{
+ return m_command_dict.find(cmd) != m_command_dict.end();
+}
+
+bool
+CommandInterpreter::AliasExists (const char *cmd)
+{
+ return m_alias_dict.find(cmd) != m_alias_dict.end();
+}
+
+bool
+CommandInterpreter::UserCommandExists (const char *cmd)
+{
+ return m_user_dict.find(cmd) != m_user_dict.end();
+}
+
+void
+CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
+{
+ m_alias_dict[alias_name] = command_obj_sp;
+}
+
+bool
+CommandInterpreter::RemoveAlias (const char *alias_name)
+{
+ CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name);
+ if (pos != m_alias_dict.end())
+ {
+ m_alias_dict.erase(pos);
+ return true;
+ }
+ return false;
+}
+bool
+CommandInterpreter::RemoveUser (const char *alias_name)
+{
+ CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
+ if (pos != m_user_dict.end())
+ {
+ m_user_dict.erase(pos);
+ return true;
+ }
+ return false;
+}
+
+StateVariable *
+CommandInterpreter::GetStateVariable(const char *name)
+{
+ VariableMap::const_iterator pos = m_variables.find(name);
+ if (pos != m_variables.end())
+ return pos->second.get();
+ return NULL;
+}
+
+void
+CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string)
+{
+ help_string.Printf ("'%s", command_name);
+ OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
+
+ if (option_arg_vector_sp != NULL)
+ {
+ OptionArgVector *options = option_arg_vector_sp.get();
+ for (int i = 0; i < options->size(); ++i)
+ {
+ OptionArgPair cur_option = (*options)[i];
+ std::string opt = cur_option.first;
+ std::string value = cur_option.second;
+ if (opt.compare("<argument>") == 0)
+ {
+ help_string.Printf (" %s", value.c_str());
+ }
+ else
+ {
+ help_string.Printf (" %s", opt.c_str());
+ if ((value.compare ("<no-argument>") != 0)
+ && (value.compare ("<need-argument") != 0))
+ {
+ help_string.Printf (" %s", value.c_str());
+ }
+ }
+ }
+ }
+
+ help_string.Printf ("'");
+}
+
+std::string
+CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict)
+{
+ CommandObject::CommandMap::const_iterator pos;
+ int max_len = 0;
+ CommandObjectSP cmd_sp;
+ std::string longest_word;
+
+ for (pos = dict.begin(); pos != dict.end(); ++pos)
+ {
+ if ((max_len == 0)
+ || (strlen (pos->first.c_str()) > max_len))
+ {
+ longest_word = pos->first;
+ max_len = strlen (longest_word.c_str());
+ }
+ }
+
+ return longest_word;
+}
+
+void
+CommandInterpreter::GetHelp (CommandReturnObject &result)
+{
+ CommandObject::CommandMap::const_iterator pos;
+ result.AppendMessage("The following is a list of built-in, permanent debugger commands:");
+ result.AppendMessage("");
+ std::string longest_word = FindLongestCommandWord (m_command_dict);
+ uint32_t max_len = strlen (longest_word.c_str());
+
+ for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
+ {
+ OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
+ max_len);
+ }
+ result.AppendMessage("");
+
+ if (m_alias_dict.size() > 0)
+ {
+ result.AppendMessage("The following is a list of your current command abbreviations (see 'alias' for more info):");
+ result.AppendMessage("");
+ longest_word = FindLongestCommandWord (m_alias_dict);
+ max_len = strlen (longest_word.c_str());
+ for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos)
+ {
+ StreamString sstr;
+ StreamString translation_and_help;
+ std::string entry_name = pos->first;
+ std::string second_entry = pos->second.get()->GetCommandName();
+ GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr);
+
+ translation_and_help.Printf ("(%s) %s", sstr.GetData(), pos->second->GetHelp());
+ OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--",
+ translation_and_help.GetData(), max_len);
+ }
+ result.AppendMessage("");
+ }
+
+ if (m_user_dict.size() > 0)
+ {
+ result.AppendMessage ("The following is a list of your current user-defined commands:");
+ result.AppendMessage("");
+ for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
+ {
+ result.AppendMessageWithFormat ("%s -- %s\n", pos->first.c_str(), pos->second->GetHelp());
+ }
+ result.AppendMessage("");
+ }
+
+ result.AppendMessage("For more information on any particular command, try 'help <command-name>'.");
+}
+
+void
+CommandInterpreter::ShowVariableValues (CommandReturnObject &result)
+{
+ result.AppendMessage ("Below is a list of all the debugger setting variables and their values:");
+
+ for (VariableMap::const_iterator pos = m_variables.begin(); pos != m_variables.end(); ++pos)
+ {
+ StateVariable *var = pos->second.get();
+ var->AppendVariableInformation (result);
+ }
+}
+
+void
+CommandInterpreter::ShowVariableHelp (CommandReturnObject &result)
+{
+ result.AppendMessage ("Below is a list of all the internal debugger variables that are settable:");
+ for (VariableMap::const_iterator pos = m_variables.begin(); pos != m_variables.end(); ++pos)
+ {
+ StateVariable *var = pos->second.get();
+ result.AppendMessageWithFormat (" %s -- %s \n", var->GetName(), var->GetHelp());
+ }
+}
+
+// Main entry point into the command_interpreter; this function takes a text
+// line containing a debugger command, with all its flags, options, etc,
+// parses the line and takes the appropriate actions.
+
+bool
+CommandInterpreter::HandleCommand (const char *command_line, bool add_to_history, CommandReturnObject &result,
+ ExecutionContext *override_context)
+{
+ // FIXME: there should probably be a mutex to make sure only one thread can
+ // run the interpreter at a time.
+
+ // TODO: this should be a logging channel in lldb.
+// if (DebugSelf())
+// {
+// result.AppendMessageWithFormat ("Processing command: %s\n", command_line);
+// }
+
+ m_current_context.Update (override_context);
+
+ if (command_line == NULL || command_line[0] == '\0')
+ {
+ if (m_command_history.empty())
+ {
+ result.AppendError ("empty command");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ command_line = m_command_history.back().c_str();
+ }
+ add_to_history = false;
+ }
+
+ Args command_args(command_line);
+
+ if (command_args.GetArgumentCount() > 0)
+ {
+ const char *command_cstr = command_args.GetArgumentAtIndex(0);
+ if (command_cstr)
+ {
+
+ // We're looking up the command object here. So first find an exact match to the
+ // command in the commands.
+
+ CommandObject *command_obj = GetCommandObject (command_cstr, false, true);
+
+ // If we didn't find an exact match to the command string in the commands, look in
+ // the aliases.
+
+ if (command_obj == NULL)
+ {
+ command_obj = GetCommandObject (command_cstr, true, true);
+ if (command_obj != NULL)
+ {
+ BuildAliasCommandArgs (command_obj, command_cstr, command_args, result);
+ if (!result.Succeeded())
+ return false;
+ }
+ }
+
+ // Finally, if there wasn't an exact match among the aliases, look for an inexact match.
+
+ if (command_obj == NULL)
+ command_obj = GetCommandObject(command_cstr, false, false);
+
+ if (command_obj)
+ {
+ if (command_obj->WantsRawCommandString())
+ {
+ const char *stripped_command = ::strstr (command_line, command_cstr);
+ if (stripped_command)
+ {
+ stripped_command += strlen(command_cstr);
+ while (isspace(*stripped_command))
+ ++stripped_command;
+ command_obj->ExecuteRawCommandString(stripped_command, Context(), this, result);
+ }
+ }
+ else
+ {
+ if (add_to_history)
+ m_command_history.push_back (command_line);
+
+ // Remove the command from the args.
+ command_args.Shift();
+ command_obj->ExecuteWithOptions (command_args, Context(), this, result);
+ }
+ }
+ else
+ {
+ StringList matches;
+ int num_matches;
+ int cursor_index = command_args.GetArgumentCount() - 1;
+ int cursor_char_position = strlen (command_args.GetArgumentAtIndex(command_args.GetArgumentCount() - 1));
+ num_matches = HandleCompletionMatches (command_args, cursor_index,
+ cursor_char_position,
+ 0, -1, matches);
+
+ if (num_matches > 0)
+ {
+ std::string error_msg;
+ error_msg.assign ("ambiguous command '");
+ error_msg.append(command_cstr);
+ error_msg.append ("'.");
+
+ error_msg.append (" Possible completions:");
+ for (int i = 0; i < num_matches; i++)
+ {
+ error_msg.append ("\n\t");
+ error_msg.append (matches.GetStringAtIndex (i));
+ }
+ error_msg.append ("\n");
+ result.AppendRawError (error_msg.c_str(), error_msg.size());
+ }
+ else
+ result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_cstr);
+
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ return result.Succeeded();
+}
+
+int
+CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
+ int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ StringList &matches)
+{
+ int num_command_matches = 0;
+ bool include_aliases = true;
+ bool look_for_subcommand = false;
+
+ if (cursor_index == -1)
+ {
+ // We got nothing on the command line, so return the list of commands
+ num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
+ }
+ else if (cursor_index == 0)
+ {
+ // The cursor is in the first argument, so just do a lookup in the dictionary.
+ CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), include_aliases, false,
+ &matches);
+ num_command_matches = matches.GetSize();
+
+ if (num_command_matches == 1
+ && cmd_obj && cmd_obj->IsMultiwordObject()
+ && matches.GetStringAtIndex(0) != NULL
+ && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
+ {
+ look_for_subcommand = true;
+ num_command_matches = 0;
+ matches.DeleteStringAtIndex(0);
+ parsed_line.AppendArgument ("");
+ cursor_index++;
+ cursor_char_position = 0;
+ }
+ }
+
+ if (cursor_index > 0 || look_for_subcommand)
+ {
+ // We are completing further on into a commands arguments, so find the command and tell it
+ // to complete the command.
+ // First see if there is a matching initial command:
+ CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0), include_aliases, false);
+ if (command_object == NULL)
+ {
+ return 0;
+ }
+ else
+ {
+ parsed_line.Shift();
+ cursor_index--;
+ num_command_matches = command_object->HandleCompletion (parsed_line, cursor_index, cursor_char_position,
+ match_start_point, max_return_elements, this,
+ matches);
+ }
+ }
+
+ return num_command_matches;
+
+}
+
+int
+CommandInterpreter::HandleCompletion (const char *current_line,
+ const char *cursor,
+ const char *last_char,
+ int match_start_point,
+ int max_return_elements,
+ StringList &matches)
+{
+ // We parse the argument up to the cursor, so the last argument in parsed_line is
+ // the one containing the cursor, and the cursor is after the last character.
+
+ Args parsed_line(current_line, last_char - current_line);
+ Args partial_parsed_line(current_line, cursor - current_line);
+
+ int num_args = partial_parsed_line.GetArgumentCount();
+ int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
+ int cursor_char_position;
+
+ if (cursor_index == -1)
+ cursor_char_position = 0;
+ else
+ cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
+
+ int num_command_matches;
+
+ matches.Clear();
+
+ // Only max_return_elements == -1 is supported at present:
+ assert (max_return_elements == -1);
+ num_command_matches = HandleCompletionMatches (parsed_line, cursor_index, cursor_char_position, match_start_point,
+ max_return_elements, matches);
+
+ if (num_command_matches <= 0)
+ return num_command_matches;
+
+ if (num_args == 0)
+ {
+ // If we got an empty string, insert nothing.
+ matches.InsertStringAtIndex(0, "");
+ }
+ else
+ {
+ // Now figure out if there is a common substring, and if so put that in element 0, otherwise
+ // put an empty string in element 0.
+ std::string command_partial_str;
+ if (cursor_index >= 0)
+ command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index), parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);
+
+ std::string common_prefix;
+ matches.LongestCommonPrefix (common_prefix);
+ int partial_name_len = command_partial_str.size();
+
+ // If we matched a unique single command, add a space...
+ if (num_command_matches == 1)
+ {
+ char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
+ if (quote_char != '\0')
+ common_prefix.push_back(quote_char);
+
+ common_prefix.push_back(' ');
+ }
+ common_prefix.erase (0, partial_name_len);
+ matches.InsertStringAtIndex(0, common_prefix.c_str());
+ }
+ return num_command_matches;
+}
+
+CommandContext *
+CommandInterpreter::Context ()
+{
+ return &m_current_context;
+}
+
+const Args *
+CommandInterpreter::GetProgramArguments ()
+{
+ if (! HasInterpreterVariables())
+ return NULL;
+
+ VariableMap::const_iterator pos = m_variables.find("run-args");
+ if (pos == m_variables.end())
+ return NULL;
+
+ StateVariable *var = pos->second.get();
+
+ if (var)
+ return &var->GetArgs();
+ return NULL;
+}
+
+const Args *
+CommandInterpreter::GetEnvironmentVariables ()
+{
+ if (! HasInterpreterVariables())
+ return NULL;
+
+ VariableMap::const_iterator pos = m_variables.find("env-vars");
+ if (pos == m_variables.end())
+ return NULL;
+
+ StateVariable *var = pos->second.get();
+ if (var)
+ return &var->GetArgs();
+ return NULL;
+}
+
+
+CommandInterpreter::~CommandInterpreter ()
+{
+}
+
+const char *
+CommandInterpreter::GetPrompt ()
+{
+ VariableMap::iterator pos;
+
+ if (! HasInterpreterVariables())
+ return NULL;
+
+ pos = m_variables.find("prompt");
+ if (pos == m_variables.end())
+ return NULL;
+
+ StateVariable *var = pos->second.get();
+
+ return ((char *) var->GetStringValue());
+}
+
+void
+CommandInterpreter::SetPrompt (const char *new_prompt)
+{
+ VariableMap::iterator pos;
+ CommandReturnObject result;
+
+ if (! HasInterpreterVariables())
+ return;
+
+ pos = m_variables.find ("prompt");
+ if (pos == m_variables.end())
+ return;
+
+ StateVariable *var = pos->second.get();
+
+ if (var->VerifyValue (this, (void *) new_prompt, result))
+ var->SetStringValue (new_prompt);
+}
+
+void
+CommandInterpreter::CrossRegisterCommand (const char * dest_cmd, const char * object_type)
+{
+ CommandObjectSP cmd_obj_sp = GetCommandSP (dest_cmd);
+
+ if (cmd_obj_sp != NULL)
+ {
+ CommandObject *cmd_obj = cmd_obj_sp.get();
+ if (cmd_obj->IsCrossRefObject ())
+ cmd_obj->AddObject (object_type);
+ }
+}
+
+void
+CommandInterpreter::SetScriptLanguage (ScriptLanguage lang)
+{
+ m_script_language = lang;
+}
+
+Listener *
+CommandInterpreter::GetListener ()
+{
+ return m_listener;
+}
+
+SourceManager &
+CommandInterpreter::GetSourceManager ()
+{
+ return m_source_manager;
+}
+
+
+
+OptionArgVectorSP
+CommandInterpreter::GetAliasOptions (const char *alias_name)
+{
+ OptionArgMap::iterator pos;
+ OptionArgVectorSP ret_val;
+
+ std::string alias (alias_name);
+
+ if (HasAliasOptions())
+ {
+ pos = m_alias_options.find (alias);
+ if (pos != m_alias_options.end())
+ ret_val = pos->second;
+ }
+
+ return ret_val;
+}
+
+void
+CommandInterpreter::RemoveAliasOptions (const char *alias_name)
+{
+ OptionArgMap::iterator pos = m_alias_options.find(alias_name);
+ if (pos != m_alias_options.end())
+ {
+ m_alias_options.erase (pos);
+ }
+}
+
+void
+CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp)
+{
+ m_alias_options[alias_name] = option_arg_vector_sp;
+}
+
+bool
+CommandInterpreter::HasCommands ()
+{
+ return (!m_command_dict.empty());
+}
+
+bool
+CommandInterpreter::HasAliases ()
+{
+ return (!m_alias_dict.empty());
+}
+
+bool
+CommandInterpreter::HasUserCommands ()
+{
+ return (!m_user_dict.empty());
+}
+
+bool
+CommandInterpreter::HasAliasOptions ()
+{
+ return (!m_alias_options.empty());
+}
+
+bool
+CommandInterpreter::HasInterpreterVariables ()
+{
+ return (!m_variables.empty());
+}
+
+void
+CommandInterpreter::BuildAliasCommandArgs
+(
+ CommandObject *alias_cmd_obj,
+ const char *alias_name,
+ Args &cmd_args,
+ CommandReturnObject &result
+)
+{
+ OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
+
+ if (option_arg_vector_sp.get())
+ {
+ // Make sure that the alias name is the 0th element in cmd_args
+ std::string alias_name_str = alias_name;
+ if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
+ cmd_args.Unshift (alias_name);
+
+ Args new_args (alias_cmd_obj->GetCommandName());
+ if (new_args.GetArgumentCount() == 2)
+ new_args.Shift();
+
+ OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
+ int old_size = cmd_args.GetArgumentCount();
+ int *used = (int *) malloc ((old_size + 1) * sizeof (int));
+
+ memset (used, 0, (old_size + 1) * sizeof (int));
+ used[0] = 1;
+
+ for (int i = 0; i < option_arg_vector->size(); ++i)
+ {
+ OptionArgPair option_pair = (*option_arg_vector)[i];
+ std::string option = option_pair.first;
+ std::string value = option_pair.second;
+ if (option.compare ("<argument>") == 0)
+ new_args.AppendArgument (value.c_str());
+ else
+ {
+ new_args.AppendArgument (option.c_str());
+ if (value.compare ("<no-argument>") != 0)
+ {
+ int index = GetOptionArgumentPosition (value.c_str());
+ if (index == 0)
+ // value was NOT a positional argument; must be a real value
+ new_args.AppendArgument (value.c_str());
+ else if (index >= cmd_args.GetArgumentCount())
+ {
+ result.AppendErrorWithFormat
+ ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
+ index);
+ result.SetStatus (eReturnStatusFailed);
+ return;
+ }
+ else
+ {
+ new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
+ used[index] = 1;
+ }
+ }
+ }
+ }
+
+ for (int j = 0; j < cmd_args.GetArgumentCount(); ++j)
+ {
+ if (!used[j])
+ new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
+ }
+
+ cmd_args.Clear();
+ cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
+ }
+ else
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ // This alias was not created with any options; nothing further needs to be done.
+ return;
+ }
+
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ return;
+}
+
+
+int
+CommandInterpreter::GetOptionArgumentPosition (const char *in_string)
+{
+ int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
+ // of zero.
+
+ char *cptr = (char *) in_string;
+
+ // Does it start with '%'
+ if (cptr[0] == '%')
+ {
+ ++cptr;
+
+ // Is the rest of it entirely digits?
+ if (isdigit (cptr[0]))
+ {
+ const char *start = cptr;
+ while (isdigit (cptr[0]))
+ ++cptr;
+
+ // We've gotten to the end of the digits; are we at the end of the string?
+ if (cptr[0] == '\0')
+ position = atoi (start);
+ }
+ }
+
+ return position;
+}
+
+void
+CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
+{
+ const char *init_file_path = in_cwd ? "./.lldbinit" : "~/.lldbinit";
+ FileSpec init_file (init_file_path);
+ // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
+ // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
+
+ if (init_file.Exists())
+ {
+ char path[PATH_MAX];
+ init_file.GetPath(path, sizeof(path));
+ StreamString source_command;
+ source_command.Printf ("source '%s'", path);
+ HandleCommand (source_command.GetData(), false, result);
+ }
+ else
+ {
+ // nothing to be done if the file doesn't exist
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ }
+}
+
+ScriptInterpreter *
+CommandInterpreter::GetScriptInterpreter ()
+{
+ CommandObject::CommandMap::iterator pos;
+
+ pos = m_command_dict.find ("script");
+ if (pos != m_command_dict.end())
+ {
+ CommandObject *script_cmd_obj = pos->second.get();
+ return ((CommandObjectScript *) script_cmd_obj)->GetInterpreter ();
+ }
+ else
+ return NULL;
+}
+
+
+
+bool
+CommandInterpreter::GetSynchronous ()
+{
+ return m_synchronous_execution;
+}
+
+void
+CommandInterpreter::SetSynchronous (bool value)
+{
+ static bool value_set_once = false;
+ if (!value_set_once)
+ {
+ value_set_once = true;
+ m_synchronous_execution = value;
+ }
+}
+
+void
+CommandInterpreter::OutputFormattedHelpText (Stream &strm,
+ const char *word_text,
+ const char *separator,
+ const char *help_text,
+ uint32_t max_word_len)
+{
+ StateVariable *var = GetStateVariable ("term-width");
+ int max_columns = var->GetIntValue();
+ // Sanity check max_columns, to cope with emacs shell mode with TERM=dumb
+ // (0 rows; 0 columns;).
+ if (max_columns <= 0) max_columns = 80;
+
+ int indent_size = max_word_len + strlen (separator) + 2;
+
+ strm.IndentMore (indent_size);
+
+ int len = indent_size + strlen (help_text) + 1;
+ char *text = (char *) malloc (len);
+ sprintf (text, "%-*s %s %s", max_word_len, word_text, separator, help_text);
+ if (text[len - 1] == '\n')
+ text[--len] = '\0';
+
+ if (len < max_columns)
+ {
+ // Output it as a single line.
+ strm.Printf ("%s", text);
+ }
+ else
+ {
+ // We need to break it up into multiple lines.
+ bool first_line = true;
+ int text_width;
+ int start = 0;
+ int end = start;
+ int final_end = strlen (text);
+ int sub_len;
+
+ while (end < final_end)
+ {
+ if (first_line)
+ text_width = max_columns - 1;
+ else
+ text_width = max_columns - indent_size - 1;
+
+ // Don't start the 'text' on a space, since we're already outputting the indentation.
+ if (!first_line)
+ {
+ while ((start < final_end) && (text[start] == ' '))
+ start++;
+ }
+
+ end = start + text_width;
+ if (end > final_end)
+ end = final_end;
+ else
+ {
+ // If we're not at the end of the text, make sure we break the line on white space.
+ while (end > start
+ && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
+ end--;
+ }
+
+ sub_len = end - start;
+ if (start != 0)
+ strm.EOL();
+ if (!first_line)
+ strm.Indent();
+ else
+ first_line = false;
+ assert (start <= final_end);
+ assert (start + sub_len <= final_end);
+ if (sub_len > 0)
+ strm.Write (text + start, sub_len);
+ start = end + 1;
+ }
+ }
+ strm.EOL();
+ strm.IndentLess(indent_size);
+ free (text);
+}
+
+void
+CommandInterpreter::AproposAllSubCommands (CommandObject *cmd_obj, const char *prefix, const char *search_word,
+ StringList &commands_found, StringList &commands_help)
+{
+ CommandObject::CommandMap::const_iterator pos;
+ CommandObject::CommandMap sub_cmd_dict = ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict;
+ CommandObject *sub_cmd_obj;
+
+ for (pos = sub_cmd_dict.begin(); pos != sub_cmd_dict.end(); ++pos)
+ {
+ const char * command_name = pos->first.c_str();
+ sub_cmd_obj = pos->second.get();
+ StreamString complete_command_name;
+
+ complete_command_name.Printf ("%s %s", prefix, command_name);
+
+ if (sub_cmd_obj->HelpTextContainsWord (search_word))
+ {
+ commands_found.AppendString (complete_command_name.GetData());
+ commands_help.AppendString (sub_cmd_obj->GetHelp());
+ }
+
+ if (sub_cmd_obj->IsMultiwordObject())
+ AproposAllSubCommands (sub_cmd_obj, complete_command_name.GetData(), search_word, commands_found,
+ commands_help);
+ }
+
+}
+
+void
+CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
+ StringList &commands_help)
+{
+ CommandObject::CommandMap::const_iterator pos;
+
+ for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
+ {
+ const char *command_name = pos->first.c_str();
+ CommandObject *cmd_obj = pos->second.get();
+
+ if (cmd_obj->HelpTextContainsWord (search_word))
+ {
+ commands_found.AppendString (command_name);
+ commands_help.AppendString (cmd_obj->GetHelp());
+ }
+
+ if (cmd_obj->IsMultiwordObject())
+ AproposAllSubCommands (cmd_obj, command_name, search_word, commands_found, commands_help);
+
+ }
+}
diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp
new file mode 100644
index 00000000000..080b5b057bf
--- /dev/null
+++ b/lldb/source/Interpreter/CommandObject.cpp
@@ -0,0 +1,448 @@
+//===-- CommandObject.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/Interpreter/CommandObject.h"
+
+#include <string>
+#include <map>
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Options.h"
+
+// These are for the Sourcename completers.
+// FIXME: Make a separate file for the completers.
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/FileSpecList.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreterPython.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObject
+//-------------------------------------------------------------------------
+
+CommandObject::CommandObject (const char *name, const char *help, const char *syntax, uint32_t flags) :
+ m_cmd_name (name),
+ m_cmd_help_short (),
+ m_cmd_help_long (),
+ m_cmd_syntax (),
+ m_flags (flags)
+{
+ if (help && help[0])
+ m_cmd_help_short = help;
+ if (syntax && syntax[0])
+ m_cmd_syntax = syntax;
+}
+
+CommandObject::~CommandObject ()
+{
+}
+
+const char *
+CommandObject::GetHelp ()
+{
+ return m_cmd_help_short.c_str();
+}
+
+const char *
+CommandObject::GetHelpLong ()
+{
+ return m_cmd_help_long.c_str();
+}
+
+const char *
+CommandObject::GetSyntax ()
+{
+ return m_cmd_syntax.c_str();
+}
+
+const char *
+CommandObject::Translate ()
+{
+ //return m_cmd_func_name.c_str();
+ return "This function is currently not implemented.";
+}
+
+const char *
+CommandObject::GetCommandName ()
+{
+ return m_cmd_name.c_str();
+}
+
+void
+CommandObject::SetCommandName (const char *name)
+{
+ m_cmd_name = name;
+}
+
+void
+CommandObject::SetHelp (const char *cstr)
+{
+ m_cmd_help_short = cstr;
+}
+
+void
+CommandObject::SetHelpLong (const char *cstr)
+{
+ m_cmd_help_long = cstr;
+}
+
+void
+CommandObject::SetSyntax (const char *cstr)
+{
+ m_cmd_syntax = cstr;
+}
+
+Options *
+CommandObject::GetOptions ()
+{
+ // By default commands don't have options unless this virtual function
+ // is overridden by base classes.
+ return NULL;
+}
+
+Flags&
+CommandObject::GetFlags()
+{
+ return m_flags;
+}
+
+const Flags&
+CommandObject::GetFlags() const
+{
+ return m_flags;
+}
+
+bool
+CommandObject::ExecuteCommandString
+(
+ const char *command_line,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ Args command_args(command_line);
+ return ExecuteWithOptions (command_args, context, interpreter, result);
+}
+
+bool
+CommandObject::ParseOptions
+(
+ Args& args,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ // See if the subclass has options?
+ Options *options = GetOptions();
+ if (options != NULL)
+ {
+ Error error;
+ options->ResetOptionValues();
+
+ // ParseOptions calls getopt_long, which always skips the zero'th item in the array and starts at position 1,
+ // so we need to push a dummy value into position zero.
+ args.Unshift("dummy_string");
+ error = args.ParseOptions (*options);
+
+ // The "dummy_string" will have already been removed by ParseOptions,
+ // so no need to remove it.
+
+ if (error.Fail() || !options->VerifyOptions (result))
+ {
+ const char *error_cstr = error.AsCString();
+ if (error_cstr)
+ {
+ // We got an error string, lets use that
+ result.GetErrorStream().PutCString(error_cstr);
+ }
+ else
+ {
+ // No error string, output the usage information into result
+ options->GenerateOptionUsage (result.GetErrorStream(), this);
+ }
+ // Set the return status to failed (this was an error).
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ return true;
+}
+bool
+CommandObject::ExecuteWithOptions
+(
+ Args& args,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ for (size_t i = 0; i < args.GetArgumentCount(); ++i)
+ {
+ const char *tmp_str = args.GetArgumentAtIndex (i);
+ if (tmp_str[0] == '`') // back-quote
+ args.ReplaceArgumentAtIndex (i, interpreter->ProcessEmbeddedScriptCommands (tmp_str));
+ }
+
+ Process *process = context->GetExecutionContext().process;
+ if (process == NULL)
+ {
+ if (GetFlags().IsSet(CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused))
+ {
+ result.AppendError ("Process must exist.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ StateType state = process->GetState();
+
+ switch (state)
+ {
+
+ case eStateAttaching:
+ case eStateLaunching:
+ case eStateSuspended:
+ case eStateCrashed:
+ case eStateStopped:
+ break;
+
+ case eStateDetached:
+ case eStateExited:
+ case eStateUnloaded:
+ if (GetFlags().IsSet(CommandObject::eFlagProcessMustBeLaunched))
+ {
+ result.AppendError ("Process must be launched.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ break;
+
+ case eStateRunning:
+ case eStateStepping:
+ if (GetFlags().IsSet(CommandObject::eFlagProcessMustBePaused))
+ {
+ result.AppendError ("Process is running. Use 'process interrupt' to pause execution.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ }
+
+ if (!ParseOptions (args, interpreter, result))
+ return false;
+
+ // Call the command-specific version of 'Execute', passing it the already processed arguments.
+ return Execute (args, context, interpreter, result);
+}
+
+class CommandDictCommandPartialMatch
+{
+ public:
+ CommandDictCommandPartialMatch (const char *match_str)
+ {
+ m_match_str = match_str;
+ }
+ bool operator() (const std::pair<std::string, lldb::CommandObjectSP> map_element) const
+ {
+ // A NULL or empty string matches everything.
+ if (m_match_str == NULL || *m_match_str == '\0')
+ return 1;
+
+ size_t found = map_element.first.find (m_match_str, 0);
+ if (found == std::string::npos)
+ return 0;
+ else
+ return found == 0;
+ }
+
+ private:
+ const char *m_match_str;
+};
+
+int
+CommandObject::AddNamesMatchingPartialString (CommandObject::CommandMap &in_map, const char *cmd_str,
+ StringList &matches)
+{
+ int number_added = 0;
+ CommandDictCommandPartialMatch matcher(cmd_str);
+
+ CommandObject::CommandMap::iterator matching_cmds = std::find_if (in_map.begin(), in_map.end(), matcher);
+
+ while (matching_cmds != in_map.end())
+ {
+ ++number_added;
+ matches.AppendString((*matching_cmds).first.c_str());
+ matching_cmds = std::find_if (++matching_cmds, in_map.end(), matcher);;
+ }
+ return number_added;
+}
+
+int
+CommandObject::HandleCompletion
+(
+ Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ CommandInterpreter *interpreter,
+ StringList &matches
+)
+{
+ if (WantsRawCommandString())
+ {
+ // FIXME: Abstract telling the completion to insert the completion character.
+ matches.Clear();
+ return -1;
+ }
+ else
+ {
+ // Can we do anything generic with the options?
+ Options *cur_options = GetOptions();
+ CommandReturnObject result;
+ OptionElementVector opt_element_vector;
+
+ if (cur_options != NULL)
+ {
+ // Re-insert the dummy command name string which will have been
+ // stripped off:
+ input.Unshift ("dummy-string");
+ cursor_index++;
+
+
+ // I stick an element on the end of the input, because if the last element is
+ // option that requires an argument, getopt_long will freak out.
+
+ input.AppendArgument ("<FAKE-VALUE>");
+
+ input.ParseArgsForCompletion (*cur_options, opt_element_vector);
+
+ input.DeleteArgumentAtIndex(input.GetArgumentCount() - 1);
+
+ bool handled_by_options;
+ handled_by_options = cur_options->HandleOptionCompletion(input,
+ opt_element_vector,
+ cursor_index,
+ cursor_char_position,
+ match_start_point,
+ max_return_elements,
+ interpreter,
+ matches);
+ if (handled_by_options)
+ return matches.GetSize();
+ }
+
+ // If we got here, the last word is not an option or an option argument.
+ return HandleArgumentCompletion(input,
+ cursor_index,
+ cursor_char_position,
+ opt_element_vector,
+ match_start_point,
+ max_return_elements,
+ interpreter,
+ matches);
+ }
+}
+
+int
+CommandObject::HandleArgumentCompletion
+(
+ Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ OptionElementVector &opt_element_vector,
+ int match_start_point,
+ int max_return_elements,
+ CommandInterpreter *interpreter,
+ StringList &matches
+)
+{
+ return 0;
+}
+
+// Case insensitive version of ::strstr()
+// Returns true if s2 is contained within s1.
+
+static bool
+contains_string (const char *s1, const char *s2)
+{
+ char *locase_s1 = (char *) malloc (strlen (s1) + 1);
+ char *locase_s2 = (char *) malloc (strlen (s2) + 1);
+ int i;
+ for (i = 0; s1 && s1[i] != '\0'; i++)
+ locase_s1[i] = ::tolower (s1[i]);
+ locase_s1[i] = '\0';
+ for (i = 0; s2 && s2[i] != '\0'; i++)
+ locase_s2[i] = ::tolower (s2[i]);
+ locase_s2[i] = '\0';
+
+ const char *result = ::strstr (locase_s1, locase_s2);
+ free (locase_s1);
+ free (locase_s2);
+ // 'result' points into freed memory - but we're not
+ // deref'ing it so hopefully current/future compilers
+ // won't complain..
+
+ if (result == NULL)
+ return false;
+ else
+ return true;
+}
+
+bool
+CommandObject::HelpTextContainsWord (const char *search_word)
+{
+ const char *short_help;
+ const char *long_help;
+ const char *syntax_help;
+ std::string options_usage_help;
+
+
+ bool found_word = false;
+
+ short_help = GetHelp();
+ long_help = GetHelpLong();
+ syntax_help = GetSyntax();
+
+ if (contains_string (short_help, search_word))
+ found_word = true;
+ else if (contains_string (long_help, search_word))
+ found_word = true;
+ else if (contains_string (syntax_help, search_word))
+ found_word = true;
+
+ if (!found_word
+ && GetOptions() != NULL)
+ {
+ StreamString usage_help;
+ GetOptions()->GenerateOptionUsage (usage_help, this);
+ if (usage_help.GetSize() > 0)
+ {
+ const char *usage_text = usage_help.GetData();
+ if (contains_string (usage_text, search_word))
+ found_word = true;
+ }
+ }
+
+ return found_word;
+}
diff --git a/lldb/source/Interpreter/CommandObjectCrossref.cpp b/lldb/source/Interpreter/CommandObjectCrossref.cpp
new file mode 100644
index 00000000000..27b66379e87
--- /dev/null
+++ b/lldb/source/Interpreter/CommandObjectCrossref.cpp
@@ -0,0 +1,92 @@
+//===-- CommandObjectCrossref.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/Interpreter/CommandObjectCrossref.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectCrossref
+//-------------------------------------------------------------------------
+
+CommandObjectCrossref::CommandObjectCrossref
+(
+ const char *name,
+ const char *help,
+ const char *syntax
+) :
+ CommandObject (name, help, syntax),
+ m_crossref_object_types()
+{
+}
+
+CommandObjectCrossref::~CommandObjectCrossref ()
+{
+}
+
+bool
+CommandObjectCrossref::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ if (m_crossref_object_types.GetArgumentCount() == 0)
+ {
+ result.AppendErrorWithFormat ("There are no objects for which you can call '%s'.\n", GetCommandName());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ GenerateHelpText (result);
+ }
+ return result.Succeeded();
+}
+
+void
+CommandObjectCrossref::AddObject (const char *obj_name)
+{
+ m_crossref_object_types.AppendArgument (obj_name);
+}
+
+const char **
+CommandObjectCrossref::GetObjectTypes () const
+{
+ return m_crossref_object_types.GetConstArgumentVector();
+}
+
+void
+CommandObjectCrossref::GenerateHelpText (CommandReturnObject &result)
+{
+ result.AppendMessage ("This command can be called on the following types of objects:");
+
+ for (int i = 0; i < m_crossref_object_types.GetArgumentCount(); ++i)
+ {
+ const char *obj_name = m_crossref_object_types.GetArgumentAtIndex(i);
+ result.AppendMessageWithFormat (" %s (e.g. '%s %s')\n", obj_name,
+ obj_name, GetCommandName());
+ }
+
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+}
+
+bool
+CommandObjectCrossref::IsCrossRefObject ()
+{
+ return true;
+}
diff --git a/lldb/source/Interpreter/CommandObjectMultiword.cpp b/lldb/source/Interpreter/CommandObjectMultiword.cpp
new file mode 100644
index 00000000000..874be0ea6a1
--- /dev/null
+++ b/lldb/source/Interpreter/CommandObjectMultiword.cpp
@@ -0,0 +1,263 @@
+//===-- CommandObjectMultiword.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/Interpreter/CommandObjectMultiword.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiword
+//-------------------------------------------------------------------------
+
+CommandObjectMultiword::CommandObjectMultiword
+(
+ const char *name,
+ const char *help,
+ const char *syntax,
+ uint32_t flags
+) :
+ CommandObject (name, help, syntax, flags)
+{
+}
+
+CommandObjectMultiword::~CommandObjectMultiword ()
+{
+}
+
+CommandObjectSP
+CommandObjectMultiword::GetSubcommandSP (const char *sub_cmd, StringList *matches)
+{
+ CommandObjectSP return_cmd_sp;
+ CommandObject::CommandMap::iterator pos;
+
+ if (!m_subcommand_dict.empty())
+ {
+ pos = m_subcommand_dict.find (sub_cmd);
+ if (pos != m_subcommand_dict.end())
+ return_cmd_sp = pos->second;
+ else
+ {
+
+ StringList local_matches;
+ if (matches == NULL)
+ matches = &local_matches;
+ int num_matches = CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, sub_cmd, *matches);
+
+ if (num_matches == 1)
+ {
+ // Cleaner, but slightly less efficient would be to call back into this function, since I now
+ // know I have an exact match...
+
+ sub_cmd = matches->GetStringAtIndex(0);
+ pos = m_subcommand_dict.find(sub_cmd);
+ if (pos != m_subcommand_dict.end())
+ return_cmd_sp = pos->second;
+ }
+ }
+ }
+ return return_cmd_sp;
+}
+
+CommandObject *
+CommandObjectMultiword::GetSubcommandObject (const char *sub_cmd, StringList *matches)
+{
+ return GetSubcommandSP(sub_cmd, matches).get();
+}
+
+bool
+CommandObjectMultiword::LoadSubCommand (CommandObjectSP cmd_obj, const char *name,
+ CommandInterpreter *interpreter)
+{
+ CommandMap::iterator pos;
+ bool success = true;
+
+ pos = m_subcommand_dict.find(name);
+ if (pos == m_subcommand_dict.end())
+ {
+ m_subcommand_dict[name] = cmd_obj;
+ interpreter->CrossRegisterCommand (name, GetCommandName());
+ }
+ else
+ success = false;
+
+ return success;
+}
+
+bool
+CommandObjectMultiword::Execute
+(
+ Args& args,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ const size_t argc = args.GetArgumentCount();
+ if (argc == 0)
+ {
+ GenerateHelpText (result, interpreter);
+ }
+ else
+ {
+ const char *sub_command = args.GetArgumentAtIndex (0);
+
+ if (sub_command)
+ {
+ if (::strcasecmp (sub_command, "help") == 0)
+ {
+ GenerateHelpText (result, interpreter);
+ }
+ else if (!m_subcommand_dict.empty())
+ {
+ StringList matches;
+ CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
+ if (sub_cmd_obj != NULL)
+ {
+ // Now call CommandObject::Execute to process and options in 'rest_of_line'. From there
+ // the command-specific version of Execute will be called, with the processed arguments.
+
+ args.Shift();
+
+ sub_cmd_obj->ExecuteWithOptions (args, context, interpreter, result);
+ }
+ else
+ {
+ std::string error_msg;
+ int num_subcmd_matches = matches.GetSize();
+ if (num_subcmd_matches > 0)
+ error_msg.assign ("ambiguous command ");
+ else
+ error_msg.assign ("invalid command ");
+
+ error_msg.append ("'");
+ error_msg.append (GetCommandName());
+ error_msg.append (" ");
+ error_msg.append (sub_command);
+ error_msg.append ("'");
+
+ if (num_subcmd_matches > 0)
+ {
+ error_msg.append (" Possible completions:");
+ for (int i = 0; i < num_subcmd_matches; i++)
+ {
+ error_msg.append ("\n\t");
+ error_msg.append (matches.GetStringAtIndex (i));
+ }
+ }
+ error_msg.append ("\n");
+ result.AppendRawError (error_msg.c_str(), error_msg.size());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("'%s' does not have any subcommands.\n", GetCommandName());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+
+ return result.Succeeded();
+}
+
+void
+CommandObjectMultiword::GenerateHelpText (CommandReturnObject &result, CommandInterpreter *interpreter)
+{
+ // First time through here, generate the help text for the object and
+ // push it to the return result object as well
+
+ StreamString &output_stream = result.GetOutputStream();
+ output_stream.PutCString ("The following subcommands are supported:\n\n");
+
+ CommandMap::iterator pos;
+ std::string longest_word = interpreter->FindLongestCommandWord (m_subcommand_dict);
+ uint32_t max_len = 0;
+
+ if (! longest_word.empty())
+ max_len = strlen (longest_word.c_str()) + 4; // Indent the output by 4 spaces.
+
+ for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
+ {
+ std::string indented_command (" ");
+ indented_command.append (pos->first);
+ interpreter->OutputFormattedHelpText (result.GetOutputStream(), indented_command.c_str(), "--",
+ pos->second->GetHelp(), max_len);
+ }
+
+ output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n");
+
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+}
+
+int
+CommandObjectMultiword::HandleCompletion
+(
+ Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ CommandInterpreter *interpreter,
+ StringList &matches
+)
+{
+ if (cursor_index == 0)
+ {
+ CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, input.GetArgumentAtIndex(0), matches);
+
+ if (matches.GetSize() == 1
+ && matches.GetStringAtIndex(0) != NULL
+ && strcmp (input.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
+ {
+ StringList temp_matches;
+ CommandObject *cmd_obj = GetSubcommandObject (input.GetArgumentAtIndex(0), &temp_matches);
+ if (cmd_obj != NULL)
+ {
+ matches.DeleteStringAtIndex (0);
+ input.Shift();
+ cursor_char_position = 0;
+ input.AppendArgument ("");
+ return cmd_obj->HandleCompletion (input, cursor_index, cursor_char_position, match_start_point,
+ max_return_elements, interpreter, matches);
+ }
+ else
+ return matches.GetSize();
+ }
+ else
+ return matches.GetSize();
+ }
+ else
+ {
+ CommandObject *sub_command_object = GetSubcommandObject (input.GetArgumentAtIndex(0), &matches);
+ if (sub_command_object == NULL)
+ {
+ return matches.GetSize();
+ }
+ else
+ {
+ // Remove the one match that we got from calling GetSubcommandObject.
+ matches.DeleteStringAtIndex(0);
+ input.Shift();
+ cursor_index--;
+ return sub_command_object->HandleCompletion (input, cursor_index, cursor_char_position, match_start_point,
+ max_return_elements, interpreter, matches);
+ }
+
+ }
+}
+
diff --git a/lldb/source/Interpreter/CommandObjectRegexCommand.cpp b/lldb/source/Interpreter/CommandObjectRegexCommand.cpp
new file mode 100644
index 00000000000..b3fa6a41d97
--- /dev/null
+++ b/lldb/source/Interpreter/CommandObjectRegexCommand.cpp
@@ -0,0 +1,123 @@
+//===-- CommandObjectRegexCommand.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/Interpreter/CommandObjectRegexCommand.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// CommandObjectRegexCommand constructor
+//----------------------------------------------------------------------
+CommandObjectRegexCommand::CommandObjectRegexCommand
+(
+ const char *name,
+ const char *help,
+ const char *syntax,
+ uint32_t max_matches
+) :
+ CommandObject (name, help, syntax),
+ m_entries(),
+ m_max_matches (max_matches)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CommandObjectRegexCommand::~CommandObjectRegexCommand()
+{
+}
+
+
+bool
+CommandObjectRegexCommand::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ return false;
+}
+
+
+bool
+CommandObjectRegexCommand::ExecuteRawCommandString
+(
+ const char *command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ if (command)
+ {
+ EntryCollection::const_iterator pos, end = m_entries.end();
+ for (pos = m_entries.begin(); pos != end; ++pos)
+ {
+ if (pos->regex.Execute (command, m_max_matches))
+ {
+ std::string new_command(pos->command);
+ std::string match_str;
+ char percent_var[8];
+ size_t idx, percent_var_idx;
+ for (uint32_t match_idx=1; match_idx <= m_max_matches; ++match_idx)
+ {
+ if (pos->regex.GetMatchAtIndex (command, match_idx, match_str))
+ {
+ const int percent_var_len = ::snprintf (percent_var, sizeof(percent_var), "%%%u", match_idx);
+ for (idx = 0; (percent_var_idx = new_command.find(percent_var, idx)) != std::string::npos; )
+ {
+ new_command.erase(percent_var_idx, percent_var_len);
+ new_command.insert(percent_var_idx, match_str);
+ idx += percent_var_idx + match_str.size();
+ }
+ }
+ }
+ // Interpret the new command and return this as the result!
+// if (m_options.verbose)
+// result.GetOutputStream().Printf("%s\n", new_command.c_str());
+ return interpreter->HandleCommand(new_command.c_str(), true, result);
+ }
+ }
+ result.SetStatus(eReturnStatusFailed);
+ result.AppendErrorWithFormat("Command contents '%s' failed to match any regular expression in the '%s' regex command.\n",
+ command,
+ m_cmd_name.c_str());
+ return false;
+ }
+ result.AppendError("empty command passed to regular exression command");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+}
+
+
+bool
+CommandObjectRegexCommand::AddRegexCommand (const char *re_cstr, const char *command_cstr)
+{
+ m_entries.resize(m_entries.size() + 1);
+ // Only add the regular expression if it compiles
+ if (m_entries.back().regex.Compile (re_cstr, REG_EXTENDED))
+ {
+ m_entries.back().command.assign (command_cstr);
+ return true;
+ }
+ // The regex didn't compile...
+ m_entries.pop_back();
+ return false;
+}
diff --git a/lldb/source/Interpreter/CommandReturnObject.cpp b/lldb/source/Interpreter/CommandReturnObject.cpp
new file mode 100644
index 00000000000..f634e3c7df5
--- /dev/null
+++ b/lldb/source/Interpreter/CommandReturnObject.cpp
@@ -0,0 +1,175 @@
+//===-- CommandReturnObject.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/Interpreter/CommandReturnObject.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/StreamString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandReturnObject::CommandReturnObject () :
+ m_output_stream (),
+ m_error_stream (),
+ m_status (eReturnStatusStarted),
+ m_did_change_process_state (false)
+{
+}
+
+CommandReturnObject::~CommandReturnObject ()
+{
+}
+
+StreamString &
+CommandReturnObject::GetOutputStream ()
+{
+ return m_output_stream;
+}
+
+StreamString &
+CommandReturnObject::GetErrorStream ()
+{
+ return m_error_stream;
+}
+
+void
+CommandReturnObject::AppendErrorWithFormat (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ StreamString sstrm;
+ sstrm.PrintfVarArg(format, args);
+ va_end (args);
+
+ m_error_stream.Printf("error: %s", sstrm.GetData());
+}
+
+
+void
+CommandReturnObject::AppendMessageWithFormat (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ StreamString sstrm;
+ sstrm.PrintfVarArg(format, args);
+ va_end (args);
+
+ m_output_stream.Printf("%s", sstrm.GetData());
+}
+
+void
+CommandReturnObject::AppendWarningWithFormat (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ StreamString sstrm;
+ sstrm.PrintfVarArg(format, args);
+ va_end (args);
+
+ m_error_stream.Printf("warning: %s", sstrm.GetData());
+}
+
+void
+CommandReturnObject::AppendMessage (const char *in_string, int len)
+{
+ if (len < 0)
+ len = ::strlen (in_string);
+ m_output_stream.Printf("%*.*s\n", len, len, in_string);
+}
+
+void
+CommandReturnObject::AppendWarning (const char *in_string, int len)
+{
+ if (len < 0)
+ len = ::strlen (in_string);
+ m_error_stream.Printf("warning: %*.*s\n", len, len, in_string);
+}
+
+// Similar to AppendWarning, but do not prepend 'warning: ' to message, and
+// don't append "\n" to the end of it.
+
+void
+CommandReturnObject::AppendRawWarning (const char *in_string, int len)
+{
+ if (len < 0)
+ len = ::strlen (in_string);
+ m_error_stream.Printf("%*.*s", len, len, in_string);
+}
+
+void
+CommandReturnObject::AppendError (const char *in_string, int len)
+{
+ if (!in_string)
+ return;
+
+ if (len < 0)
+ len = ::strlen (in_string);
+ m_error_stream.Printf ("error: %*.*s\n", len, len, in_string);
+}
+
+// Similar to AppendError, but do not prepend 'Error: ' to message, and
+// don't append "\n" to the end of it.
+
+void
+CommandReturnObject::AppendRawError (const char *in_string, int len)
+{
+ if (len < 0)
+ len = ::strlen (in_string);
+ m_error_stream.Printf ("%*.*s", len, len, in_string);
+}
+
+void
+CommandReturnObject::SetStatus (ReturnStatus status)
+{
+ m_status = status;
+}
+
+ReturnStatus
+CommandReturnObject::GetStatus ()
+{
+ return m_status;
+}
+
+bool
+CommandReturnObject::Succeeded ()
+{
+ return m_status <= eReturnStatusSuccessContinuingResult;
+}
+
+bool
+CommandReturnObject::HasResult ()
+{
+ return (m_status == eReturnStatusSuccessFinishResult ||
+ m_status == eReturnStatusSuccessContinuingResult);
+}
+
+void
+CommandReturnObject::Clear()
+{
+ m_output_stream.Clear();
+ m_error_stream.Clear();
+ m_status = eReturnStatusStarted;
+}
+
+bool
+CommandReturnObject::GetDidChangeProcessState ()
+{
+ return m_did_change_process_state;
+}
+
+void
+CommandReturnObject::SetDidChangeProcessState (bool b)
+{
+ m_did_change_process_state = b;
+}
+
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp
new file mode 100644
index 00000000000..fa3ac31e691
--- /dev/null
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -0,0 +1,66 @@
+//===-- ScriptInterpreter.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/Interpreter/ScriptInterpreter.h"
+
+#include <string>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+#include "PseudoTerminal.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ScriptInterpreter::ScriptInterpreter (ScriptLanguage script_lang) :
+ m_script_lang (script_lang),
+ m_interpreter_pty ()
+{
+ if (m_interpreter_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, NULL, 0))
+ {
+ const char *slave_name = m_interpreter_pty.GetSlaveName(NULL, 0);
+ if (slave_name)
+ m_pty_slave_name.assign(slave_name);
+ }
+}
+
+ScriptInterpreter::~ScriptInterpreter ()
+{
+ m_interpreter_pty.CloseMasterFileDescriptor();
+}
+
+const char *
+ScriptInterpreter::GetScriptInterpreterPtyName ()
+{
+ return m_pty_slave_name.c_str();
+}
+
+int
+ScriptInterpreter::GetMasterFileDescriptor ()
+{
+ return m_interpreter_pty.GetMasterFileDescriptor();
+}
+
+void
+ScriptInterpreter::CollectDataForBreakpointCommandCallback
+(
+ BreakpointOptions *bp_options,
+ CommandReturnObject &result
+)
+{
+ result.SetStatus (eReturnStatusFailed);
+ result.AppendError ("ScriptInterpreter::GetScriptCommands(StringList &) is not implemented.");
+}
+
+
diff --git a/lldb/source/Interpreter/ScriptInterpreterNone.cpp b/lldb/source/Interpreter/ScriptInterpreterNone.cpp
new file mode 100644
index 00000000000..cdc399e7d86
--- /dev/null
+++ b/lldb/source/Interpreter/ScriptInterpreterNone.cpp
@@ -0,0 +1,38 @@
+//===-- ScriptInterpreterNone.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/Interpreter/ScriptInterpreterNone.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StringList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ScriptInterpreterNone::ScriptInterpreterNone () :
+ ScriptInterpreter (eScriptLanguageNone)
+{
+}
+
+ScriptInterpreterNone::~ScriptInterpreterNone ()
+{
+}
+
+void
+ScriptInterpreterNone::ExecuteOneLine (const std::string &line, FILE *out, FILE *err)
+{
+ ::fprintf (err, "error: there is no embedded script interpreter in this mode.\n");
+}
+
+void
+ScriptInterpreterNone::ExecuteInterpreterLoop (FILE *out, FILE *err)
+{
+ fprintf (err, "error: there is no embedded script interpreter in this mode.\n");
+}
+
+
diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp
new file mode 100644
index 00000000000..6b2e3b2e7ad
--- /dev/null
+++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp
@@ -0,0 +1,830 @@
+//===-- ScriptInterpreterPython.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// In order to guarantee correct working with Python, Python.h *MUST* be
+// the *FIRST* header file included:
+
+#include <Python.h>
+
+#include "lldb/Interpreter/ScriptInterpreterPython.h"
+
+
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <string>
+
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+
+extern "C" void init_lldb (void);
+
+using namespace lldb;
+using namespace lldb_private;
+
+const char embedded_interpreter_string[] =
+"import readline\n\
+import code\n\
+import sys\n\
+import traceback\n\
+\n\
+class SimpleREPL(code.InteractiveConsole):\n\
+ def __init__(self, prompt, dict):\n\
+ code.InteractiveConsole.__init__(self,dict)\n\
+ self.prompt = prompt\n\
+ self.loop_exit = False\n\
+ self.dict = dict\n\
+\n\
+ def interact(self):\n\
+ try:\n\
+ sys.ps1\n\
+ except AttributeError:\n\
+ sys.ps1 = \">>> \"\n\
+ try:\n\
+ sys.ps2\n\
+ except AttributeError:\n\
+ sys.ps2 = \"... \"\n\
+\n\
+ while not self.loop_exit:\n\
+ try:\n\
+ self.read_py_command()\n\
+ except (SystemExit, EOFError):\n\
+ # EOF while in Python just breaks out to top level.\n\
+ self.write('\\n')\n\
+ self.loop_exit = True\n\
+ break\n\
+ except KeyboardInterrupt:\n\
+ self.write(\"\\nKeyboardInterrupt\\n\")\n\
+ self.resetbuffer()\n\
+ more = 0\n\
+ except:\n\
+ traceback.print_exc()\n\
+\n\
+ def process_input (self, in_str):\n\
+ # Canonicalize the format of the input string\n\
+ temp_str = in_str\n\
+ temp_str.strip(' \t')\n\
+ words = temp_str.split()\n\
+ temp_str = ('').join(words)\n\
+\n\
+ # Check the input string to see if it was the quit\n\
+ # command. If so, intercept it, so that it doesn't\n\
+ # close stdin on us!\n\
+ if (temp_str.lower() == \"quit()\"):\n\
+ self.loop_exit = True\n\
+ in_str = \"raise SystemExit \"\n\
+ return in_str\n\
+\n\
+ def my_raw_input (self, prompt):\n\
+ stream = sys.stdout\n\
+ stream.write (prompt)\n\
+ stream.flush ()\n\
+ try:\n\
+ line = sys.stdin.readline()\n\
+ except KeyboardInterrupt:\n\
+ line = \" \\n\"\n\
+ except (SystemExit, EOFError):\n\
+ line = \"quit()\\n\"\n\
+ if not line:\n\
+ raise EOFError\n\
+ if line[-1] == '\\n':\n\
+ line = line[:-1]\n\
+ return line\n\
+\n\
+ def read_py_command(self):\n\
+ # Read off a complete Python command.\n\
+ more = 0\n\
+ while 1:\n\
+ if more:\n\
+ prompt = sys.ps2\n\
+ else:\n\
+ prompt = sys.ps1\n\
+ line = self.my_raw_input(prompt)\n\
+ # Can be None if sys.stdin was redefined\n\
+ encoding = getattr(sys.stdin, \"encoding\", None)\n\
+ if encoding and not isinstance(line, unicode):\n\
+ line = line.decode(encoding)\n\
+ line = self.process_input (line)\n\
+ more = self.push(line)\n\
+ if not more:\n\
+ break\n\
+\n\
+def run_python_interpreter (dict):\n\
+ # Pass in the dictionary, for continuity from one session to the next.\n\
+ repl = SimpleREPL('>>> ', dict)\n\
+ repl.interact()\n";
+
+static int
+_check_and_flush (FILE *stream)
+{
+ int prev_fail = ferror (stream);
+ return fflush (stream) || prev_fail ? EOF : 0;
+}
+
+ScriptInterpreterPython::ScriptInterpreterPython () :
+ ScriptInterpreter (eScriptLanguagePython),
+ m_compiled_module (NULL),
+ m_termios_valid (false)
+{
+
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+ // Find the module that owns this code and use that path we get to
+ // set the PYTHONPATH appropriately.
+
+ FileSpec this_module (Host::GetModuleFileSpecForHostAddress ((void *)init_lldb));
+ std::string python_path;
+
+ if (this_module.GetDirectory())
+ {
+ // Append the directory that the module that loaded this code
+ // belongs to
+ python_path += this_module.GetDirectory().AsCString("");
+
+#if defined (__APPLE__)
+ // If we are running on MacOSX we might be in a framework and should
+ // add an appropriate path so Resource can be found in a bundle
+
+ if (::strstr(this_module.GetDirectory().AsCString(""), ".framework"))
+ {
+ python_path.append(1, ':');
+ python_path.append(this_module.GetDirectory().AsCString(""));
+ python_path.append("/Resources/Python");
+ }
+#endif
+ // The the PYTHONPATH environment variable so that Python can find
+ // our lldb.py module and our _lldb.so.
+ ::setenv ("PYTHONPATH", python_path.c_str(), 1);
+ }
+
+ Py_Initialize ();
+
+ PyObject *compiled_module = Py_CompileString (embedded_interpreter_string, "embedded_interpreter.py",
+ Py_file_input);
+
+ m_compiled_module = compiled_module;
+
+ init_lldb ();
+
+ // Update the path python uses to search for modules to include the current directory.
+
+ int success = PyRun_SimpleString ("import sys");
+ success = PyRun_SimpleString ("sys.path.append ('.')");
+ if (success == 0)
+ {
+ // Import the Script Bridge module.
+ success = PyRun_SimpleString ("from lldb import *");
+ }
+
+ const char *pty_slave_name = GetScriptInterpreterPtyName ();
+ FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+
+ PyObject *pmod = PyImport_ExecCodeModule((char *)"embedded_interpreter", m_compiled_module);
+ if (pmod != NULL)
+ {
+ PyRun_SimpleString ("ConsoleDict = locals()");
+ PyRun_SimpleString ("from embedded_interpreter import run_python_interpreter");
+ PyRun_SimpleString ("import sys");
+ PyRun_SimpleString ("from termios import *");
+ PyRun_SimpleString ("old_stdin = sys.stdin");
+
+ StreamString run_string;
+ run_string.Printf ("new_stdin = open('%s', 'r')", pty_slave_name);
+ PyRun_SimpleString (run_string.GetData());
+ PyRun_SimpleString ("sys.stdin = new_stdin");
+
+ PyRun_SimpleString ("old_stdout = sys.stdout");
+
+ if (out_fh != NULL)
+ {
+ PyObject *new_sysout = PyFile_FromFile (out_fh, (char *) "", (char *) "w",
+ _check_and_flush);
+ PyObject *sysmod = PyImport_AddModule ("sys");
+ PyObject *sysdict = PyModule_GetDict (sysmod);
+
+ if ((new_sysout != NULL)
+ && (sysmod != NULL)
+ && (sysdict != NULL))
+ {
+ PyDict_SetItemString (sysdict, "stdout", new_sysout);
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ }
+
+ PyRun_SimpleString ("new_mode = tcgetattr(new_stdin)");
+ PyRun_SimpleString ("new_mode[3] = new_mode[3] | ECHO | ICANON");
+ PyRun_SimpleString ("new_mode[6][VEOF] = 255");
+ PyRun_SimpleString ("tcsetattr (new_stdin, TCSANOW, new_mode)");
+ }
+
+
+}
+
+ScriptInterpreterPython::~ScriptInterpreterPython ()
+{
+ PyRun_SimpleString ("sys.stdin = old_stdin");
+ PyRun_SimpleString ("sys.stdout = old_stdout");
+ Py_Finalize ();
+}
+
+void
+ScriptInterpreterPython::ExecuteOneLine (const std::string& line, FILE *out, FILE *err)
+{
+ int success;
+
+ success = PyRun_SimpleString (line.c_str());
+ if (success != 0)
+ {
+ fprintf (err, "error: python failed attempting to evaluate '%s'\n", line.c_str());
+ }
+}
+
+
+
+size_t
+ScriptInterpreterPython::InputReaderCallback
+(
+ void *baton,
+ InputReader *reader,
+ lldb::InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len
+)
+{
+ if (baton == NULL)
+ return 0;
+
+ ScriptInterpreterPython *interpreter = (ScriptInterpreterPython *) baton;
+ switch (notification)
+ {
+ case eInputReaderActivate:
+ {
+ // Save terminal settings if we can
+ interpreter->m_termios_valid = ::tcgetattr (::fileno (reader->GetInputFileHandle()),
+ &interpreter->m_termios) == 0;
+ struct termios tmp_termios;
+ if (::tcgetattr (::fileno (reader->GetInputFileHandle()), &tmp_termios) == 0)
+ {
+ tmp_termios.c_cc[VEOF] = _POSIX_VDISABLE;
+ ::tcsetattr (::fileno (reader->GetInputFileHandle()), TCSANOW, &tmp_termios);
+ }
+ }
+ break;
+
+ case eInputReaderDeactivate:
+ break;
+
+ case eInputReaderReactivate:
+ break;
+
+ case eInputReaderGotToken:
+ if (bytes && bytes_len)
+ {
+ if ((int) bytes[0] == 4)
+ ::write (interpreter->GetMasterFileDescriptor(), "quit()", 6);
+ else
+ ::write (interpreter->GetMasterFileDescriptor(), bytes, bytes_len);
+ }
+ ::write (interpreter->GetMasterFileDescriptor(), "\n", 1);
+ break;
+
+ case eInputReaderDone:
+ // Send a control D to the script interpreter
+ //::write (interpreter->GetMasterFileDescriptor(), "\nquit()\n", strlen("\nquit()\n"));
+ // Write a newline out to the reader output
+ //::fwrite ("\n", 1, 1, out_fh);
+ // Restore terminal settings if they were validly saved
+ if (interpreter->m_termios_valid)
+ {
+ ::tcsetattr (::fileno (reader->GetInputFileHandle()),
+ TCSANOW,
+ &interpreter->m_termios);
+ }
+ break;
+ }
+
+ return bytes_len;
+}
+
+
+void
+ScriptInterpreterPython::ExecuteInterpreterLoop (FILE *out, FILE *err)
+{
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+ InputReaderSP reader_sp (new InputReader());
+ if (reader_sp)
+ {
+ Error error (reader_sp->Initialize (ScriptInterpreterPython::InputReaderCallback,
+ this, // baton
+ eInputReaderGranularityLine, // token size, to pass to callback function
+ NULL, // end token
+ NULL, // prompt
+ true)); // echo input
+
+ if (error.Success())
+ {
+ Debugger::GetSharedInstance().PushInputReader (reader_sp);
+ ExecuteOneLine ("run_python_interpreter(ConsoleDict)", out, err);
+ Debugger::GetSharedInstance().PopInputReader (reader_sp);
+ }
+ }
+}
+
+bool
+ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
+ ScriptInterpreter::ReturnType return_type,
+ void *ret_value)
+{
+ PyObject *py_return = NULL;
+ PyObject *mainmod = PyImport_AddModule ("__main__");
+ PyObject *globals = PyModule_GetDict (mainmod);
+ PyObject *locals = globals;
+ PyObject *py_error = NULL;
+ bool ret_success;
+ int success;
+
+ if (in_string != NULL)
+ {
+ py_return = PyRun_String (in_string, Py_eval_input, globals, locals);
+ if (py_return == NULL)
+ {
+ py_error = PyErr_Occurred ();
+ if (py_error != NULL)
+ PyErr_Clear ();
+
+ py_return = PyRun_String (in_string, Py_single_input, globals, locals);
+ }
+
+ if (py_return != NULL)
+ {
+ switch (return_type)
+ {
+ case eCharPtr: // "char *"
+ {
+ const char format[3] = "s#";
+ success = PyArg_Parse (py_return, format, (char **) &ret_value);
+ break;
+ }
+ case eBool:
+ {
+ const char format[2] = "b";
+ success = PyArg_Parse (py_return, format, (bool *) ret_value);
+ break;
+ }
+ case eShortInt:
+ {
+ const char format[2] = "h";
+ success = PyArg_Parse (py_return, format, (short *) ret_value);
+ break;
+ }
+ case eShortIntUnsigned:
+ {
+ const char format[2] = "H";
+ success = PyArg_Parse (py_return, format, (unsigned short *) ret_value);
+ break;
+ }
+ case eInt:
+ {
+ const char format[2] = "i";
+ success = PyArg_Parse (py_return, format, (int *) ret_value);
+ break;
+ }
+ case eIntUnsigned:
+ {
+ const char format[2] = "I";
+ success = PyArg_Parse (py_return, format, (unsigned int *) ret_value);
+ break;
+ }
+ case eLongInt:
+ {
+ const char format[2] = "l";
+ success = PyArg_Parse (py_return, format, (long *) ret_value);
+ break;
+ }
+ case eLongIntUnsigned:
+ {
+ const char format[2] = "k";
+ success = PyArg_Parse (py_return, format, (unsigned long *) ret_value);
+ break;
+ }
+ case eLongLong:
+ {
+ const char format[2] = "L";
+ success = PyArg_Parse (py_return, format, (long long *) ret_value);
+ break;
+ }
+ case eLongLongUnsigned:
+ {
+ const char format[2] = "K";
+ success = PyArg_Parse (py_return, format, (unsigned long long *) ret_value);
+ break;
+ }
+ case eFloat:
+ {
+ const char format[2] = "f";
+ success = PyArg_Parse (py_return, format, (float *) ret_value);
+ break;
+ }
+ case eDouble:
+ {
+ const char format[2] = "d";
+ success = PyArg_Parse (py_return, format, (double *) ret_value);
+ break;
+ }
+ case eChar:
+ {
+ const char format[2] = "c";
+ success = PyArg_Parse (py_return, format, (char *) ret_value);
+ break;
+ }
+ default:
+ {}
+ }
+ Py_DECREF (py_return);
+ if (success)
+ ret_success = true;
+ else
+ ret_success = false;
+ }
+ }
+
+ py_error = PyErr_Occurred();
+ if (py_error != NULL)
+ {
+ if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
+ PyErr_Print ();
+ PyErr_Clear();
+ ret_success = false;
+ }
+
+ return ret_success;
+}
+
+bool
+ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string)
+{
+ bool success = false;
+ PyObject *py_return = NULL;
+ PyObject *mainmod = PyImport_AddModule ("__main__");
+ PyObject *globals = PyModule_GetDict (mainmod);
+ PyObject *locals = globals;
+ PyObject *py_error = NULL;
+
+ if (in_string != NULL)
+ {
+ struct _node *compiled_node = PyParser_SimpleParseString (in_string, Py_file_input);
+ if (compiled_node)
+ {
+ PyCodeObject *compiled_code = PyNode_Compile (compiled_node, "temp.py");
+ if (compiled_code)
+ {
+ py_return = PyEval_EvalCode (compiled_code, globals, locals);
+ if (py_return != NULL)
+ {
+ success = true;
+ Py_DECREF (py_return);
+ }
+ }
+ }
+ }
+
+ py_error = PyErr_Occurred ();
+ if (py_error != NULL)
+ {
+ if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
+ PyErr_Print ();
+ PyErr_Clear();
+ success = false;
+ }
+
+ return success;
+}
+
+static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.";
+
+size_t
+ScriptInterpreterPython::GenerateBreakpointOptionsCommandCallback
+(
+ void *baton,
+ InputReader *reader,
+ lldb::InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len
+)
+{
+ static StringList commands_in_progress;
+
+ FILE *out_fh = reader->GetOutputFileHandle();
+ switch (notification)
+ {
+ case eInputReaderActivate:
+ {
+ commands_in_progress.Clear();
+ if (out_fh)
+ {
+ ::fprintf (out_fh, "%s\n", g_reader_instructions);
+ if (reader->GetPrompt())
+ ::fprintf (out_fh, "%s", reader->GetPrompt());
+ }
+ }
+ break;
+
+ case eInputReaderDeactivate:
+ break;
+
+ case eInputReaderReactivate:
+ if (reader->GetPrompt() && out_fh)
+ ::fprintf (out_fh, "%s", reader->GetPrompt());
+ break;
+
+ case eInputReaderGotToken:
+ {
+ std::string temp_string (bytes, bytes_len);
+ commands_in_progress.AppendString (temp_string.c_str());
+ if (out_fh && !reader->IsDone() && reader->GetPrompt())
+ ::fprintf (out_fh, "%s", reader->GetPrompt());
+ }
+ break;
+
+ case eInputReaderDone:
+ {
+ BreakpointOptions *bp_options = (BreakpointOptions *)baton;
+ std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+ data_ap->user_source.AppendList (commands_in_progress);
+ if (data_ap.get())
+ {
+ ScriptInterpreter *interpreter = Debugger::GetSharedInstance().GetCommandInterpreter().GetScriptInterpreter();
+ if (interpreter)
+ {
+ if (interpreter->GenerateBreakpointCommandCallbackData (data_ap->user_source,
+ data_ap->script_source))
+ {
+ if (data_ap->script_source.GetSize() == 1)
+ {
+ BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+ bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
+ }
+ }
+ }
+ else
+ {
+ // FIXME: Error processing.
+ }
+ }
+ }
+ break;
+
+ }
+
+ return bytes_len;
+}
+
+void
+ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
+ CommandReturnObject &result)
+{
+ InputReaderSP reader_sp (new InputReader ());
+
+ if (reader_sp)
+ {
+ Error err = reader_sp->Initialize (
+ ScriptInterpreterPython::GenerateBreakpointOptionsCommandCallback,
+ bp_options, // baton
+ eInputReaderGranularityLine, // token size, for feeding data to callback function
+ "DONE", // end token
+ "> ", // prompt
+ true); // echo input
+
+ if (err.Success())
+ Debugger::GetSharedInstance().PushInputReader (reader_sp);
+ else
+ {
+ result.AppendError (err.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError("out of memory");
+ result.SetStatus (eReturnStatusFailed);
+ }
+}
+
+bool
+ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def)
+{
+ // Convert StringList to one long, newline delimited, const char *.
+ std::string function_def_string;
+
+ int num_lines = function_def.GetSize();
+
+ for (int i = 0; i < num_lines; ++i)
+ {
+ function_def_string.append (function_def.GetStringAtIndex(i));
+ if (function_def_string.at (function_def_string.length() - 1) != '\n')
+ function_def_string.append ("\n");
+
+ }
+
+ return ExecuteMultipleLines (function_def_string.c_str());
+}
+
+bool
+ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, StringList &callback_data)
+{
+ static int num_created_functions = 0;
+
+ user_input.RemoveBlankLines ();
+ int num_lines = user_input.GetSize();
+ std::string last_function_call;
+
+ // Go through lines of input looking for any function definitions. For each function definition found,
+ // export the function definition to Python, create a potential function call for the function, and
+ // mark the lines of the function to be removed from the user input.
+
+ for (int i = 0; i < num_lines; ++i)
+ {
+ int function_start = i;
+ std::string current_str = user_input.GetStringAtIndex (i);
+ const char *current_line = current_str.c_str();
+ int len = 0;
+ if (current_line)
+ len = strlen (current_line);
+
+ // Check to see if the current line is the start of a Python function definition.
+ if (len > 4 && strncmp (current_line, "def ", 4) == 0)
+ {
+ // We've found the first line of a function. First, get the function name.
+
+ // Skip over the 'def '.
+ char *start = (char *) current_line + 4;
+
+ // Skip over white space.
+ while (start[0] == ' ' || start[0] == '\t')
+ ++start;
+
+ // Find the end of the function name.
+ char *end = start;
+ while (isalnum (end[0]) || end[0] == '_')
+ ++end;
+
+ int name_len = end - start;
+ std::string func_name = current_str.substr (4, name_len);
+
+ // Now to find the last line of the function. That will be the first line that does not begin with
+ // any white space (thanks to Python's indentation rules).
+ ++i;
+ bool found = false;
+ while (i < num_lines && !found)
+ {
+ std::string next_str = user_input.GetStringAtIndex (i);
+ const char *next_line = next_str.c_str();
+ if (next_line[0] != ' ' && next_line[0] != '\t')
+ found = true;
+ else
+ ++i;
+ }
+ if (found)
+ --i; // Make 'i' correspond to the last line of the function.
+ int function_end = i;
+
+ // Special case: All of user_input is one big function definition.
+ if ((function_start == 0) && (function_end == (num_lines - 1)))
+ {
+ ExportFunctionDefinitionToInterpreter (user_input);
+ last_function_call = func_name + " ()";
+ callback_data.AppendString (last_function_call.c_str());
+ return callback_data.GetSize() > 0;
+ }
+ else
+ {
+ // Make a copy of the function definition:
+ StringList new_function;
+ for (int k = function_start; k <= function_end; ++k)
+ {
+ new_function.AppendString (user_input.GetStringAtIndex (k));
+ // Mark the string to be deleted from user_input.
+ user_input.DeleteStringAtIndex (k);
+ user_input.InsertStringAtIndex (k, "<lldb_delete>");
+ }
+ ExportFunctionDefinitionToInterpreter (new_function);
+ last_function_call = func_name + " ()";
+ }
+ }
+ }
+
+ // Now instead of trying to really delete the marked lines from user_input, we will just copy all the
+ // unmarked lines into a new StringList.
+
+ StringList new_user_input;
+
+ for (int i = 0; i < num_lines; ++i)
+ {
+ std::string current_string = user_input.GetStringAtIndex (i);
+ if (current_string.compare (0, 13, "<lldb_delete>") == 0)
+ continue;
+
+ new_user_input.AppendString (current_string.c_str());
+ }
+
+ num_lines = new_user_input.GetSize();
+
+ if (num_lines > 0)
+ {
+ if (num_lines == 1
+ && strchr (new_user_input.GetStringAtIndex(0), '\n') == NULL)
+ {
+ // If there's only one line of input, and it doesn't contain any newline characters....
+ callback_data.AppendString (new_user_input.GetStringAtIndex (0));
+ }
+ else
+ {
+ // Create the new function name.
+ StreamString func_name;
+ func_name.Printf ("lldb_bp_callback_func_%d", num_created_functions);
+ //std::string func_name = "lldb_bp_callback_func_" + num_created_functions;
+ ++num_created_functions;
+
+ // Create the function call for the new function.
+ last_function_call = func_name.GetString() + " ()";
+
+ // Create the Python function definition line (which will have to be inserted at the beginning of
+ // the function).
+ std::string def_line = "def " + func_name.GetString() + " ():";
+
+
+ // Indent all lines an additional four spaces (as they are now being put inside a function definition).
+ for (int i = 0; i < num_lines; ++i)
+ {
+ const char *temp_cstring = new_user_input.GetStringAtIndex(i);
+ std::string temp2 = " ";
+ temp2.append(temp_cstring);
+ new_user_input.DeleteStringAtIndex (i);
+ new_user_input.InsertStringAtIndex (i, temp2.c_str());
+ }
+
+ // Insert the function definition line at the top of the new function.
+ new_user_input.InsertStringAtIndex (0, def_line.c_str());
+
+ ExportFunctionDefinitionToInterpreter (new_user_input);
+ callback_data.AppendString (last_function_call.c_str());
+ }
+ }
+ else
+ {
+ if (!last_function_call.empty())
+ callback_data.AppendString (last_function_call.c_str());
+ }
+
+ return callback_data.GetSize() > 0;
+}
+
+bool
+ScriptInterpreterPython::BreakpointCallbackFunction
+(
+ void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id
+)
+{
+ bool ret_value = true;
+ bool temp_bool;
+
+ BreakpointOptions::CommandData *bp_option_data = (BreakpointOptions::CommandData *) baton;
+
+ const char *python_string = bp_option_data->script_source.GetStringAtIndex(0);
+
+ if (python_string != NULL)
+ {
+ bool success =
+ Debugger::GetSharedInstance().GetCommandInterpreter().GetScriptInterpreter()->ExecuteOneLineWithReturn
+ (python_string,
+ ScriptInterpreter::eBool,
+ (void *) &temp_bool);
+ if (success)
+ ret_value = temp_bool;
+ }
+
+ return ret_value;
+}
diff --git a/lldb/source/Interpreter/StateVariable.cpp b/lldb/source/Interpreter/StateVariable.cpp
new file mode 100644
index 00000000000..3f3c3fdb1e0
--- /dev/null
+++ b/lldb/source/Interpreter/StateVariable.cpp
@@ -0,0 +1,320 @@
+//===-- StateVariable.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/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+
+
+#include "lldb/Interpreter/StateVariable.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// Variables with integer values.
+
+StateVariable::StateVariable
+(
+ const char *name,
+ int value,
+ const char *help,
+ Callback func_ptr
+) :
+ m_name (name),
+ m_type (eTypeInteger),
+ m_help_text (help),
+ m_verification_func_ptr (func_ptr)
+{
+ m_int_value = value;
+}
+
+// Variables with boolean values.
+
+StateVariable::StateVariable
+(
+ const char *name,
+ bool value,
+ const char *help,
+ Callback func_ptr
+ ) :
+ m_name (name),
+ m_type (eTypeBoolean),
+ m_help_text (help),
+ m_verification_func_ptr (func_ptr)
+{
+ m_int_value = value;
+}
+
+// Variables with string values.
+
+StateVariable::StateVariable
+(
+ const char *name,
+ const char *value,
+ bool can_append,
+ const char *help,
+ Callback func_ptr
+ ) :
+ m_name (name),
+ m_type (eTypeString),
+ m_int_value (0),
+ m_string_values (),
+ m_help_text (help),
+ m_verification_func_ptr (func_ptr)
+{
+ m_string_values.AppendArgument(value);
+}
+
+// Variables with array of strings values.
+
+StateVariable::StateVariable
+(
+ const char *name,
+ const Args *args,
+ const char *help,
+ Callback func_ptr
+ ) :
+ m_name (name),
+ m_type (eTypeStringArray),
+ m_help_text (help),
+ m_string_values(),
+ m_verification_func_ptr (func_ptr)
+{
+ if (args)
+ m_string_values = *args;
+}
+
+StateVariable::~StateVariable ()
+{
+}
+
+const char *
+StateVariable::GetName () const
+{
+ return m_name.c_str();
+}
+
+StateVariable::Type
+StateVariable::GetType () const
+{
+ return m_type;
+}
+
+int
+StateVariable::GetIntValue () const
+{
+ return m_int_value;
+}
+
+bool
+StateVariable::GetBoolValue () const
+{
+ return m_int_value;
+}
+
+const char *
+StateVariable::GetStringValue () const
+{
+ return m_string_values.GetArgumentAtIndex(0);
+}
+
+const Args &
+StateVariable::GetArgs () const
+{
+ return m_string_values;
+}
+
+Args &
+StateVariable::GetArgs ()
+{
+ return m_string_values;
+}
+
+const char *
+StateVariable::GetHelp () const
+{
+ return m_help_text.c_str();
+}
+
+void
+StateVariable::SetHelp (const char *help)
+{
+ m_help_text = help;
+}
+
+void
+StateVariable::AppendVariableInformation (CommandReturnObject &result)
+{
+ switch (m_type)
+ {
+ case eTypeBoolean:
+ if (m_int_value)
+ result.AppendMessageWithFormat (" %s (bool) = True\n", m_name.c_str());
+ else
+ result.AppendMessageWithFormat (" %s (bool) = False\n", m_name.c_str());
+ break;
+
+ case eTypeInteger:
+ result.AppendMessageWithFormat (" %s (int) = %d\n", m_name.c_str(), m_int_value);
+ break;
+
+ case eTypeString:
+ {
+ const char *cstr = m_string_values.GetArgumentAtIndex(0);
+ if (cstr && cstr[0])
+ result.AppendMessageWithFormat (" %s (str) = '%s'\n", m_name.c_str(), cstr);
+ else
+ result.AppendMessageWithFormat (" %s (str) = <no value>\n", m_name.c_str());
+ }
+ break;
+
+ case eTypeStringArray:
+ {
+ const size_t argc = m_string_values.GetArgumentCount();
+ result.AppendMessageWithFormat (" %s (string vector):\n", m_name.c_str());
+ for (size_t i = 0; i < argc; ++i)
+ result.AppendMessageWithFormat (" [%d] %s\n", i, m_string_values.GetArgumentAtIndex(i));
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+StateVariable::SetStringValue (const char *new_value)
+{
+ if (m_string_values.GetArgumentCount() > 0)
+ m_string_values.ReplaceArgumentAtIndex(0, new_value);
+ else
+ m_string_values.AppendArgument(new_value);
+}
+
+void
+StateVariable::SetIntValue (int new_value)
+{
+ m_int_value = new_value;
+}
+
+void
+StateVariable::SetBoolValue (bool new_value)
+{
+ m_int_value = new_value;
+}
+
+void
+StateVariable::AppendStringValue (const char *cstr)
+{
+ if (cstr && cstr[0])
+ {
+ if (m_string_values.GetArgumentCount() == 0)
+ {
+ m_string_values.AppendArgument(cstr);
+ }
+ else
+ {
+ const char *curr_arg = m_string_values.GetArgumentAtIndex(0);
+ if (curr_arg != NULL)
+ {
+ std::string new_arg_str(curr_arg);
+ new_arg_str += " ";
+ new_arg_str += cstr;
+ m_string_values.ReplaceArgumentAtIndex(0, new_arg_str.c_str());
+ }
+ else
+ {
+ m_string_values.ReplaceArgumentAtIndex(0, cstr);
+ }
+ }
+ }
+}
+
+bool
+StateVariable::VerifyValue (CommandInterpreter *interpreter, void *data, CommandReturnObject &result)
+{
+ return (*m_verification_func_ptr) (interpreter, data, result);
+}
+
+//void
+//StateVariable::SetArrayValue (STLStringArray &new_value)
+//{
+// m_string_values.AppendArgument.append(cstr);
+//
+// if (m_array_value != NULL)
+// {
+// if (m_array_value->size() > 0)
+// {
+// m_array_value->clear();
+// }
+// }
+// else
+// m_array_value = new STLStringArray;
+//
+// for (int i = 0; i < new_value.size(); ++i)
+// m_array_value->push_back (new_value[i]);
+//}
+//
+
+void
+StateVariable::ArrayClearValues ()
+{
+ m_string_values.Clear();
+}
+
+
+void
+StateVariable::ArrayAppendValue (const char *cstr)
+{
+ m_string_values.AppendArgument(cstr);
+}
+
+
+bool
+StateVariable::HasVerifyFunction ()
+{
+ return (m_verification_func_ptr != NULL);
+}
+
+// Verification functions for various command interpreter variables.
+
+bool
+StateVariable::VerifyScriptLanguage (CommandInterpreter *interpreter, void *data, CommandReturnObject &result)
+{
+ bool valid_lang = true;
+ interpreter->SetScriptLanguage (Args::StringToScriptLanguage((char *) data, eScriptLanguageDefault, &valid_lang));
+ return valid_lang;
+}
+
+bool
+StateVariable::BroadcastPromptChange (CommandInterpreter *interpreter, void *data, CommandReturnObject &result)
+{
+ char *prompt = (char *) data;
+ if (prompt != NULL)
+ {
+ std::string tmp_prompt = prompt ;
+ int len = tmp_prompt.size();
+ if (len > 1
+ && (tmp_prompt[0] == '\'' || tmp_prompt[0] == '"')
+ && (tmp_prompt[len-1] == tmp_prompt[0]))
+ {
+ tmp_prompt = tmp_prompt.substr(1,len-2);
+ }
+ len = tmp_prompt.size();
+ if (tmp_prompt[len-1] != ' ')
+ tmp_prompt.append(" ");
+ strcpy (prompt, tmp_prompt.c_str());
+ data = (void *) prompt;
+ }
+ EventSP new_event_sp;
+ new_event_sp.reset (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (prompt)));
+ interpreter->BroadcastEvent (new_event_sp);
+
+ return true;
+}
+
diff --git a/lldb/source/Interpreter/embedded_interpreter.py b/lldb/source/Interpreter/embedded_interpreter.py
new file mode 100644
index 00000000000..38b2f9ef01e
--- /dev/null
+++ b/lldb/source/Interpreter/embedded_interpreter.py
@@ -0,0 +1,90 @@
+import readline
+import code
+import sys
+import traceback
+
+class SimpleREPL(code.InteractiveConsole):
+ def __init__(self, prompt, dict):
+ code.InteractiveConsole.__init__(self,dict)
+ self.prompt = prompt
+ self.loop_exit = False
+ self.dict = dict
+
+ def interact(self):
+ try:
+ sys.ps1
+ except AttributeError:
+ sys.ps1 = ">>> "
+ try:
+ sys.ps2
+ except AttributeError:
+ sys.ps2 = "... "
+
+ while not self.loop_exit:
+ try:
+ self.read_py_command()
+ except (SystemExit, EOFError):
+ # EOF while in Python just breaks out to top level.
+ self.write('\n')
+ self.loop_exit = True
+ break
+ except KeyboardInterrupt:
+ self.write("\nKeyboardInterrupt\n")
+ self.resetbuffer()
+ more = 0
+ except:
+ traceback.print_exc()
+
+ def process_input (self, in_str):
+ # Canonicalize the format of the input string
+ temp_str = in_str
+ temp_str.strip(' \t')
+ words = temp_str.split()
+ temp_str = ('').join(words)
+
+ # Check the input string to see if it was the quit
+ # command. If so, intercept it, so that it doesn't
+ # close stdin on us!
+ if (temp_str.lower() == "quit()"):
+ self.loop_exit = True
+ in_str = "raise SystemExit "
+ return in_str
+
+ def my_raw_input (self, prompt):
+ stream = sys.stdout
+ stream.write (prompt)
+ stream.flush ()
+ try:
+ line = sys.stdin.readline()
+ except KeyboardInterrupt:
+ line = " \n"
+ except (SystemExit, EOFError):
+ line = "quit()\n"
+ if not line:
+ raise EOFError
+ if line[-1] == '\n':
+ line = line[:-1]
+ return line
+
+ def read_py_command(self):
+ # Read off a complete Python command.
+ more = 0
+ while 1:
+ if more:
+ prompt = sys.ps2
+ else:
+ prompt = sys.ps1
+ line = self.my_raw_input(prompt)
+ # Can be None if sys.stdin was redefined
+ encoding = getattr(sys.stdin, "encoding", None)
+ if encoding and not isinstance(line, unicode):
+ line = line.decode(encoding)
+ line = self.process_input (line)
+ more = self.push(line)
+ if not more:
+ break
+
+def run_python_interpreter (dict):
+ # Pass in the dictionary, for continuity from one session to the next.
+ repl = SimpleREPL('>>> ', dict)
+ repl.interact()
OpenPOWER on IntegriCloud