Initial checkin of lldb code from internal Apple repo.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@105619 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Interpreter/CommandCompletions.cpp b/source/Interpreter/CommandCompletions.cpp
new file mode 100644
index 0000000..a299ffb
--- /dev/null
+++ b/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/source/Interpreter/CommandContext.cpp b/source/Interpreter/CommandContext.cpp
new file mode 100644
index 0000000..012611c
--- /dev/null
+++ b/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/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp
new file mode 100644
index 0000000..ed85b33
--- /dev/null
+++ b/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/source/Interpreter/CommandObject.cpp b/source/Interpreter/CommandObject.cpp
new file mode 100644
index 0000000..080b5b0
--- /dev/null
+++ b/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/source/Interpreter/CommandObjectCrossref.cpp b/source/Interpreter/CommandObjectCrossref.cpp
new file mode 100644
index 0000000..27b6637
--- /dev/null
+++ b/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/source/Interpreter/CommandObjectMultiword.cpp b/source/Interpreter/CommandObjectMultiword.cpp
new file mode 100644
index 0000000..874be0e
--- /dev/null
+++ b/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/source/Interpreter/CommandObjectRegexCommand.cpp b/source/Interpreter/CommandObjectRegexCommand.cpp
new file mode 100644
index 0000000..b3fa6a4
--- /dev/null
+++ b/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/source/Interpreter/CommandReturnObject.cpp b/source/Interpreter/CommandReturnObject.cpp
new file mode 100644
index 0000000..f634e3c
--- /dev/null
+++ b/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/source/Interpreter/ScriptInterpreter.cpp b/source/Interpreter/ScriptInterpreter.cpp
new file mode 100644
index 0000000..fa3ac31
--- /dev/null
+++ b/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/source/Interpreter/ScriptInterpreterNone.cpp b/source/Interpreter/ScriptInterpreterNone.cpp
new file mode 100644
index 0000000..cdc399e
--- /dev/null
+++ b/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/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp
new file mode 100644
index 0000000..6b2e3b2
--- /dev/null
+++ b/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/source/Interpreter/StateVariable.cpp b/source/Interpreter/StateVariable.cpp
new file mode 100644
index 0000000..3f3c3fd
--- /dev/null
+++ b/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/source/Interpreter/embedded_interpreter.py b/source/Interpreter/embedded_interpreter.py
new file mode 100644
index 0000000..38b2f9e
--- /dev/null
+++ b/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()