summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/lldb/source/Interpreter
diff options
context:
space:
mode:
authoremaste <emaste@FreeBSD.org>2013-08-23 18:06:42 +0000
committeremaste <emaste@FreeBSD.org>2013-08-23 18:06:42 +0000
commit424d4dadd208e2a1e9a43c3d55f47f03ba0c4509 (patch)
tree05d762b98a499804ce690e6ce04033f1ddf4dee6 /contrib/llvm/tools/lldb/source/Interpreter
parentcde487f27a84e02a560384f75178fddca68740f6 (diff)
parentdcd15f81789e389c1cb27d264fcdddfd0a6002bd (diff)
downloadFreeBSD-src-424d4dadd208e2a1e9a43c3d55f47f03ba0c4509.zip
FreeBSD-src-424d4dadd208e2a1e9a43c3d55f47f03ba0c4509.tar.gz
Merge lldb r188801 to contrib/llvm/tools/lldb/
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Interpreter')
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/Args.cpp1789
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandHistory.cpp143
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp2882
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp1174
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandObjectRegexCommand.cpp150
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.cpp93
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.h42
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/CommandReturnObject.cpp219
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupArchitecture.cpp86
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupBoolean.cpp67
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupFile.cpp97
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupFormat.cpp249
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupOutputFile.cpp81
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupPlatform.cpp149
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupString.cpp58
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupUInt64.cpp58
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupUUID.cpp76
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp181
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupVariable.cpp144
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionGroupWatchpoint.cpp121
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValue.cpp633
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueArch.cpp111
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueArgs.cpp38
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueArray.cpp350
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueBoolean.cpp135
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp436
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueEnumeration.cpp166
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpec.cpp159
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp186
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormat.cpp78
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValuePathMappings.cpp185
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp762
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueRegex.cpp86
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueSInt64.cpp89
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueString.cpp186
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueUInt64.cpp89
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/OptionValueUUID.cpp123
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/Options.cpp1077
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/Property.cpp275
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/PythonDataObjects.cpp430
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreter.cpp105
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterNone.cpp43
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp3166
-rw-r--r--contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py103
44 files changed, 16870 insertions, 0 deletions
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/Args.cpp b/contrib/llvm/tools/lldb/source/Interpreter/Args.cpp
new file mode 100644
index 0000000..e6d2043
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/Args.cpp
@@ -0,0 +1,1789 @@
+//===-- Args.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+// C Includes
+#include <getopt.h>
+#include <cstdlib>
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/Interpreter/Options.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+//#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+//#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Args constructor
+//----------------------------------------------------------------------
+Args::Args (const char *command) :
+ m_args(),
+ m_argv(),
+ m_args_quote_char()
+{
+ if (command)
+ SetCommandString (command);
+}
+
+
+Args::Args (const char *command, size_t len) :
+ m_args(),
+ m_argv(),
+ m_args_quote_char()
+{
+ if (command && len)
+ SetCommandString (command, len);
+}
+
+//----------------------------------------------------------------------
+// We have to be very careful on the copy constructor of this class
+// to make sure we copy all of the string values, but we can't copy the
+// rhs.m_argv into m_argv since it will point to the "const char *" c
+// strings in rhs.m_args. We need to copy the string list and update our
+// own m_argv appropriately.
+//----------------------------------------------------------------------
+Args::Args (const Args &rhs) :
+ m_args (rhs.m_args),
+ m_argv (),
+ m_args_quote_char(rhs.m_args_quote_char)
+{
+ UpdateArgvFromArgs();
+}
+
+//----------------------------------------------------------------------
+// We have to be very careful on the copy constructor of this class
+// to make sure we copy all of the string values, but we can't copy the
+// rhs.m_argv into m_argv since it will point to the "const char *" c
+// strings in rhs.m_args. We need to copy the string list and update our
+// own m_argv appropriately.
+//----------------------------------------------------------------------
+const Args &
+Args::operator= (const Args &rhs)
+{
+ // Make sure we aren't assigning to self
+ if (this != &rhs)
+ {
+ m_args = rhs.m_args;
+ m_args_quote_char = rhs.m_args_quote_char;
+ UpdateArgvFromArgs();
+ }
+ return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Args::~Args ()
+{
+}
+
+void
+Args::Dump (Stream *s)
+{
+ const size_t argc = m_argv.size();
+ for (size_t i=0; i<argc; ++i)
+ {
+ s->Indent();
+ const char *arg_cstr = m_argv[i];
+ if (arg_cstr)
+ s->Printf("argv[%zi]=\"%s\"\n", i, arg_cstr);
+ else
+ s->Printf("argv[%zi]=NULL\n", i);
+ }
+ s->EOL();
+}
+
+bool
+Args::GetCommandString (std::string &command) const
+{
+ command.clear();
+ const size_t argc = GetArgumentCount();
+ for (size_t i=0; i<argc; ++i)
+ {
+ if (i > 0)
+ command += ' ';
+ command += m_argv[i];
+ }
+ return argc > 0;
+}
+
+bool
+Args::GetQuotedCommandString (std::string &command) const
+{
+ command.clear ();
+ const size_t argc = GetArgumentCount();
+ for (size_t i = 0; i < argc; ++i)
+ {
+ if (i > 0)
+ command.append (1, ' ');
+ char quote_char = GetArgumentQuoteCharAtIndex(i);
+ if (quote_char)
+ {
+ command.append (1, quote_char);
+ command.append (m_argv[i]);
+ command.append (1, quote_char);
+ }
+ else
+ command.append (m_argv[i]);
+ }
+ return argc > 0;
+}
+
+void
+Args::SetCommandString (const char *command, size_t len)
+{
+ // Use std::string to make sure we get a NULL terminated string we can use
+ // as "command" could point to a string within a large string....
+ std::string null_terminated_command(command, len);
+ SetCommandString(null_terminated_command.c_str());
+}
+
+void
+Args::SetCommandString (const char *command)
+{
+ m_args.clear();
+ m_argv.clear();
+ m_args_quote_char.clear();
+
+ if (command && command[0])
+ {
+ static const char *k_space_separators = " \t";
+ static const char *k_space_separators_with_slash_and_quotes = " \t \\'\"";
+ const char *arg_end = NULL;
+ const char *arg_pos;
+ for (arg_pos = command;
+ arg_pos && arg_pos[0];
+ arg_pos = arg_end)
+ {
+ // Skip any leading space separators
+ const char *arg_start = ::strspn (arg_pos, k_space_separators) + arg_pos;
+
+ // If there were only space separators to the end of the line, then
+ // we're done.
+ if (*arg_start == '\0')
+ break;
+
+ // Arguments can be split into multiple discontiguous pieces,
+ // for example:
+ // "Hello ""World"
+ // this would result in a single argument "Hello World" (without/
+ // the quotes) since the quotes would be removed and there is
+ // not space between the strings. So we need to keep track of the
+ // current start of each argument piece in "arg_piece_start"
+ const char *arg_piece_start = arg_start;
+ arg_pos = arg_piece_start;
+
+ std::string arg;
+ // Since we can have multiple quotes that form a single command
+ // in a command like: "Hello "world'!' (which will make a single
+ // argument "Hello world!") we remember the first quote character
+ // we encounter and use that for the quote character.
+ char first_quote_char = '\0';
+ char quote_char = '\0';
+ bool arg_complete = false;
+
+ do
+ {
+ arg_end = ::strcspn (arg_pos, k_space_separators_with_slash_and_quotes) + arg_pos;
+
+ switch (arg_end[0])
+ {
+ default:
+ assert (!"Unhandled case statement, we must handle this...");
+ break;
+
+ case '\0':
+ // End of C string
+ if (arg_piece_start && arg_piece_start[0])
+ arg.append (arg_piece_start);
+ arg_complete = true;
+ break;
+
+ case '\\':
+ // Backslash character
+ switch (arg_end[1])
+ {
+ case '\0':
+ arg.append (arg_piece_start);
+ ++arg_end;
+ arg_complete = true;
+ break;
+
+ default:
+ if (quote_char == '\0')
+ {
+ arg.append (arg_piece_start, arg_end - arg_piece_start);
+ if (arg_end[1] != '\0')
+ {
+ arg.append (arg_end + 1, 1);
+ arg_pos = arg_end + 2;
+ arg_piece_start = arg_pos;
+ }
+ }
+ else
+ arg_pos = arg_end + 2;
+ break;
+ }
+ break;
+
+ case '"':
+ case '\'':
+ case '`':
+ // Quote characters
+ if (quote_char)
+ {
+ // We found a quote character while inside a quoted
+ // character argument. If it matches our current quote
+ // character, this ends the effect of the quotes. If it
+ // doesn't we ignore it.
+ if (quote_char == arg_end[0])
+ {
+ arg.append (arg_piece_start, arg_end - arg_piece_start);
+ // Clear the quote character and let parsing
+ // continue (we need to watch for things like:
+ // "Hello ""World"
+ // "Hello "World
+ // "Hello "'World'
+ // All of which will result in a single argument "Hello World"
+ quote_char = '\0'; // Note that we are no longer inside quotes
+ arg_pos = arg_end + 1; // Skip the quote character
+ arg_piece_start = arg_pos; // Note we are starting from later in the string
+ }
+ else
+ {
+ // different quote, skip it and keep going
+ arg_pos = arg_end + 1;
+ }
+ }
+ else
+ {
+ // We found the start of a quote scope.
+ // Make sure there isn't a string that precedes
+ // the start of a quote scope like:
+ // Hello" World"
+ // If so, then add the "Hello" to the arg
+ if (arg_end > arg_piece_start)
+ arg.append (arg_piece_start, arg_end - arg_piece_start);
+
+ // Enter into a quote scope
+ quote_char = arg_end[0];
+
+ if (first_quote_char == '\0')
+ first_quote_char = quote_char;
+
+ arg_pos = arg_end;
+ ++arg_pos; // Skip the quote character
+ arg_piece_start = arg_pos; // Note we are starting from later in the string
+
+ // Skip till the next quote character
+ const char *end_quote = ::strchr (arg_piece_start, quote_char);
+ while (end_quote && end_quote[-1] == '\\')
+ {
+ // Don't skip the quote character if it is
+ // preceded by a '\' character
+ end_quote = ::strchr (end_quote + 1, quote_char);
+ }
+
+ if (end_quote)
+ {
+ if (end_quote > arg_piece_start)
+ arg.append (arg_piece_start, end_quote - arg_piece_start);
+
+ // If the next character is a space or the end of
+ // string, this argument is complete...
+ if (end_quote[1] == ' ' || end_quote[1] == '\t' || end_quote[1] == '\0')
+ {
+ arg_complete = true;
+ arg_end = end_quote + 1;
+ }
+ else
+ {
+ arg_pos = end_quote + 1;
+ arg_piece_start = arg_pos;
+ }
+ quote_char = '\0';
+ }
+ else
+ {
+ // Consume the rest of the string as there was no terminating quote
+ arg.append(arg_piece_start);
+ arg_end = arg_piece_start + strlen(arg_piece_start);
+ arg_complete = true;
+ }
+ }
+ break;
+
+ case ' ':
+ case '\t':
+ if (quote_char)
+ {
+ // We are currently processing a quoted character and found
+ // a space character, skip any spaces and keep trying to find
+ // the end of the argument.
+ arg_pos = ::strspn (arg_end, k_space_separators) + arg_end;
+ }
+ else
+ {
+ // We are not inside any quotes, we just found a space after an
+ // argument
+ if (arg_end > arg_piece_start)
+ arg.append (arg_piece_start, arg_end - arg_piece_start);
+ arg_complete = true;
+ }
+ break;
+ }
+ } while (!arg_complete);
+
+ m_args.push_back(arg);
+ m_args_quote_char.push_back (first_quote_char);
+ }
+ UpdateArgvFromArgs();
+ }
+}
+
+void
+Args::UpdateArgsAfterOptionParsing()
+{
+ // Now m_argv might be out of date with m_args, so we need to fix that
+ arg_cstr_collection::const_iterator argv_pos, argv_end = m_argv.end();
+ arg_sstr_collection::iterator args_pos;
+ arg_quote_char_collection::iterator quotes_pos;
+
+ for (argv_pos = m_argv.begin(), args_pos = m_args.begin(), quotes_pos = m_args_quote_char.begin();
+ argv_pos != argv_end && args_pos != m_args.end();
+ ++argv_pos)
+ {
+ const char *argv_cstr = *argv_pos;
+ if (argv_cstr == NULL)
+ break;
+
+ while (args_pos != m_args.end())
+ {
+ const char *args_cstr = args_pos->c_str();
+ if (args_cstr == argv_cstr)
+ {
+ // We found the argument that matches the C string in the
+ // vector, so we can now look for the next one
+ ++args_pos;
+ ++quotes_pos;
+ break;
+ }
+ else
+ {
+ quotes_pos = m_args_quote_char.erase (quotes_pos);
+ args_pos = m_args.erase (args_pos);
+ }
+ }
+ }
+
+ if (args_pos != m_args.end())
+ m_args.erase (args_pos, m_args.end());
+
+ if (quotes_pos != m_args_quote_char.end())
+ m_args_quote_char.erase (quotes_pos, m_args_quote_char.end());
+}
+
+void
+Args::UpdateArgvFromArgs()
+{
+ m_argv.clear();
+ arg_sstr_collection::const_iterator pos, end = m_args.end();
+ for (pos = m_args.begin(); pos != end; ++pos)
+ m_argv.push_back(pos->c_str());
+ m_argv.push_back(NULL);
+ // Make sure we have enough arg quote chars in the array
+ if (m_args_quote_char.size() < m_args.size())
+ m_args_quote_char.resize (m_argv.size());
+}
+
+size_t
+Args::GetArgumentCount() const
+{
+ if (m_argv.empty())
+ return 0;
+ return m_argv.size() - 1;
+}
+
+const char *
+Args::GetArgumentAtIndex (size_t idx) const
+{
+ if (idx < m_argv.size())
+ return m_argv[idx];
+ return NULL;
+}
+
+char
+Args::GetArgumentQuoteCharAtIndex (size_t idx) const
+{
+ if (idx < m_args_quote_char.size())
+ return m_args_quote_char[idx];
+ return '\0';
+}
+
+char **
+Args::GetArgumentVector()
+{
+ if (!m_argv.empty())
+ return (char **)&m_argv[0];
+ return NULL;
+}
+
+const char **
+Args::GetConstArgumentVector() const
+{
+ if (!m_argv.empty())
+ return (const char **)&m_argv[0];
+ return NULL;
+}
+
+void
+Args::Shift ()
+{
+ // Don't pop the last NULL terminator from the argv array
+ if (m_argv.size() > 1)
+ {
+ m_argv.erase(m_argv.begin());
+ m_args.pop_front();
+ if (!m_args_quote_char.empty())
+ m_args_quote_char.erase(m_args_quote_char.begin());
+ }
+}
+
+const char *
+Args::Unshift (const char *arg_cstr, char quote_char)
+{
+ m_args.push_front(arg_cstr);
+ m_argv.insert(m_argv.begin(), m_args.front().c_str());
+ m_args_quote_char.insert(m_args_quote_char.begin(), quote_char);
+ return GetArgumentAtIndex (0);
+}
+
+void
+Args::AppendArguments (const Args &rhs)
+{
+ const size_t rhs_argc = rhs.GetArgumentCount();
+ for (size_t i=0; i<rhs_argc; ++i)
+ AppendArgument(rhs.GetArgumentAtIndex(i));
+}
+
+void
+Args::AppendArguments (const char **argv)
+{
+ if (argv)
+ {
+ for (uint32_t i=0; argv[i]; ++i)
+ AppendArgument(argv[i]);
+ }
+}
+
+const char *
+Args::AppendArgument (const char *arg_cstr, char quote_char)
+{
+ return InsertArgumentAtIndex (GetArgumentCount(), arg_cstr, quote_char);
+}
+
+const char *
+Args::InsertArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
+{
+ // Since we are using a std::list to hold onto the copied C string and
+ // we don't have direct access to the elements, we have to iterate to
+ // find the value.
+ arg_sstr_collection::iterator pos, end = m_args.end();
+ size_t i = idx;
+ for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
+ --i;
+
+ pos = m_args.insert(pos, arg_cstr);
+
+ if (idx >= m_args_quote_char.size())
+ {
+ m_args_quote_char.resize(idx + 1);
+ m_args_quote_char[idx] = quote_char;
+ }
+ else
+ m_args_quote_char.insert(m_args_quote_char.begin() + idx, quote_char);
+
+ UpdateArgvFromArgs();
+ return GetArgumentAtIndex(idx);
+}
+
+const char *
+Args::ReplaceArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
+{
+ // Since we are using a std::list to hold onto the copied C string and
+ // we don't have direct access to the elements, we have to iterate to
+ // find the value.
+ arg_sstr_collection::iterator pos, end = m_args.end();
+ size_t i = idx;
+ for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
+ --i;
+
+ if (pos != end)
+ {
+ pos->assign(arg_cstr);
+ assert(idx < m_argv.size() - 1);
+ m_argv[idx] = pos->c_str();
+ if (idx >= m_args_quote_char.size())
+ m_args_quote_char.resize(idx + 1);
+ m_args_quote_char[idx] = quote_char;
+ return GetArgumentAtIndex(idx);
+ }
+ return NULL;
+}
+
+void
+Args::DeleteArgumentAtIndex (size_t idx)
+{
+ // Since we are using a std::list to hold onto the copied C string and
+ // we don't have direct access to the elements, we have to iterate to
+ // find the value.
+ arg_sstr_collection::iterator pos, end = m_args.end();
+ size_t i = idx;
+ for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
+ --i;
+
+ if (pos != end)
+ {
+ m_args.erase (pos);
+ assert(idx < m_argv.size() - 1);
+ m_argv.erase(m_argv.begin() + idx);
+ if (idx < m_args_quote_char.size())
+ m_args_quote_char.erase(m_args_quote_char.begin() + idx);
+ }
+}
+
+void
+Args::SetArguments (size_t argc, const char **argv)
+{
+ // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
+ // no need to clear it here.
+ m_args.clear();
+ m_args_quote_char.clear();
+
+ // First copy each string
+ for (size_t i=0; i<argc; ++i)
+ {
+ m_args.push_back (argv[i]);
+ if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
+ m_args_quote_char.push_back (argv[i][0]);
+ else
+ m_args_quote_char.push_back ('\0');
+ }
+
+ UpdateArgvFromArgs();
+}
+
+void
+Args::SetArguments (const char **argv)
+{
+ // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
+ // no need to clear it here.
+ m_args.clear();
+ m_args_quote_char.clear();
+
+ if (argv)
+ {
+ // First copy each string
+ for (size_t i=0; argv[i]; ++i)
+ {
+ m_args.push_back (argv[i]);
+ if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
+ m_args_quote_char.push_back (argv[i][0]);
+ else
+ m_args_quote_char.push_back ('\0');
+ }
+ }
+
+ UpdateArgvFromArgs();
+}
+
+
+Error
+Args::ParseOptions (Options &options)
+{
+ StreamString sstr;
+ Error error;
+ struct option *long_options = options.GetLongOptions();
+ if (long_options == NULL)
+ {
+ error.SetErrorStringWithFormat("invalid long options");
+ return error;
+ }
+
+ for (int i=0; long_options[i].name != NULL; ++i)
+ {
+ if (long_options[i].flag == NULL)
+ {
+ if (isprint8(long_options[i].val))
+ {
+ sstr << (char)long_options[i].val;
+ switch (long_options[i].has_arg)
+ {
+ default:
+ case no_argument: break;
+ case required_argument: sstr << ':'; break;
+ case optional_argument: sstr << "::"; break;
+ }
+ }
+ }
+ }
+#ifdef __GLIBC__
+ optind = 0;
+#else
+ optreset = 1;
+ optind = 1;
+#endif
+ int val;
+ while (1)
+ {
+ int long_options_index = -1;
+ val = ::getopt_long_only(GetArgumentCount(),
+ GetArgumentVector(),
+ sstr.GetData(),
+ long_options,
+ &long_options_index);
+ if (val == -1)
+ break;
+
+ // Did we get an error?
+ if (val == '?')
+ {
+ error.SetErrorStringWithFormat("unknown or ambiguous option");
+ break;
+ }
+ // The option auto-set itself
+ if (val == 0)
+ continue;
+
+ ((Options *) &options)->OptionSeen (val);
+
+ // Lookup the long option index
+ if (long_options_index == -1)
+ {
+ for (int i=0;
+ long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
+ ++i)
+ {
+ if (long_options[i].val == val)
+ {
+ long_options_index = i;
+ break;
+ }
+ }
+ }
+ // Call the callback with the option
+ if (long_options_index >= 0)
+ {
+ error = options.SetOptionValue(long_options_index,
+ long_options[long_options_index].has_arg == no_argument ? NULL : optarg);
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("invalid option with value '%i'", val);
+ }
+ if (error.Fail())
+ break;
+ }
+
+ // Update our ARGV now that get options has consumed all the options
+ m_argv.erase(m_argv.begin(), m_argv.begin() + optind);
+ UpdateArgsAfterOptionParsing ();
+ return error;
+}
+
+void
+Args::Clear ()
+{
+ m_args.clear ();
+ m_argv.clear ();
+ m_args_quote_char.clear();
+}
+
+int32_t
+Args::StringToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr)
+{
+ if (s && s[0])
+ {
+ char *end = NULL;
+ const long sval = ::strtol (s, &end, base);
+ if (*end == '\0')
+ {
+ if (success_ptr)
+ *success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN));
+ return (int32_t)sval; // All characters were used, return the result
+ }
+ }
+ if (success_ptr) *success_ptr = false;
+ return fail_value;
+}
+
+uint32_t
+Args::StringToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr)
+{
+ if (s && s[0])
+ {
+ char *end = NULL;
+ const unsigned long uval = ::strtoul (s, &end, base);
+ if (*end == '\0')
+ {
+ if (success_ptr)
+ *success_ptr = (uval <= UINT32_MAX);
+ return (uint32_t)uval; // All characters were used, return the result
+ }
+ }
+ if (success_ptr) *success_ptr = false;
+ return fail_value;
+}
+
+
+int64_t
+Args::StringToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr)
+{
+ if (s && s[0])
+ {
+ char *end = NULL;
+ int64_t uval = ::strtoll (s, &end, base);
+ if (*end == '\0')
+ {
+ if (success_ptr) *success_ptr = true;
+ return uval; // All characters were used, return the result
+ }
+ }
+ if (success_ptr) *success_ptr = false;
+ return fail_value;
+}
+
+uint64_t
+Args::StringToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr)
+{
+ if (s && s[0])
+ {
+ char *end = NULL;
+ uint64_t uval = ::strtoull (s, &end, base);
+ if (*end == '\0')
+ {
+ if (success_ptr) *success_ptr = true;
+ return uval; // All characters were used, return the result
+ }
+ }
+ if (success_ptr) *success_ptr = false;
+ return fail_value;
+}
+
+lldb::addr_t
+Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::addr_t fail_value, Error *error_ptr)
+{
+ bool error_set = false;
+ if (s && s[0])
+ {
+ char *end = NULL;
+ lldb::addr_t addr = ::strtoull (s, &end, 0);
+ if (*end == '\0')
+ {
+ if (error_ptr)
+ error_ptr->Clear();
+ return addr; // All characters were used, return the result
+ }
+ // Try base 16 with no prefix...
+ addr = ::strtoull (s, &end, 16);
+ if (*end == '\0')
+ {
+ if (error_ptr)
+ error_ptr->Clear();
+ return addr; // All characters were used, return the result
+ }
+
+ if (exe_ctx)
+ {
+ Target *target = exe_ctx->GetTargetPtr();
+ if (target)
+ {
+ lldb::ValueObjectSP valobj_sp;
+ EvaluateExpressionOptions options;
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetKeepInMemory(false);
+ options.SetRunOthers(true);
+
+ ExecutionResults expr_result = target->EvaluateExpression(s,
+ exe_ctx->GetFramePtr(),
+ valobj_sp,
+ options);
+
+ bool success = false;
+ if (expr_result == eExecutionCompleted)
+ {
+ // Get the address to watch.
+ addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
+ if (success)
+ {
+ if (error_ptr)
+ error_ptr->Clear();
+ return addr;
+ }
+ else
+ {
+ if (error_ptr)
+ {
+ error_set = true;
+ error_ptr->SetErrorStringWithFormat("address expression \"%s\" resulted in a value whose type can't be converted to an address: %s", s, valobj_sp->GetTypeName().GetCString());
+ }
+ }
+
+ }
+ else
+ {
+ // Since the compiler can't handle things like "main + 12" we should
+ // try to do this for now. The compliler doesn't like adding offsets
+ // to function pointer types.
+ static RegularExpression g_symbol_plus_offset_regex("^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
+ RegularExpression::Match regex_match(3);
+ if (g_symbol_plus_offset_regex.Execute(s, &regex_match))
+ {
+ uint64_t offset = 0;
+ bool add = true;
+ std::string name;
+ std::string str;
+ if (regex_match.GetMatchAtIndex(s, 1, name))
+ {
+ if (regex_match.GetMatchAtIndex(s, 2, str))
+ {
+ add = str[0] == '+';
+
+ if (regex_match.GetMatchAtIndex(s, 3, str))
+ {
+ offset = Args::StringToUInt64(str.c_str(), 0, 0, &success);
+
+ if (success)
+ {
+ Error error;
+ addr = StringToAddress (exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, &error);
+ if (addr != LLDB_INVALID_ADDRESS)
+ {
+ if (add)
+ return addr + offset;
+ else
+ return addr - offset;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (error_ptr)
+ {
+ error_set = true;
+ error_ptr->SetErrorStringWithFormat("address expression \"%s\" evaluation failed", s);
+ }
+ }
+ }
+ }
+ }
+ if (error_ptr)
+ {
+ if (!error_set)
+ error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", s);
+ }
+ return fail_value;
+}
+
+const char *
+Args::StripSpaces (std::string &s, bool leading, bool trailing, bool return_null_if_empty)
+{
+ static const char *k_white_space = " \t\v";
+ if (!s.empty())
+ {
+ if (leading)
+ {
+ size_t pos = s.find_first_not_of (k_white_space);
+ if (pos == std::string::npos)
+ s.clear();
+ else if (pos > 0)
+ s.erase(0, pos);
+ }
+
+ if (trailing)
+ {
+ size_t rpos = s.find_last_not_of(k_white_space);
+ if (rpos != std::string::npos && rpos + 1 < s.size())
+ s.erase(rpos + 1);
+ }
+ }
+ if (return_null_if_empty && s.empty())
+ return NULL;
+ return s.c_str();
+}
+
+bool
+Args::StringToBoolean (const char *s, bool fail_value, bool *success_ptr)
+{
+ if (s && s[0])
+ {
+ if (::strcasecmp (s, "false") == 0 ||
+ ::strcasecmp (s, "off") == 0 ||
+ ::strcasecmp (s, "no") == 0 ||
+ ::strcmp (s, "0") == 0)
+ {
+ if (success_ptr)
+ *success_ptr = true;
+ return false;
+ }
+ else
+ if (::strcasecmp (s, "true") == 0 ||
+ ::strcasecmp (s, "on") == 0 ||
+ ::strcasecmp (s, "yes") == 0 ||
+ ::strcmp (s, "1") == 0)
+ {
+ if (success_ptr) *success_ptr = true;
+ return true;
+ }
+ }
+ if (success_ptr) *success_ptr = false;
+ return fail_value;
+}
+
+const char *
+Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update)
+{
+ major = UINT32_MAX;
+ minor = UINT32_MAX;
+ update = UINT32_MAX;
+
+ if (s && s[0])
+ {
+ char *pos = NULL;
+ unsigned long uval32 = ::strtoul (s, &pos, 0);
+ if (pos == s)
+ return s;
+ major = uval32;
+ if (*pos == '\0')
+ {
+ return pos; // Decoded major and got end of string
+ }
+ else if (*pos == '.')
+ {
+ const char *minor_cstr = pos + 1;
+ uval32 = ::strtoul (minor_cstr, &pos, 0);
+ if (pos == minor_cstr)
+ return pos; // Didn't get any digits for the minor version...
+ minor = uval32;
+ if (*pos == '.')
+ {
+ const char *update_cstr = pos + 1;
+ uval32 = ::strtoul (update_cstr, &pos, 0);
+ if (pos == update_cstr)
+ return pos;
+ update = uval32;
+ }
+ return pos;
+ }
+ }
+ return 0;
+}
+
+const char *
+Args::GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg)
+{
+ safe_arg.assign (unsafe_arg);
+ size_t prev_pos = 0;
+ while (prev_pos < safe_arg.size())
+ {
+ // Escape spaces and quotes
+ size_t pos = safe_arg.find_first_of(" '\"", prev_pos);
+ if (pos != std::string::npos)
+ {
+ safe_arg.insert (pos, 1, '\\');
+ prev_pos = pos + 2;
+ }
+ else
+ break;
+ }
+ return safe_arg.c_str();
+}
+
+
+int64_t
+Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error)
+{
+ if (enum_values)
+ {
+ if (s && s[0])
+ {
+ for (int i = 0; enum_values[i].string_value != NULL ; i++)
+ {
+ if (strstr(enum_values[i].string_value, s) == enum_values[i].string_value)
+ {
+ error.Clear();
+ return enum_values[i].value;
+ }
+ }
+ }
+
+ StreamString strm;
+ strm.PutCString ("invalid enumeration value, valid values are: ");
+ for (int i = 0; enum_values[i].string_value != NULL; i++)
+ {
+ strm.Printf ("%s\"%s\"",
+ i > 0 ? ", " : "",
+ enum_values[i].string_value);
+ }
+ error.SetErrorString(strm.GetData());
+ }
+ else
+ {
+ error.SetErrorString ("invalid enumeration argument");
+ }
+ return fail_value;
+}
+
+ScriptLanguage
+Args::StringToScriptLanguage (const char *s, ScriptLanguage fail_value, bool *success_ptr)
+{
+ if (s && s[0])
+ {
+ if ((::strcasecmp (s, "python") == 0) ||
+ (::strcasecmp (s, "default") == 0 && eScriptLanguagePython == eScriptLanguageDefault))
+ {
+ if (success_ptr) *success_ptr = true;
+ return eScriptLanguagePython;
+ }
+ if (::strcasecmp (s, "none"))
+ {
+ if (success_ptr) *success_ptr = true;
+ return eScriptLanguageNone;
+ }
+ }
+ if (success_ptr) *success_ptr = false;
+ return fail_value;
+}
+
+Error
+Args::StringToFormat
+(
+ const char *s,
+ lldb::Format &format,
+ size_t *byte_size_ptr
+)
+{
+ format = eFormatInvalid;
+ Error error;
+
+ if (s && s[0])
+ {
+ if (byte_size_ptr)
+ {
+ if (isdigit (s[0]))
+ {
+ char *format_char = NULL;
+ unsigned long byte_size = ::strtoul (s, &format_char, 0);
+ if (byte_size != ULONG_MAX)
+ *byte_size_ptr = byte_size;
+ s = format_char;
+ }
+ else
+ *byte_size_ptr = 0;
+ }
+
+ const bool partial_match_ok = true;
+ if (!FormatManager::GetFormatFromCString (s, partial_match_ok, format))
+ {
+ StreamString error_strm;
+ error_strm.Printf ("Invalid format character or name '%s'. Valid values are:\n", s);
+ for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1))
+ {
+ char format_char = FormatManager::GetFormatAsFormatChar(f);
+ if (format_char)
+ error_strm.Printf ("'%c' or ", format_char);
+
+ error_strm.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f));
+ error_strm.EOL();
+ }
+
+ if (byte_size_ptr)
+ error_strm.PutCString ("An optional byte size can precede the format character.\n");
+ error.SetErrorString(error_strm.GetString().c_str());
+ }
+
+ if (error.Fail())
+ return error;
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
+ }
+ return error;
+}
+
+lldb::Encoding
+Args::StringToEncoding (const char *s, lldb::Encoding fail_value)
+{
+ if (s && s[0])
+ {
+ if (strcmp(s, "uint") == 0)
+ return eEncodingUint;
+ else if (strcmp(s, "sint") == 0)
+ return eEncodingSint;
+ else if (strcmp(s, "ieee754") == 0)
+ return eEncodingIEEE754;
+ else if (strcmp(s, "vector") == 0)
+ return eEncodingVector;
+ }
+ return fail_value;
+}
+
+uint32_t
+Args::StringToGenericRegister (const char *s)
+{
+ if (s && s[0])
+ {
+ if (strcmp(s, "pc") == 0)
+ return LLDB_REGNUM_GENERIC_PC;
+ else if (strcmp(s, "sp") == 0)
+ return LLDB_REGNUM_GENERIC_SP;
+ else if (strcmp(s, "fp") == 0)
+ return LLDB_REGNUM_GENERIC_FP;
+ else if (strcmp(s, "ra") == 0)
+ return LLDB_REGNUM_GENERIC_RA;
+ else if (strcmp(s, "flags") == 0)
+ return LLDB_REGNUM_GENERIC_FLAGS;
+ else if (strncmp(s, "arg", 3) == 0)
+ {
+ if (s[3] && s[4] == '\0')
+ {
+ switch (s[3])
+ {
+ case '1': return LLDB_REGNUM_GENERIC_ARG1;
+ case '2': return LLDB_REGNUM_GENERIC_ARG2;
+ case '3': return LLDB_REGNUM_GENERIC_ARG3;
+ case '4': return LLDB_REGNUM_GENERIC_ARG4;
+ case '5': return LLDB_REGNUM_GENERIC_ARG5;
+ case '6': return LLDB_REGNUM_GENERIC_ARG6;
+ case '7': return LLDB_REGNUM_GENERIC_ARG7;
+ case '8': return LLDB_REGNUM_GENERIC_ARG8;
+ }
+ }
+ }
+ }
+ return LLDB_INVALID_REGNUM;
+}
+
+
+void
+Args::LongestCommonPrefix (std::string &common_prefix)
+{
+ arg_sstr_collection::iterator pos, end = m_args.end();
+ pos = m_args.begin();
+ if (pos == end)
+ common_prefix.clear();
+ else
+ common_prefix = (*pos);
+
+ for (++pos; pos != end; ++pos)
+ {
+ size_t new_size = (*pos).size();
+
+ // First trim common_prefix if it is longer than the current element:
+ if (common_prefix.size() > new_size)
+ common_prefix.erase (new_size);
+
+ // Then trim it at the first disparity:
+
+ for (size_t i = 0; i < common_prefix.size(); i++)
+ {
+ if ((*pos)[i] != common_prefix[i])
+ {
+ common_prefix.erase(i);
+ break;
+ }
+ }
+
+ // If we've emptied the common prefix, we're done.
+ if (common_prefix.empty())
+ break;
+ }
+}
+
+size_t
+Args::FindArgumentIndexForOption (struct option *long_options, int long_options_index)
+{
+ char short_buffer[3];
+ char long_buffer[255];
+ ::snprintf (short_buffer, sizeof (short_buffer), "-%c", long_options[long_options_index].val);
+ ::snprintf (long_buffer, sizeof (long_buffer), "--%s", long_options[long_options_index].name);
+ size_t end = GetArgumentCount ();
+ size_t idx = 0;
+ while (idx < end)
+ {
+ if ((::strncmp (GetArgumentAtIndex (idx), short_buffer, strlen (short_buffer)) == 0)
+ || (::strncmp (GetArgumentAtIndex (idx), long_buffer, strlen (long_buffer)) == 0))
+ {
+ return idx;
+ }
+ ++idx;
+ }
+
+ return end;
+}
+
+bool
+Args::IsPositionalArgument (const char *arg)
+{
+ if (arg == NULL)
+ return false;
+
+ bool is_positional = true;
+ char *cptr = (char *) arg;
+
+ if (cptr[0] == '%')
+ {
+ ++cptr;
+ while (isdigit (cptr[0]))
+ ++cptr;
+ if (cptr[0] != '\0')
+ is_positional = false;
+ }
+ else
+ is_positional = false;
+
+ return is_positional;
+}
+
+void
+Args::ParseAliasOptions (Options &options,
+ CommandReturnObject &result,
+ OptionArgVector *option_arg_vector,
+ std::string &raw_input_string)
+{
+ StreamString sstr;
+ int i;
+ struct option *long_options = options.GetLongOptions();
+
+ if (long_options == NULL)
+ {
+ result.AppendError ("invalid long options");
+ result.SetStatus (eReturnStatusFailed);
+ return;
+ }
+
+ for (i = 0; long_options[i].name != NULL; ++i)
+ {
+ if (long_options[i].flag == NULL)
+ {
+ sstr << (char) long_options[i].val;
+ switch (long_options[i].has_arg)
+ {
+ default:
+ case no_argument:
+ break;
+ case required_argument:
+ sstr << ":";
+ break;
+ case optional_argument:
+ sstr << "::";
+ break;
+ }
+ }
+ }
+
+#ifdef __GLIBC__
+ optind = 0;
+#else
+ optreset = 1;
+ optind = 1;
+#endif
+ int val;
+ while (1)
+ {
+ int long_options_index = -1;
+ val = ::getopt_long_only (GetArgumentCount(),
+ GetArgumentVector(),
+ sstr.GetData(),
+ long_options,
+ &long_options_index);
+
+ if (val == -1)
+ break;
+
+ if (val == '?')
+ {
+ result.AppendError ("unknown or ambiguous option");
+ result.SetStatus (eReturnStatusFailed);
+ break;
+ }
+
+ if (val == 0)
+ continue;
+
+ ((Options *) &options)->OptionSeen (val);
+
+ // Look up the long option index
+ if (long_options_index == -1)
+ {
+ for (int j = 0;
+ long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
+ ++j)
+ {
+ if (long_options[j].val == val)
+ {
+ long_options_index = j;
+ break;
+ }
+ }
+ }
+
+ // See if the option takes an argument, and see if one was supplied.
+ if (long_options_index >= 0)
+ {
+ StreamString option_str;
+ option_str.Printf ("-%c", val);
+
+ switch (long_options[long_options_index].has_arg)
+ {
+ case no_argument:
+ option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
+ OptionArgValue (no_argument, "<no-argument>")));
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ break;
+ case required_argument:
+ if (optarg != NULL)
+ {
+ option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
+ OptionArgValue (required_argument,
+ std::string (optarg))));
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Option '%s' is missing argument specifier.\n",
+ option_str.GetData());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ break;
+ case optional_argument:
+ if (optarg != NULL)
+ {
+ option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
+ OptionArgValue (optional_argument,
+ std::string (optarg))));
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
+ OptionArgValue (optional_argument, "<no-argument>")));
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ break;
+ default:
+ result.AppendErrorWithFormat ("error with options table; invalid value in has_arg field for option '%c'.\n", val);
+ result.SetStatus (eReturnStatusFailed);
+ break;
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Invalid option with value '%c'.\n", val);
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ if (long_options_index >= 0)
+ {
+ // Find option in the argument list; also see if it was supposed to take an argument and if one was
+ // supplied. Remove option (and argument, if given) from the argument list. Also remove them from
+ // the raw_input_string, if one was passed in.
+ size_t idx = FindArgumentIndexForOption (long_options, long_options_index);
+ if (idx < GetArgumentCount())
+ {
+ if (raw_input_string.size() > 0)
+ {
+ const char *tmp_arg = GetArgumentAtIndex (idx);
+ size_t pos = raw_input_string.find (tmp_arg);
+ if (pos != std::string::npos)
+ raw_input_string.erase (pos, strlen (tmp_arg));
+ }
+ ReplaceArgumentAtIndex (idx, "");
+ if ((long_options[long_options_index].has_arg != no_argument)
+ && (optarg != NULL)
+ && (idx+1 < GetArgumentCount())
+ && (strcmp (optarg, GetArgumentAtIndex(idx+1)) == 0))
+ {
+ if (raw_input_string.size() > 0)
+ {
+ const char *tmp_arg = GetArgumentAtIndex (idx+1);
+ size_t pos = raw_input_string.find (tmp_arg);
+ if (pos != std::string::npos)
+ raw_input_string.erase (pos, strlen (tmp_arg));
+ }
+ ReplaceArgumentAtIndex (idx+1, "");
+ }
+ }
+ }
+
+ if (!result.Succeeded())
+ break;
+ }
+}
+
+void
+Args::ParseArgsForCompletion
+(
+ Options &options,
+ OptionElementVector &option_element_vector,
+ uint32_t cursor_index
+)
+{
+ StreamString sstr;
+ struct option *long_options = options.GetLongOptions();
+ option_element_vector.clear();
+
+ if (long_options == NULL)
+ {
+ return;
+ }
+
+ // Leading : tells getopt to return a : for a missing option argument AND
+ // to suppress error messages.
+
+ sstr << ":";
+ for (int i = 0; long_options[i].name != NULL; ++i)
+ {
+ if (long_options[i].flag == NULL)
+ {
+ sstr << (char) long_options[i].val;
+ switch (long_options[i].has_arg)
+ {
+ default:
+ case no_argument:
+ break;
+ case required_argument:
+ sstr << ":";
+ break;
+ case optional_argument:
+ sstr << "::";
+ break;
+ }
+ }
+ }
+
+#ifdef __GLIBC__
+ optind = 0;
+#else
+ optreset = 1;
+ optind = 1;
+#endif
+ opterr = 0;
+
+ int val;
+ const OptionDefinition *opt_defs = options.GetDefinitions();
+
+ // Fooey... getopt_long_only permutes the GetArgumentVector to move the options to the front.
+ // So we have to build another Arg and pass that to getopt_long_only so it doesn't
+ // change the one we have.
+
+ std::vector<const char *> dummy_vec (GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1);
+
+ bool failed_once = false;
+ uint32_t dash_dash_pos = -1;
+
+ while (1)
+ {
+ bool missing_argument = false;
+ int long_options_index = -1;
+
+ val = ::getopt_long_only (dummy_vec.size() - 1,
+ (char *const *) &dummy_vec.front(),
+ sstr.GetData(),
+ long_options,
+ &long_options_index);
+
+ if (val == -1)
+ {
+ // When we're completing a "--" which is the last option on line,
+ if (failed_once)
+ break;
+
+ failed_once = true;
+
+ // If this is a bare "--" we mark it as such so we can complete it successfully later.
+ // Handling the "--" is a little tricky, since that may mean end of options or arguments, or the
+ // user might want to complete options by long name. I make this work by checking whether the
+ // cursor is in the "--" argument, and if so I assume we're completing the long option, otherwise
+ // I let it pass to getopt_long_only which will terminate the option parsing.
+ // Note, in either case we continue parsing the line so we can figure out what other options
+ // were passed. This will be useful when we come to restricting completions based on what other
+ // options we've seen on the line.
+
+ if (optind < dummy_vec.size() - 1
+ && (strcmp (dummy_vec[optind-1], "--") == 0))
+ {
+ dash_dash_pos = optind - 1;
+ if (optind - 1 == cursor_index)
+ {
+ option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDoubleDash, optind - 1,
+ OptionArgElement::eBareDoubleDash));
+ continue;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ else if (val == '?')
+ {
+ option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
+ OptionArgElement::eUnrecognizedArg));
+ continue;
+ }
+ else if (val == 0)
+ {
+ continue;
+ }
+ else if (val == ':')
+ {
+ // This is a missing argument.
+ val = optopt;
+ missing_argument = true;
+ }
+
+ ((Options *) &options)->OptionSeen (val);
+
+ // Look up the long option index
+ if (long_options_index == -1)
+ {
+ for (int j = 0;
+ long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
+ ++j)
+ {
+ if (long_options[j].val == val)
+ {
+ long_options_index = j;
+ break;
+ }
+ }
+ }
+
+ // See if the option takes an argument, and see if one was supplied.
+ if (long_options_index >= 0)
+ {
+ int opt_defs_index = -1;
+ for (int i = 0; ; i++)
+ {
+ if (opt_defs[i].short_option == 0)
+ break;
+ else if (opt_defs[i].short_option == val)
+ {
+ opt_defs_index = i;
+ break;
+ }
+ }
+
+ switch (long_options[long_options_index].has_arg)
+ {
+ case no_argument:
+ option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 1, 0));
+ break;
+ case required_argument:
+ if (optarg != NULL)
+ {
+ int arg_index;
+ if (missing_argument)
+ arg_index = -1;
+ else
+ arg_index = optind - 1;
+
+ option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, arg_index));
+ }
+ else
+ {
+ option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 1, -1));
+ }
+ break;
+ case optional_argument:
+ if (optarg != NULL)
+ {
+ option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, optind - 1));
+ }
+ else
+ {
+ option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, optind - 1));
+ }
+ break;
+ default:
+ // The options table is messed up. Here we'll just continue
+ option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
+ OptionArgElement::eUnrecognizedArg));
+ break;
+ }
+ }
+ else
+ {
+ option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
+ OptionArgElement::eUnrecognizedArg));
+ }
+ }
+
+ // Finally we have to handle the case where the cursor index points at a single "-". We want to mark that in
+ // the option_element_vector, but only if it is not after the "--". But it turns out that getopt_long_only just ignores
+ // an isolated "-". So we have to look it up by hand here. We only care if it is AT the cursor position.
+
+ if ((dash_dash_pos == -1 || cursor_index < dash_dash_pos)
+ && strcmp (GetArgumentAtIndex(cursor_index), "-") == 0)
+ {
+ option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDash, cursor_index,
+ OptionArgElement::eBareDash));
+
+ }
+}
+
+void
+Args::EncodeEscapeSequences (const char *src, std::string &dst)
+{
+ dst.clear();
+ if (src)
+ {
+ for (const char *p = src; *p != '\0'; ++p)
+ {
+ size_t non_special_chars = ::strcspn (p, "\\");
+ if (non_special_chars > 0)
+ {
+ dst.append(p, non_special_chars);
+ p += non_special_chars;
+ if (*p == '\0')
+ break;
+ }
+
+ if (*p == '\\')
+ {
+ ++p; // skip the slash
+ switch (*p)
+ {
+ case 'a' : dst.append(1, '\a'); break;
+ case 'b' : dst.append(1, '\b'); break;
+ case 'f' : dst.append(1, '\f'); break;
+ case 'n' : dst.append(1, '\n'); break;
+ case 'r' : dst.append(1, '\r'); break;
+ case 't' : dst.append(1, '\t'); break;
+ case 'v' : dst.append(1, '\v'); break;
+ case '\\': dst.append(1, '\\'); break;
+ case '\'': dst.append(1, '\''); break;
+ case '"' : dst.append(1, '"'); break;
+ case '0' :
+ // 1 to 3 octal chars
+ {
+ // Make a string that can hold onto the initial zero char,
+ // up to 3 octal digits, and a terminating NULL.
+ char oct_str[5] = { '\0', '\0', '\0', '\0', '\0' };
+
+ int i;
+ for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i)
+ oct_str[i] = p[i];
+
+ // We don't want to consume the last octal character since
+ // the main for loop will do this for us, so we advance p by
+ // one less than i (even if i is zero)
+ p += i - 1;
+ unsigned long octal_value = ::strtoul (oct_str, NULL, 8);
+ if (octal_value <= UINT8_MAX)
+ {
+ dst.append(1, (char)octal_value);
+ }
+ }
+ break;
+
+ case 'x':
+ // hex number in the format
+ if (isxdigit(p[1]))
+ {
+ ++p; // Skip the 'x'
+
+ // Make a string that can hold onto two hex chars plus a
+ // NULL terminator
+ char hex_str[3] = { *p, '\0', '\0' };
+ if (isxdigit(p[1]))
+ {
+ ++p; // Skip the first of the two hex chars
+ hex_str[1] = *p;
+ }
+
+ unsigned long hex_value = strtoul (hex_str, NULL, 16);
+ if (hex_value <= UINT8_MAX)
+ dst.append (1, (char)hex_value);
+ }
+ else
+ {
+ dst.append(1, 'x');
+ }
+ break;
+
+ default:
+ // Just desensitize any other character by just printing what
+ // came after the '\'
+ dst.append(1, *p);
+ break;
+
+ }
+ }
+ }
+ }
+}
+
+
+void
+Args::ExpandEscapedCharacters (const char *src, std::string &dst)
+{
+ dst.clear();
+ if (src)
+ {
+ for (const char *p = src; *p != '\0'; ++p)
+ {
+ if (isprint8(*p))
+ dst.append(1, *p);
+ else
+ {
+ switch (*p)
+ {
+ case '\a': dst.append("\\a"); break;
+ case '\b': dst.append("\\b"); break;
+ case '\f': dst.append("\\f"); break;
+ case '\n': dst.append("\\n"); break;
+ case '\r': dst.append("\\r"); break;
+ case '\t': dst.append("\\t"); break;
+ case '\v': dst.append("\\v"); break;
+ case '\'': dst.append("\\'"); break;
+ case '"': dst.append("\\\""); break;
+ case '\\': dst.append("\\\\"); break;
+ default:
+ {
+ // Just encode as octal
+ dst.append("\\0");
+ char octal_str[32];
+ snprintf(octal_str, sizeof(octal_str), "%o", *p);
+ dst.append(octal_str);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandHistory.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandHistory.cpp
new file mode 100644
index 0000000..33971e3
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandHistory.cpp
@@ -0,0 +1,143 @@
+//===-- CommandHistory.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/CommandHistory.h"
+#include "lldb/Interpreter/Args.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+CommandHistory::CommandHistory () :
+ m_mutex(Mutex::eMutexTypeRecursive),
+ m_history()
+{}
+
+CommandHistory::~CommandHistory ()
+{}
+
+size_t
+CommandHistory::GetSize () const
+{
+ Mutex::Locker locker(m_mutex);
+ return m_history.size();
+}
+
+bool
+CommandHistory::IsEmpty () const
+{
+ Mutex::Locker locker(m_mutex);
+ return m_history.empty();
+}
+
+const char*
+CommandHistory::FindString (const char* input_str) const
+{
+ Mutex::Locker locker(m_mutex);
+ if (!input_str)
+ return NULL;
+ if (input_str[0] != g_repeat_char)
+ return NULL;
+ if (input_str[1] == '-')
+ {
+ bool success;
+ size_t idx = Args::StringToUInt32 (input_str+2, 0, 0, &success);
+ if (!success)
+ return NULL;
+ if (idx > m_history.size())
+ return NULL;
+ idx = m_history.size() - idx;
+ return m_history[idx].c_str();
+
+ }
+ else if (input_str[1] == g_repeat_char)
+ {
+ if (m_history.empty())
+ return NULL;
+ else
+ return m_history.back().c_str();
+ }
+ else
+ {
+ bool success;
+ uint32_t idx = Args::StringToUInt32 (input_str+1, 0, 0, &success);
+ if (!success)
+ return NULL;
+ if (idx >= m_history.size())
+ return NULL;
+ return m_history[idx].c_str();
+ }
+}
+
+const char*
+CommandHistory::GetStringAtIndex (size_t idx) const
+{
+ Mutex::Locker locker(m_mutex);
+ if (idx < m_history.size())
+ return m_history[idx].c_str();
+ return NULL;
+}
+
+const char*
+CommandHistory::operator [] (size_t idx) const
+{
+ return GetStringAtIndex(idx);
+}
+
+const char*
+CommandHistory::GetRecentmostString () const
+{
+ Mutex::Locker locker(m_mutex);
+ if (m_history.empty())
+ return NULL;
+ return m_history.back().c_str();
+}
+
+void
+CommandHistory::AppendString (const std::string& str,
+ bool reject_if_dupe)
+{
+ Mutex::Locker locker(m_mutex);
+ if (reject_if_dupe)
+ {
+ if (!m_history.empty())
+ {
+ if (str == m_history.back())
+ return;
+ }
+ }
+ m_history.push_back(std::string(str));
+}
+
+void
+CommandHistory::Clear ()
+{
+ Mutex::Locker locker(m_mutex);
+ m_history.clear();
+}
+
+void
+CommandHistory::Dump (Stream& stream,
+ size_t start_idx,
+ size_t stop_idx) const
+{
+ Mutex::Locker locker(m_mutex);
+ stop_idx = std::min(stop_idx, m_history.size() - 1);
+ for (size_t counter = start_idx;
+ counter <= stop_idx;
+ counter++)
+ {
+ const std::string hist_item = m_history[counter];
+ if (!hist_item.empty())
+ {
+ stream.Indent();
+ stream.Printf ("%4zu: %s\n", counter, hist_item.c_str());
+ }
+ }
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp
new file mode 100644
index 0000000..db2f2fa
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -0,0 +1,2882 @@
+//===-- 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 "lldb/lldb-python.h"
+
+#include <string>
+#include <vector>
+
+#include <getopt.h>
+#include <stdlib.h>
+
+#include "CommandObjectScript.h"
+#include "lldb/Interpreter/CommandObjectRegexCommand.h"
+
+#include "../Commands/CommandObjectApropos.h"
+#include "../Commands/CommandObjectArgs.h"
+#include "../Commands/CommandObjectBreakpoint.h"
+#include "../Commands/CommandObjectDisassemble.h"
+#include "../Commands/CommandObjectExpression.h"
+#include "../Commands/CommandObjectFrame.h"
+#include "../Commands/CommandObjectHelp.h"
+#include "../Commands/CommandObjectLog.h"
+#include "../Commands/CommandObjectMemory.h"
+#include "../Commands/CommandObjectPlatform.h"
+#include "../Commands/CommandObjectPlugin.h"
+#include "../Commands/CommandObjectProcess.h"
+#include "../Commands/CommandObjectQuit.h"
+#include "../Commands/CommandObjectRegister.h"
+#include "../Commands/CommandObjectSettings.h"
+#include "../Commands/CommandObjectSource.h"
+#include "../Commands/CommandObjectCommands.h"
+#include "../Commands/CommandObjectSyntax.h"
+#include "../Commands/CommandObjectTarget.h"
+#include "../Commands/CommandObjectThread.h"
+#include "../Commands/CommandObjectType.h"
+#include "../Commands/CommandObjectVersion.h"
+#include "../Commands/CommandObjectWatchpoint.h"
+
+
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Timer.h"
+
+#include "lldb/Host/Host.h"
+
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/Options.h"
+#include "lldb/Interpreter/ScriptInterpreterNone.h"
+#include "lldb/Interpreter/ScriptInterpreterPython.h"
+
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/TargetList.h"
+
+#include "lldb/Utility/CleanUp.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+static PropertyDefinition
+g_properties[] =
+{
+ { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." },
+ { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." },
+ { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will stop running a 'command source' script upon encountering an error." },
+ { NULL , OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL }
+};
+
+enum
+{
+ ePropertyExpandRegexAliases = 0,
+ ePropertyPromptOnQuit = 1,
+ ePropertyStopCmdSourceOnError = 2
+};
+
+ConstString &
+CommandInterpreter::GetStaticBroadcasterClass ()
+{
+ static ConstString class_name ("lldb.commandInterpreter");
+ return class_name;
+}
+
+CommandInterpreter::CommandInterpreter
+(
+ Debugger &debugger,
+ ScriptLanguage script_language,
+ bool synchronous_execution
+) :
+ Broadcaster (&debugger, "lldb.command-interpreter"),
+ Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))),
+ m_debugger (debugger),
+ m_synchronous_execution (synchronous_execution),
+ m_skip_lldbinit_files (false),
+ m_skip_app_init_files (false),
+ m_script_interpreter_ap (),
+ m_comment_char ('#'),
+ m_batch_command_mode (false),
+ m_truncation_warning(eNoTruncation),
+ m_command_source_depth (0)
+{
+ debugger.SetScriptLanguage (script_language);
+ SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit");
+ SetEventName (eBroadcastBitResetPrompt, "reset-prompt");
+ SetEventName (eBroadcastBitQuitCommandReceived, "quit");
+ CheckInWithManager ();
+ m_collection_sp->Initialize (g_properties);
+}
+
+bool
+CommandInterpreter::GetExpandRegexAliases () const
+{
+ const uint32_t idx = ePropertyExpandRegexAliases;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+bool
+CommandInterpreter::GetPromptOnQuit () const
+{
+ const uint32_t idx = ePropertyPromptOnQuit;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+bool
+CommandInterpreter::GetStopCmdSourceOnError () const
+{
+ const uint32_t idx = ePropertyStopCmdSourceOnError;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+void
+CommandInterpreter::Initialize ()
+{
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+ CommandReturnObject result;
+
+ LoadCommandDictionary ();
+
+ // Set up some initial aliases.
+ CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("q", cmd_obj_sp);
+ AddAlias ("exit", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("attach", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("process detach",false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("detach", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("process continue", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("c", cmd_obj_sp);
+ AddAlias ("continue", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("_regexp-break",false);
+ if (cmd_obj_sp)
+ AddAlias ("b", cmd_obj_sp);
+
+ cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false);
+ if (cmd_obj_sp)
+ AddAlias ("tbreak", cmd_obj_sp);
+
+ cmd_obj_sp = GetCommandSPExact ("thread step-inst", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("stepi", cmd_obj_sp);
+ AddAlias ("si", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("nexti", cmd_obj_sp);
+ AddAlias ("ni", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("thread step-in", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("s", cmd_obj_sp);
+ AddAlias ("step", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("thread step-over", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("n", cmd_obj_sp);
+ AddAlias ("next", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("thread step-out", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("finish", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("frame select", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("f", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("thread select", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("t", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("_regexp-list", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("l", cmd_obj_sp);
+ AddAlias ("list", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("_regexp-env", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("env", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("memory read", false);
+ if (cmd_obj_sp)
+ AddAlias ("x", cmd_obj_sp);
+
+ cmd_obj_sp = GetCommandSPExact ("_regexp-up", false);
+ if (cmd_obj_sp)
+ AddAlias ("up", cmd_obj_sp);
+
+ cmd_obj_sp = GetCommandSPExact ("_regexp-down", false);
+ if (cmd_obj_sp)
+ AddAlias ("down", cmd_obj_sp);
+
+ cmd_obj_sp = GetCommandSPExact ("_regexp-display", false);
+ if (cmd_obj_sp)
+ AddAlias ("display", cmd_obj_sp);
+
+ cmd_obj_sp = GetCommandSPExact ("disassemble", false);
+ if (cmd_obj_sp)
+ AddAlias ("dis", cmd_obj_sp);
+
+ cmd_obj_sp = GetCommandSPExact ("disassemble", false);
+ if (cmd_obj_sp)
+ AddAlias ("di", cmd_obj_sp);
+
+
+
+ cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false);
+ if (cmd_obj_sp)
+ AddAlias ("undisplay", cmd_obj_sp);
+
+ cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false);
+ if (cmd_obj_sp)
+ AddAlias ("bt", cmd_obj_sp);
+
+ cmd_obj_sp = GetCommandSPExact ("target create", false);
+ if (cmd_obj_sp)
+ AddAlias ("file", cmd_obj_sp);
+
+ cmd_obj_sp = GetCommandSPExact ("target modules", false);
+ if (cmd_obj_sp)
+ AddAlias ("image", cmd_obj_sp);
+
+
+ OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector);
+
+ cmd_obj_sp = GetCommandSPExact ("expression", false);
+ if (cmd_obj_sp)
+ {
+ ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
+ AddAlias ("p", cmd_obj_sp);
+ AddAlias ("print", cmd_obj_sp);
+ AddAlias ("call", cmd_obj_sp);
+ AddOrReplaceAliasOptions ("p", alias_arguments_vector_sp);
+ AddOrReplaceAliasOptions ("print", alias_arguments_vector_sp);
+ AddOrReplaceAliasOptions ("call", alias_arguments_vector_sp);
+
+ alias_arguments_vector_sp.reset (new OptionArgVector);
+ ProcessAliasOptionsArgs (cmd_obj_sp, "-O -- ", alias_arguments_vector_sp);
+ AddAlias ("po", cmd_obj_sp);
+ AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("process kill", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("kill", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("process launch", false);
+ if (cmd_obj_sp)
+ {
+ alias_arguments_vector_sp.reset (new OptionArgVector);
+#if defined (__arm__)
+ ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
+#else
+ ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=/bin/bash --", alias_arguments_vector_sp);
+#endif
+ AddAlias ("r", cmd_obj_sp);
+ AddAlias ("run", cmd_obj_sp);
+ AddOrReplaceAliasOptions ("r", alias_arguments_vector_sp);
+ AddOrReplaceAliasOptions ("run", alias_arguments_vector_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("target symbols add", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("add-dsym", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("breakpoint set", false);
+ if (cmd_obj_sp)
+ {
+ alias_arguments_vector_sp.reset (new OptionArgVector);
+ ProcessAliasOptionsArgs (cmd_obj_sp, "--func-regex %1", alias_arguments_vector_sp);
+ AddAlias ("rbreak", cmd_obj_sp);
+ AddOrReplaceAliasOptions("rbreak", alias_arguments_vector_sp);
+ }
+}
+
+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__);
+
+ lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
+
+ m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this));
+ m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
+ m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
+ m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this));
+ m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this));
+ m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this));
+ m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp (*this));
+ m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this));
+ m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this));
+ m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this));
+ m_command_dict["plugin"] = CommandObjectSP (new CommandObjectPlugin (*this));
+ m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this));
+ m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this));
+ m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this));
+ m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (*this, script_language));
+ m_command_dict["settings"] = CommandObjectSP (new CommandObjectMultiwordSettings (*this));
+ m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this));
+ m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this));
+ m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this));
+ m_command_dict["type"] = CommandObjectSP (new CommandObjectType (*this));
+ m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this));
+ m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this));
+
+ const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"},
+ {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
+ {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
+ {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"},
+ {"^(-.*)$", "breakpoint set %1"},
+ {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"},
+ {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"},
+ {"^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"}};
+
+ size_t num_regexes = sizeof break_regexes/sizeof(char *[2]);
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-break",
+ "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
+ "_regexp-break [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
+ 2,
+ CommandCompletions::eSymbolCompletion |
+ CommandCompletions::eSourceFileCompletion));
+
+ if (break_regex_cmd_ap.get())
+ {
+ bool success = true;
+ for (size_t i = 0; i < num_regexes; i++)
+ {
+ success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]);
+ if (!success)
+ break;
+ }
+ success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
+
+ if (success)
+ {
+ CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
+ m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-tbreak",
+ "Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
+ "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
+ 2,
+ CommandCompletions::eSymbolCompletion |
+ CommandCompletions::eSourceFileCompletion));
+
+ if (tbreak_regex_cmd_ap.get())
+ {
+ bool success = true;
+ for (size_t i = 0; i < num_regexes; i++)
+ {
+ // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer.
+ char buffer[1024];
+ int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o");
+ assert (num_printed < 1024);
+ success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer);
+ if (!success)
+ break;
+ }
+ success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
+
+ if (success)
+ {
+ CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release());
+ m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ attach_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-attach",
+ "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.",
+ "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]",
+ 2));
+ if (attach_regex_cmd_ap.get())
+ {
+ if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") &&
+ attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach'
+ attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") &&
+ attach_regex_cmd_ap->AddRegexCommand("^$", "process attach"))
+ {
+ CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release());
+ m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ down_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-down",
+ "Go down \"n\" frames in the stack (1 frame by default).",
+ "_regexp-down [n]", 2));
+ if (down_regex_cmd_ap.get())
+ {
+ if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") &&
+ down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1"))
+ {
+ CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release());
+ m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ up_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-up",
+ "Go up \"n\" frames in the stack (1 frame by default).",
+ "_regexp-up [n]", 2));
+ if (up_regex_cmd_ap.get())
+ {
+ if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") &&
+ up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1"))
+ {
+ CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release());
+ m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ display_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-display",
+ "Add an expression evaluation stop-hook.",
+ "_regexp-display expression", 2));
+ if (display_regex_cmd_ap.get())
+ {
+ if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\""))
+ {
+ CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release());
+ m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-undisplay",
+ "Remove an expression evaluation stop-hook.",
+ "_regexp-undisplay stop-hook-number", 2));
+ if (undisplay_regex_cmd_ap.get())
+ {
+ if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1"))
+ {
+ CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release());
+ m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this,
+ "gdb-remote",
+ "Connect to a remote GDB server. If no hostname is provided, localhost is assumed.",
+ "gdb-remote [<hostname>:]<portnum>", 2));
+ if (connect_gdb_remote_cmd_ap.get())
+ {
+ if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") &&
+ connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1"))
+ {
+ CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release());
+ m_command_dict[command_sp->GetCommandName ()] = command_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this,
+ "kdp-remote",
+ "Connect to a remote KDP server. udp port 41139 is the default port number.",
+ "kdp-remote <hostname>[:<portnum>]", 2));
+ if (connect_kdp_remote_cmd_ap.get())
+ {
+ if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") &&
+ connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139"))
+ {
+ CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release());
+ m_command_dict[command_sp->GetCommandName ()] = command_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ bt_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-bt",
+ "Show a backtrace. An optional argument is accepted; if that argument is a number, it specifies the number of frames to display. If that argument is 'all', full backtraces of all threads are displayed.",
+ "bt [<digit>|all]", 2));
+ if (bt_regex_cmd_ap.get())
+ {
+ // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace
+ // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and
+ // so now "bt 3" is the preferred form, in line with gdb.
+ if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") &&
+ bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") &&
+ bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") &&
+ bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace"))
+ {
+ CommandObjectSP command_sp(bt_regex_cmd_ap.release());
+ m_command_dict[command_sp->GetCommandName ()] = command_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ list_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-list",
+ "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.",
+ "_regexp-list [<line>]\n_regexp-attach [<file>:<line>]\n_regexp-attach [<file>:<line>]",
+ 2,
+ CommandCompletions::eSourceFileCompletion));
+ if (list_regex_cmd_ap.get())
+ {
+ if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") &&
+ list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") &&
+ list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") &&
+ list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") &&
+ list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") &&
+ list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") &&
+ list_regex_cmd_ap->AddRegexCommand("^$", "source list"))
+ {
+ CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release());
+ m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ env_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-env",
+ "Implements a shortcut to viewing and setting environment variables.",
+ "_regexp-env\n_regexp-env FOO=BAR", 2));
+ if (env_regex_cmd_ap.get())
+ {
+ if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") &&
+ env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1"))
+ {
+ CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release());
+ m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_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 command_sp;
+
+ std::string cmd(cmd_cstr);
+
+ if (HasCommands())
+ {
+ pos = m_command_dict.find(cmd);
+ if (pos != m_command_dict.end())
+ command_sp = pos->second;
+ }
+
+ if (include_aliases && HasAliases())
+ {
+ pos = m_alias_dict.find(cmd);
+ if (pos != m_alias_dict.end())
+ command_sp = pos->second;
+ }
+
+ if (HasUserCommands())
+ {
+ pos = m_user_dict.find(cmd);
+ if (pos != m_user_dict.end())
+ command_sp = pos->second;
+ }
+
+ if (!exact && !command_sp)
+ {
+ // We will only get into here if we didn't find any exact matches.
+
+ CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
+
+ StringList local_matches;
+ if (matches == NULL)
+ matches = &local_matches;
+
+ unsigned int num_cmd_matches = 0;
+ unsigned int num_alias_matches = 0;
+ unsigned int num_user_matches = 0;
+
+ // Look through the command dictionaries one by one, and if we get only one match from any of
+ // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches.
+
+ 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())
+ real_match_sp = pos->second;
+ }
+
+ if (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())
+ alias_match_sp = pos->second;
+ }
+
+ if (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())
+ user_match_sp = pos->second;
+ }
+
+ // If we got exactly one match, return that, otherwise return the match list.
+
+ if (num_user_matches + num_cmd_matches + num_alias_matches == 1)
+ {
+ if (num_cmd_matches)
+ return real_match_sp;
+ else if (num_alias_matches)
+ return alias_match_sp;
+ else
+ return user_match_sp;
+ }
+ }
+ else if (matches && command_sp)
+ {
+ matches->AppendString (cmd_cstr);
+ }
+
+
+ return command_sp;
+}
+
+bool
+CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
+{
+ if (name && name[0])
+ {
+ std::string name_sstr(name);
+ bool found = (m_command_dict.find (name_sstr) != m_command_dict.end());
+ if (found && !can_replace)
+ return false;
+ if (found && m_command_dict[name_sstr]->IsRemovable() == false)
+ return false;
+ m_command_dict[name_sstr] = cmd_sp;
+ return true;
+ }
+ return false;
+}
+
+bool
+CommandInterpreter::AddUserCommand (std::string name,
+ const lldb::CommandObjectSP &cmd_sp,
+ bool can_replace)
+{
+ if (!name.empty())
+ {
+
+ const char* name_cstr = name.c_str();
+
+ // do not allow replacement of internal commands
+ if (CommandExists(name_cstr))
+ {
+ if (can_replace == false)
+ return false;
+ if (m_command_dict[name]->IsRemovable() == false)
+ return false;
+ }
+
+ if (UserCommandExists(name_cstr))
+ {
+ if (can_replace == false)
+ return false;
+ if (m_user_dict[name]->IsRemovable() == false)
+ return false;
+ }
+
+ m_user_dict[name] = cmd_sp;
+ return true;
+ }
+ return false;
+}
+
+CommandObjectSP
+CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
+{
+ Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command.
+ CommandObjectSP ret_val; // Possibly empty return value.
+
+ if (cmd_cstr == NULL)
+ return ret_val;
+
+ if (cmd_words.GetArgumentCount() == 1)
+ return GetCommandSP(cmd_cstr, include_aliases, true, NULL);
+ else
+ {
+ // We have a multi-word command (seemingly), so we need to do more work.
+ // First, get the cmd_obj_sp for the first word in the command.
+ CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, NULL);
+ if (cmd_obj_sp.get() != NULL)
+ {
+ // Loop through the rest of the words in the command (everything passed in was supposed to be part of a
+ // command name), and find the appropriate sub-command SP for each command word....
+ size_t end = cmd_words.GetArgumentCount();
+ for (size_t j= 1; j < end; ++j)
+ {
+ if (cmd_obj_sp->IsMultiwordObject())
+ {
+ cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j));
+ if (cmd_obj_sp.get() == NULL)
+ // The sub-command name was invalid. Fail and return the empty 'ret_val'.
+ return ret_val;
+ }
+ else
+ // We have more words in the command name, but we don't have a multiword object. Fail and return
+ // empty 'ret_val'.
+ return ret_val;
+ }
+ // We successfully looped through all the command words and got valid command objects for them. Assign the
+ // last object retrieved to 'ret_val'.
+ ret_val = cmd_obj_sp;
+ }
+ }
+ return ret_val;
+}
+
+CommandObject *
+CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
+{
+ return GetCommandSPExact (cmd_cstr, include_aliases).get();
+}
+
+CommandObject *
+CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
+{
+ CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get();
+
+ // If we didn't find an exact match to the command string in the commands, look in
+ // the aliases.
+
+ if (command_obj)
+ return command_obj;
+
+ command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
+
+ if (command_obj)
+ return command_obj;
+
+ // If there wasn't an exact match then look for an inexact one in just the commands
+ command_obj = GetCommandSP(cmd_cstr, false, false, NULL).get();
+
+ // Finally, if there wasn't an inexact match among the commands, look for an inexact
+ // match in both the commands and aliases.
+
+ if (command_obj)
+ {
+ if (matches)
+ matches->AppendString(command_obj->GetCommandName());
+ return command_obj;
+ }
+
+ return GetCommandSP(cmd_cstr, true, false, matches).get();
+}
+
+bool
+CommandInterpreter::CommandExists (const char *cmd)
+{
+ return m_command_dict.find(cmd) != m_command_dict.end();
+}
+
+bool
+CommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp,
+ const char *options_args,
+ OptionArgVectorSP &option_arg_vector_sp)
+{
+ bool success = true;
+ OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
+
+ if (!options_args || (strlen (options_args) < 1))
+ return true;
+
+ std::string options_string (options_args);
+ Args args (options_args);
+ CommandReturnObject result;
+ // Check to see if the command being aliased can take any command options.
+ Options *options = cmd_obj_sp->GetOptions ();
+ if (options)
+ {
+ // See if any options were specified as part of the alias; if so, handle them appropriately.
+ options->NotifyOptionParsingStarting ();
+ args.Unshift ("dummy_arg");
+ args.ParseAliasOptions (*options, result, option_arg_vector, options_string);
+ args.Shift ();
+ if (result.Succeeded())
+ options->VerifyPartialOptions (result);
+ if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
+ {
+ result.AppendError ("Unable to create requested alias.\n");
+ return false;
+ }
+ }
+
+ if (!options_string.empty())
+ {
+ if (cmd_obj_sp->WantsRawCommandString ())
+ option_arg_vector->push_back (OptionArgPair ("<argument>",
+ OptionArgValue (-1,
+ options_string)));
+ else
+ {
+ const size_t argc = args.GetArgumentCount();
+ for (size_t i = 0; i < argc; ++i)
+ if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
+ option_arg_vector->push_back
+ (OptionArgPair ("<argument>",
+ OptionArgValue (-1,
+ std::string (args.GetArgumentAtIndex (i)))));
+ }
+ }
+
+ return success;
+}
+
+bool
+CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name)
+{
+ bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end());
+ if (exact_match)
+ {
+ full_name.assign(cmd);
+ return exact_match;
+ }
+ else
+ {
+ StringList matches;
+ size_t num_alias_matches;
+ num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd, matches);
+ if (num_alias_matches == 1)
+ {
+ // Make sure this isn't shadowing a command in the regular command space:
+ StringList regular_matches;
+ const bool include_aliases = false;
+ const bool exact = false;
+ CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, &regular_matches));
+ if (cmd_obj_sp || regular_matches.GetSize() > 0)
+ return false;
+ else
+ {
+ full_name.assign (matches.GetStringAtIndex(0));
+ return true;
+ }
+ }
+ else
+ return false;
+ }
+}
+
+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)
+{
+ command_obj_sp->SetIsAlias (true);
+ 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;
+}
+
+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)
+ {
+ OptionArgVector *options = option_arg_vector_sp.get();
+ for (size_t i = 0; i < options->size(); ++i)
+ {
+ OptionArgPair cur_option = (*options)[i];
+ std::string opt = cur_option.first;
+ OptionArgValue value_pair = cur_option.second;
+ std::string value = value_pair.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 ("'");
+}
+
+size_t
+CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict)
+{
+ CommandObject::CommandMap::const_iterator pos;
+ CommandObject::CommandMap::const_iterator end = dict.end();
+ size_t max_len = 0;
+
+ for (pos = dict.begin(); pos != end; ++pos)
+ {
+ size_t len = pos->first.size();
+ if (max_len < len)
+ max_len = len;
+ }
+ return max_len;
+}
+
+void
+CommandInterpreter::GetHelp (CommandReturnObject &result,
+ uint32_t cmd_types)
+{
+ CommandObject::CommandMap::const_iterator pos;
+ size_t max_len = FindLongestCommandWord (m_command_dict);
+
+ if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin )
+ {
+
+ result.AppendMessage("The following is a list of built-in, permanent debugger commands:");
+ result.AppendMessage("");
+
+ 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.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases ))
+ {
+ result.AppendMessage("The following is a list of your current command abbreviations "
+ "(see 'help command alias' for more info):");
+ result.AppendMessage("");
+ max_len = FindLongestCommandWord (m_alias_dict);
+
+ 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.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef ))
+ {
+ result.AppendMessage ("The following is a list of your current user-defined commands:");
+ result.AppendMessage("");
+ max_len = FindLongestCommandWord (m_user_dict);
+ for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
+ {
+ OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
+ max_len);
+ }
+ result.AppendMessage("");
+ }
+
+ result.AppendMessage("For more information on any particular command, try 'help <command-name>'.");
+}
+
+CommandObject *
+CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)
+{
+ // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will
+ // eventually be invoked by the given command line.
+
+ CommandObject *cmd_obj = NULL;
+ std::string white_space (" \t\v");
+ size_t start = command_string.find_first_not_of (white_space);
+ size_t end = 0;
+ bool done = false;
+ while (!done)
+ {
+ if (start != std::string::npos)
+ {
+ // Get the next word from command_string.
+ end = command_string.find_first_of (white_space, start);
+ if (end == std::string::npos)
+ end = command_string.size();
+ std::string cmd_word = command_string.substr (start, end - start);
+
+ if (cmd_obj == NULL)
+ // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid
+ // command or alias.
+ cmd_obj = GetCommandObject (cmd_word.c_str());
+ else if (cmd_obj->IsMultiwordObject ())
+ {
+ // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object.
+ CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str());
+ if (sub_cmd_obj)
+ cmd_obj = sub_cmd_obj;
+ else // cmd_word was not a valid sub-command word, so we are donee
+ done = true;
+ }
+ else
+ // We have a cmd_obj and it is not a multi-word object, so we are done.
+ done = true;
+
+ // If we didn't find a valid command object, or our command object is not a multi-word object, or
+ // we are at the end of the command_string, then we are done. Otherwise, find the start of the
+ // next word.
+
+ if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size())
+ done = true;
+ else
+ start = command_string.find_first_not_of (white_space, end);
+ }
+ else
+ // Unable to find any more words.
+ done = true;
+ }
+
+ if (end == command_string.size())
+ command_string.clear();
+ else
+ command_string = command_string.substr(end);
+
+ return cmd_obj;
+}
+
+static const char *k_white_space = " \t\v";
+static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
+static void
+StripLeadingSpaces (std::string &s)
+{
+ if (!s.empty())
+ {
+ size_t pos = s.find_first_not_of (k_white_space);
+ if (pos == std::string::npos)
+ s.clear();
+ else if (pos == 0)
+ return;
+ s.erase (0, pos);
+ }
+}
+
+static size_t
+FindArgumentTerminator (const std::string &s)
+{
+ const size_t s_len = s.size();
+ size_t offset = 0;
+ while (offset < s_len)
+ {
+ size_t pos = s.find ("--", offset);
+ if (pos == std::string::npos)
+ break;
+ if (pos > 0)
+ {
+ if (isspace(s[pos-1]))
+ {
+ // Check if the string ends "\s--" (where \s is a space character)
+ // or if we have "\s--\s".
+ if ((pos + 2 >= s_len) || isspace(s[pos+2]))
+ {
+ return pos;
+ }
+ }
+ }
+ offset = pos + 2;
+ }
+ return std::string::npos;
+}
+
+static bool
+ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char &quote_char)
+{
+ command.clear();
+ suffix.clear();
+ StripLeadingSpaces (command_string);
+
+ bool result = false;
+ quote_char = '\0';
+
+ if (!command_string.empty())
+ {
+ const char first_char = command_string[0];
+ if (first_char == '\'' || first_char == '"')
+ {
+ quote_char = first_char;
+ const size_t end_quote_pos = command_string.find (quote_char, 1);
+ if (end_quote_pos == std::string::npos)
+ {
+ command.swap (command_string);
+ command_string.erase ();
+ }
+ else
+ {
+ command.assign (command_string, 1, end_quote_pos - 1);
+ if (end_quote_pos + 1 < command_string.size())
+ command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1));
+ else
+ command_string.erase ();
+ }
+ }
+ else
+ {
+ const size_t first_space_pos = command_string.find_first_of (k_white_space);
+ if (first_space_pos == std::string::npos)
+ {
+ command.swap (command_string);
+ command_string.erase();
+ }
+ else
+ {
+ command.assign (command_string, 0, first_space_pos);
+ command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos));
+ }
+ }
+ result = true;
+ }
+
+
+ if (!command.empty())
+ {
+ // actual commands can't start with '-' or '_'
+ if (command[0] != '-' && command[0] != '_')
+ {
+ size_t pos = command.find_first_not_of(k_valid_command_chars);
+ if (pos > 0 && pos != std::string::npos)
+ {
+ suffix.assign (command.begin() + pos, command.end());
+ command.erase (pos);
+ }
+ }
+ }
+
+ return result;
+}
+
+CommandObject *
+CommandInterpreter::BuildAliasResult (const char *alias_name,
+ std::string &raw_input_string,
+ std::string &alias_result,
+ CommandReturnObject &result)
+{
+ CommandObject *alias_cmd_obj = NULL;
+ Args cmd_args (raw_input_string.c_str());
+ alias_cmd_obj = GetCommandObject (alias_name);
+ StreamString result_str;
+
+ if (alias_cmd_obj)
+ {
+ std::string alias_name_str = alias_name;
+ if ((cmd_args.GetArgumentCount() == 0)
+ || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0))
+ cmd_args.Unshift (alias_name);
+
+ result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
+ OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
+
+ if (option_arg_vector_sp.get())
+ {
+ OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
+
+ for (size_t i = 0; i < option_arg_vector->size(); ++i)
+ {
+ OptionArgPair option_pair = (*option_arg_vector)[i];
+ OptionArgValue value_pair = option_pair.second;
+ int value_type = value_pair.first;
+ std::string option = option_pair.first;
+ std::string value = value_pair.second;
+ if (option.compare ("<argument>") == 0)
+ result_str.Printf (" %s", value.c_str());
+ else
+ {
+ result_str.Printf (" %s", option.c_str());
+ if (value_type != optional_argument)
+ result_str.Printf (" ");
+ if (value.compare ("<no_argument>") != 0)
+ {
+ int index = GetOptionArgumentPosition (value.c_str());
+ if (index == 0)
+ result_str.Printf ("%s", 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 alias_cmd_obj;
+ }
+ else
+ {
+ size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
+ if (strpos != std::string::npos)
+ raw_input_string = raw_input_string.erase (strpos,
+ strlen (cmd_args.GetArgumentAtIndex (index)));
+ result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index));
+ }
+ }
+ }
+ }
+ }
+
+ alias_result = result_str.GetData();
+ }
+ return alias_cmd_obj;
+}
+
+Error
+CommandInterpreter::PreprocessCommand (std::string &command)
+{
+ // The command preprocessor needs to do things to the command
+ // line before any parsing of arguments or anything else is done.
+ // The only current stuff that gets proprocessed is anyting enclosed
+ // in backtick ('`') characters is evaluated as an expression and
+ // the result of the expression must be a scalar that can be substituted
+ // into the command. An example would be:
+ // (lldb) memory read `$rsp + 20`
+ Error error; // Error for any expressions that might not evaluate
+ size_t start_backtick;
+ size_t pos = 0;
+ while ((start_backtick = command.find ('`', pos)) != std::string::npos)
+ {
+ if (start_backtick > 0 && command[start_backtick-1] == '\\')
+ {
+ // The backtick was preceeded by a '\' character, remove the slash
+ // and don't treat the backtick as the start of an expression
+ command.erase(start_backtick-1, 1);
+ // No need to add one to start_backtick since we just deleted a char
+ pos = start_backtick;
+ }
+ else
+ {
+ const size_t expr_content_start = start_backtick + 1;
+ const size_t end_backtick = command.find ('`', expr_content_start);
+ if (end_backtick == std::string::npos)
+ return error;
+ else if (end_backtick == expr_content_start)
+ {
+ // Empty expression (two backticks in a row)
+ command.erase (start_backtick, 2);
+ }
+ else
+ {
+ std::string expr_str (command, expr_content_start, end_backtick - expr_content_start);
+
+ ExecutionContext exe_ctx(GetExecutionContext());
+ Target *target = exe_ctx.GetTargetPtr();
+ // Get a dummy target to allow for calculator mode while processing backticks.
+ // This also helps break the infinite loop caused when target is null.
+ if (!target)
+ target = Host::GetDummyTarget(GetDebugger()).get();
+ if (target)
+ {
+ ValueObjectSP expr_result_valobj_sp;
+
+ EvaluateExpressionOptions options;
+ options.SetCoerceToId(false)
+ .SetUnwindOnError(true)
+ .SetIgnoreBreakpoints(true)
+ .SetKeepInMemory(false)
+ .SetRunOthers(true)
+ .SetTimeoutUsec(0);
+
+ ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
+ exe_ctx.GetFramePtr(),
+ expr_result_valobj_sp,
+ options);
+
+ if (expr_result == eExecutionCompleted)
+ {
+ Scalar scalar;
+ if (expr_result_valobj_sp->ResolveValue (scalar))
+ {
+ command.erase (start_backtick, end_backtick - start_backtick + 1);
+ StreamString value_strm;
+ const bool show_type = false;
+ scalar.GetValue (&value_strm, show_type);
+ size_t value_string_size = value_strm.GetSize();
+ if (value_string_size)
+ {
+ command.insert (start_backtick, value_strm.GetData(), value_string_size);
+ pos = start_backtick + value_string_size;
+ continue;
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
+ }
+ }
+ else
+ {
+ if (expr_result_valobj_sp)
+ error = expr_result_valobj_sp->GetError();
+ if (error.Success())
+ {
+
+ switch (expr_result)
+ {
+ case eExecutionSetupError:
+ error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str());
+ break;
+ case eExecutionCompleted:
+ break;
+ case eExecutionDiscarded:
+ error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str());
+ break;
+ case eExecutionInterrupted:
+ error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
+ break;
+ case eExecutionHitBreakpoint:
+ error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str());
+ break;
+ case eExecutionTimedOut:
+ error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (error.Fail())
+ break;
+ }
+ }
+ return error;
+}
+
+
+bool
+CommandInterpreter::HandleCommand (const char *command_line,
+ LazyBool lazy_add_to_history,
+ CommandReturnObject &result,
+ ExecutionContext *override_context,
+ bool repeat_on_empty_command,
+ bool no_context_switching)
+
+{
+
+ bool done = false;
+ CommandObject *cmd_obj = NULL;
+ bool wants_raw_input = false;
+ std::string command_string (command_line);
+ std::string original_command_string (command_line);
+
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
+ Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
+
+ // Make a scoped cleanup object that will clear the crash description string
+ // on exit of this function.
+ lldb_utility::CleanUp <const char *> crash_description_cleanup(NULL, Host::SetCrashDescription);
+
+ if (log)
+ log->Printf ("Processing command: %s", command_line);
+
+ Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line);
+
+ if (!no_context_switching)
+ UpdateExecutionContext (override_context);
+
+ bool add_to_history;
+ if (lazy_add_to_history == eLazyBoolCalculate)
+ add_to_history = (m_command_source_depth == 0);
+ else
+ add_to_history = (lazy_add_to_history == eLazyBoolYes);
+
+ bool empty_command = false;
+ bool comment_command = false;
+ if (command_string.empty())
+ empty_command = true;
+ else
+ {
+ const char *k_space_characters = "\t\n\v\f\r ";
+
+ size_t non_space = command_string.find_first_not_of (k_space_characters);
+ // Check for empty line or comment line (lines whose first
+ // non-space character is the comment character for this interpreter)
+ if (non_space == std::string::npos)
+ empty_command = true;
+ else if (command_string[non_space] == m_comment_char)
+ comment_command = true;
+ else if (command_string[non_space] == CommandHistory::g_repeat_char)
+ {
+ const char *history_string = m_command_history.FindString(command_string.c_str() + non_space);
+ if (history_string == NULL)
+ {
+ result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ add_to_history = false;
+ command_string = history_string;
+ original_command_string = history_string;
+ }
+ }
+
+ if (empty_command)
+ {
+ if (repeat_on_empty_command)
+ {
+ if (m_command_history.IsEmpty())
+ {
+ result.AppendError ("empty command");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ command_line = m_repeat_command.c_str();
+ command_string = command_line;
+ original_command_string = command_line;
+ if (m_repeat_command.empty())
+ {
+ result.AppendErrorWithFormat("No auto repeat.\n");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ add_to_history = false;
+ }
+ else
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+ }
+ else if (comment_command)
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+
+
+ Error error (PreprocessCommand (command_string));
+
+ if (error.Fail())
+ {
+ result.AppendError (error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ // Phase 1.
+
+ // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object
+ // is for the specified command, and whether or not it wants raw input. This gets complicated by the fact that
+ // the user could have specified an alias, and in translating the alias there may also be command options and/or
+ // even data (including raw text strings) that need to be found and inserted into the command line as part of
+ // the translation. So this first step is plain look-up & replacement, resulting in three things: 1). the command
+ // object whose Execute method will actually be called; 2). a revised command string, with all substitutions &
+ // replacements taken care of; 3). whether or not the Execute function wants raw input or not.
+
+ StreamString revised_command_line;
+ size_t actual_cmd_name_len = 0;
+ std::string next_word;
+ StringList matches;
+ while (!done)
+ {
+ char quote_char = '\0';
+ std::string suffix;
+ ExtractCommand (command_string, next_word, suffix, quote_char);
+ if (cmd_obj == NULL)
+ {
+ std::string full_name;
+ if (GetAliasFullName(next_word.c_str(), full_name))
+ {
+ std::string alias_result;
+ cmd_obj = BuildAliasResult (full_name.c_str(), command_string, alias_result, result);
+ revised_command_line.Printf ("%s", alias_result.c_str());
+ if (cmd_obj)
+ {
+ wants_raw_input = cmd_obj->WantsRawCommandString ();
+ actual_cmd_name_len = strlen (cmd_obj->GetCommandName());
+ }
+ }
+ else
+ {
+ cmd_obj = GetCommandObject (next_word.c_str(), &matches);
+ if (cmd_obj)
+ {
+ actual_cmd_name_len += next_word.length();
+ revised_command_line.Printf ("%s", next_word.c_str());
+ wants_raw_input = cmd_obj->WantsRawCommandString ();
+ }
+ else
+ {
+ revised_command_line.Printf ("%s", next_word.c_str());
+ }
+ }
+ }
+ else
+ {
+ if (cmd_obj->IsMultiwordObject ())
+ {
+ CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (next_word.c_str());
+ if (sub_cmd_obj)
+ {
+ actual_cmd_name_len += next_word.length() + 1;
+ revised_command_line.Printf (" %s", next_word.c_str());
+ cmd_obj = sub_cmd_obj;
+ wants_raw_input = cmd_obj->WantsRawCommandString ();
+ }
+ else
+ {
+ if (quote_char)
+ revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
+ else
+ revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
+ done = true;
+ }
+ }
+ else
+ {
+ if (quote_char)
+ revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
+ else
+ revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
+ done = true;
+ }
+ }
+
+ if (cmd_obj == NULL)
+ {
+ const size_t num_matches = matches.GetSize();
+ if (matches.GetSize() > 1) {
+ StreamString error_msg;
+ error_msg.Printf ("Ambiguous command '%s'. Possible matches:\n", next_word.c_str());
+
+ for (uint32_t i = 0; i < num_matches; ++i) {
+ error_msg.Printf ("\t%s\n", matches.GetStringAtIndex(i));
+ }
+ result.AppendRawError (error_msg.GetString().c_str());
+ } else {
+ // We didn't have only one match, otherwise we wouldn't get here.
+ assert(num_matches == 0);
+ result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str());
+ }
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (cmd_obj->IsMultiwordObject ())
+ {
+ if (!suffix.empty())
+ {
+
+ result.AppendErrorWithFormat ("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n",
+ cmd_obj->GetCommandName(),
+ next_word.empty() ? "" : next_word.c_str(),
+ next_word.empty() ? " -- " : " ",
+ suffix.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ // If we found a normal command, we are done
+ done = true;
+ if (!suffix.empty())
+ {
+ switch (suffix[0])
+ {
+ case '/':
+ // GDB format suffixes
+ {
+ Options *command_options = cmd_obj->GetOptions();
+ if (command_options && command_options->SupportsLongOption("gdb-format"))
+ {
+ std::string gdb_format_option ("--gdb-format=");
+ gdb_format_option += (suffix.c_str() + 1);
+
+ bool inserted = false;
+ std::string &cmd = revised_command_line.GetString();
+ size_t arg_terminator_idx = FindArgumentTerminator (cmd);
+ if (arg_terminator_idx != std::string::npos)
+ {
+ // Insert the gdb format option before the "--" that terminates options
+ gdb_format_option.append(1,' ');
+ cmd.insert(arg_terminator_idx, gdb_format_option);
+ inserted = true;
+ }
+
+ if (!inserted)
+ revised_command_line.Printf (" %s", gdb_format_option.c_str());
+
+ if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos)
+ revised_command_line.PutCString (" --");
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("the '%s' command doesn't support the --gdb-format option\n",
+ cmd_obj->GetCommandName());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ break;
+
+ default:
+ result.AppendErrorWithFormat ("unknown command shorthand suffix: '%s'\n",
+ suffix.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+
+ }
+ }
+ }
+ if (command_string.length() == 0)
+ done = true;
+
+ }
+
+ if (!command_string.empty())
+ revised_command_line.Printf (" %s", command_string.c_str());
+
+ // End of Phase 1.
+ // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command
+ // specified was valid; revised_command_line contains the complete command line (including command name(s)),
+ // fully translated with all substitutions & translations taken care of (still in raw text format); and
+ // wants_raw_input specifies whether the Execute method expects raw input or not.
+
+
+ if (log)
+ {
+ log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
+ log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData());
+ log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False");
+ }
+
+ // Phase 2.
+ // Take care of things like setting up the history command & calling the appropriate Execute method on the
+ // CommandObject, with the appropriate arguments.
+
+ if (cmd_obj != NULL)
+ {
+ if (add_to_history)
+ {
+ Args command_args (revised_command_line.GetData());
+ const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
+ if (repeat_command != NULL)
+ m_repeat_command.assign(repeat_command);
+ else
+ m_repeat_command.assign(original_command_string.c_str());
+
+ m_command_history.AppendString (original_command_string);
+ }
+
+ command_string = revised_command_line.GetData();
+ std::string command_name (cmd_obj->GetCommandName());
+ std::string remainder;
+ if (actual_cmd_name_len < command_string.length())
+ remainder = command_string.substr (actual_cmd_name_len); // Note: 'actual_cmd_name_len' may be considerably shorter
+ // than cmd_obj->GetCommandName(), because name completion
+ // allows users to enter short versions of the names,
+ // e.g. 'br s' for 'breakpoint set'.
+
+ // Remove any initial spaces
+ std::string white_space (" \t\v");
+ size_t pos = remainder.find_first_not_of (white_space);
+ if (pos != 0 && pos != std::string::npos)
+ remainder.erase(0, pos);
+
+ if (log)
+ log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str());
+
+ cmd_obj->Execute (remainder.c_str(), result);
+ }
+ else
+ {
+ // We didn't find the first command object, so complete the first argument.
+ Args command_args (revised_command_line.GetData());
+ StringList matches;
+ int num_matches;
+ int cursor_index = 0;
+ int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
+ bool word_complete;
+ num_matches = HandleCompletionMatches (command_args,
+ cursor_index,
+ cursor_char_position,
+ 0,
+ -1,
+ word_complete,
+ matches);
+
+ if (num_matches > 0)
+ {
+ std::string error_msg;
+ error_msg.assign ("ambiguous command '");
+ error_msg.append(command_args.GetArgumentAtIndex(0));
+ 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());
+ }
+ else
+ result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
+
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ if (log)
+ log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed"));
+
+ return result.Succeeded();
+}
+
+int
+CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
+ int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+{
+ int num_command_matches = 0;
+ bool look_for_subcommand = false;
+
+ // For any of the command completions a unique match will be a complete word.
+ word_complete = true;
+
+ if (cursor_index == -1)
+ {
+ // We got nothing on the command line, so return the list of commands
+ bool include_aliases = true;
+ 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), &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));
+ 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,
+ word_complete,
+ 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);
+
+ // Don't complete comments, and if the line we are completing is just the history repeat character,
+ // substitute the appropriate history line.
+ const char *first_arg = parsed_line.GetArgumentAtIndex(0);
+ if (first_arg)
+ {
+ if (first_arg[0] == m_comment_char)
+ return 0;
+ else if (first_arg[0] == CommandHistory::g_repeat_char)
+ {
+ const char *history_string = m_command_history.FindString (first_arg);
+ if (history_string != NULL)
+ {
+ matches.Clear();
+ matches.InsertStringAtIndex(0, history_string);
+ return -2;
+ }
+ else
+ return 0;
+
+ }
+ }
+
+
+ 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));
+
+ if (cursor > current_line && cursor[-1] == ' ')
+ {
+ // We are just after a space. If we are in an argument, then we will continue
+ // parsing, but if we are between arguments, then we have to complete whatever the next
+ // element would be.
+ // We can distinguish the two cases because if we are in an argument (e.g. because the space is
+ // protected by a quote) then the space will also be in the parsed argument...
+
+ const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index);
+ if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ')
+ {
+ parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '"');
+ cursor_index++;
+ cursor_char_position = 0;
+ }
+ }
+
+ int num_command_matches;
+
+ matches.Clear();
+
+ // Only max_return_elements == -1 is supported at present:
+ assert (max_return_elements == -1);
+ bool word_complete;
+ num_command_matches = HandleCompletionMatches (parsed_line,
+ cursor_index,
+ cursor_char_position,
+ match_start_point,
+ max_return_elements,
+ word_complete,
+ 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);
+ const size_t partial_name_len = command_partial_str.size();
+
+ // If we matched a unique single command, add a space...
+ // Only do this if the completer told us this was a complete word, however...
+ if (num_command_matches == 1 && word_complete)
+ {
+ 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;
+}
+
+
+CommandInterpreter::~CommandInterpreter ()
+{
+}
+
+const char *
+CommandInterpreter::GetPrompt ()
+{
+ return m_debugger.GetPrompt();
+}
+
+void
+CommandInterpreter::SetPrompt (const char *new_prompt)
+{
+ m_debugger.SetPrompt (new_prompt);
+}
+
+size_t
+CommandInterpreter::GetConfirmationInputReaderCallback
+(
+ void *baton,
+ InputReader &reader,
+ lldb::InputReaderAction action,
+ const char *bytes,
+ size_t bytes_len
+)
+{
+ File &out_file = reader.GetDebugger().GetOutputFile();
+ bool *response_ptr = (bool *) baton;
+
+ switch (action)
+ {
+ case eInputReaderActivate:
+ if (out_file.IsValid())
+ {
+ if (reader.GetPrompt())
+ {
+ out_file.Printf ("%s", reader.GetPrompt());
+ out_file.Flush ();
+ }
+ }
+ break;
+
+ case eInputReaderDeactivate:
+ break;
+
+ case eInputReaderReactivate:
+ if (out_file.IsValid() && reader.GetPrompt())
+ {
+ out_file.Printf ("%s", reader.GetPrompt());
+ out_file.Flush ();
+ }
+ break;
+
+ case eInputReaderAsynchronousOutputWritten:
+ break;
+
+ case eInputReaderGotToken:
+ if (bytes_len == 0)
+ {
+ reader.SetIsDone(true);
+ }
+ else if (bytes[0] == 'y' || bytes[0] == 'Y')
+ {
+ *response_ptr = true;
+ reader.SetIsDone(true);
+ }
+ else if (bytes[0] == 'n' || bytes[0] == 'N')
+ {
+ *response_ptr = false;
+ reader.SetIsDone(true);
+ }
+ else
+ {
+ if (out_file.IsValid() && !reader.IsDone() && reader.GetPrompt())
+ {
+ out_file.Printf ("Please answer \"y\" or \"n\".\n%s", reader.GetPrompt());
+ out_file.Flush ();
+ }
+ }
+ break;
+
+ case eInputReaderInterrupt:
+ case eInputReaderEndOfFile:
+ *response_ptr = false; // Assume ^C or ^D means cancel the proposed action
+ reader.SetIsDone (true);
+ break;
+
+ case eInputReaderDone:
+ break;
+ }
+
+ return bytes_len;
+
+}
+
+bool
+CommandInterpreter::Confirm (const char *message, bool default_answer)
+{
+ // Check AutoConfirm first:
+ if (m_debugger.GetAutoConfirm())
+ return default_answer;
+
+ InputReaderSP reader_sp (new InputReader(GetDebugger()));
+ bool response = default_answer;
+ if (reader_sp)
+ {
+ std::string prompt(message);
+ prompt.append(": [");
+ if (default_answer)
+ prompt.append ("Y/n] ");
+ else
+ prompt.append ("y/N] ");
+
+ Error err (reader_sp->Initialize (CommandInterpreter::GetConfirmationInputReaderCallback,
+ &response, // baton
+ eInputReaderGranularityLine, // token size, to pass to callback function
+ NULL, // end token
+ prompt.c_str(), // prompt
+ true)); // echo input
+ if (err.Success())
+ {
+ GetDebugger().PushInputReader (reader_sp);
+ }
+ reader_sp->WaitOnReaderIsDone();
+ }
+ return response;
+}
+
+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());
+}
+
+void
+CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
+ const char *alias_name,
+ Args &cmd_args,
+ std::string &raw_input_string,
+ CommandReturnObject &result)
+{
+ OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
+
+ bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
+
+ // 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();
+
+ if (option_arg_vector_sp.get())
+ {
+ if (wants_raw_input)
+ {
+ // We have a command that both has command options and takes raw input. Make *sure* it has a
+ // " -- " in the right place in the raw_input_string.
+ size_t pos = raw_input_string.find(" -- ");
+ if (pos == std::string::npos)
+ {
+ // None found; assume it goes at the beginning of the raw input string
+ raw_input_string.insert (0, " -- ");
+ }
+ }
+
+ OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
+ const size_t old_size = cmd_args.GetArgumentCount();
+ std::vector<bool> used (old_size + 1, false);
+
+ used[0] = true;
+
+ for (size_t i = 0; i < option_arg_vector->size(); ++i)
+ {
+ OptionArgPair option_pair = (*option_arg_vector)[i];
+ OptionArgValue value_pair = option_pair.second;
+ int value_type = value_pair.first;
+ std::string option = option_pair.first;
+ std::string value = value_pair.second;
+ if (option.compare ("<argument>") == 0)
+ {
+ if (!wants_raw_input
+ || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice
+ new_args.AppendArgument (value.c_str());
+ }
+ else
+ {
+ if (value_type != optional_argument)
+ 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
+ if (value_type != optional_argument)
+ new_args.AppendArgument (value.c_str());
+ else
+ {
+ char buffer[255];
+ ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str());
+ new_args.AppendArgument (buffer);
+ }
+
+ }
+ 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
+ {
+ // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
+ size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
+ if (strpos != std::string::npos)
+ {
+ raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index)));
+ }
+
+ if (value_type != optional_argument)
+ new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
+ else
+ {
+ char buffer[255];
+ ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(),
+ cmd_args.GetArgumentAtIndex (index));
+ new_args.AppendArgument (buffer);
+ }
+ used[index] = true;
+ }
+ }
+ }
+ }
+
+ for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j)
+ {
+ if (!used[j] && !wants_raw_input)
+ 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, unless it is a command that
+ // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw
+ // input string.
+ if (wants_raw_input)
+ {
+ cmd_args.Clear();
+ cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
+ }
+ 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)
+{
+ FileSpec init_file;
+ if (in_cwd)
+ {
+ // In the current working directory we don't load any program specific
+ // .lldbinit files, we only look for a "./.lldbinit" file.
+ if (m_skip_lldbinit_files)
+ return;
+
+ init_file.SetFile ("./.lldbinit", true);
+ }
+ else
+ {
+ // If we aren't looking in the current working directory we are looking
+ // in the home directory. We will first see if there is an application
+ // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a
+ // "-" and the name of the program. If this file doesn't exist, we fall
+ // back to just the "~/.lldbinit" file. We also obey any requests to not
+ // load the init files.
+ const char *init_file_path = "~/.lldbinit";
+
+ if (m_skip_app_init_files == false)
+ {
+ FileSpec program_file_spec (Host::GetProgramFileSpec());
+ const char *program_name = program_file_spec.GetFilename().AsCString();
+
+ if (program_name)
+ {
+ char program_init_file_name[PATH_MAX];
+ ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path, program_name);
+ init_file.SetFile (program_init_file_name, true);
+ if (!init_file.Exists())
+ init_file.Clear();
+ }
+ }
+
+ if (!init_file && !m_skip_lldbinit_files)
+ init_file.SetFile (init_file_path, true);
+ }
+
+ // 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())
+ {
+ ExecutionContext *exe_ctx = NULL; // We don't have any context yet.
+ bool stop_on_continue = true;
+ bool stop_on_error = false;
+ bool echo_commands = false;
+ bool print_results = false;
+
+ HandleCommandsFromFile (init_file, exe_ctx, stop_on_continue, stop_on_error, echo_commands, print_results, eLazyBoolNo, result);
+ }
+ else
+ {
+ // nothing to be done if the file doesn't exist
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ }
+}
+
+PlatformSP
+CommandInterpreter::GetPlatform (bool prefer_target_platform)
+{
+ PlatformSP platform_sp;
+ if (prefer_target_platform)
+ {
+ ExecutionContext exe_ctx(GetExecutionContext());
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ platform_sp = target->GetPlatform();
+ }
+
+ if (!platform_sp)
+ platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
+ return platform_sp;
+}
+
+void
+CommandInterpreter::HandleCommands (const StringList &commands,
+ ExecutionContext *override_context,
+ bool stop_on_continue,
+ bool stop_on_error,
+ bool echo_commands,
+ bool print_results,
+ LazyBool add_to_history,
+ CommandReturnObject &result)
+{
+ size_t num_lines = commands.GetSize();
+
+ // If we are going to continue past a "continue" then we need to run the commands synchronously.
+ // Make sure you reset this value anywhere you return from the function.
+
+ bool old_async_execution = m_debugger.GetAsyncExecution();
+
+ // If we've been given an execution context, set it at the start, but don't keep resetting it or we will
+ // cause series of commands that change the context, then do an operation that relies on that context to fail.
+
+ if (override_context != NULL)
+ UpdateExecutionContext (override_context);
+
+ if (!stop_on_continue)
+ {
+ m_debugger.SetAsyncExecution (false);
+ }
+
+ for (size_t idx = 0; idx < num_lines; idx++)
+ {
+ const char *cmd = commands.GetStringAtIndex(idx);
+ if (cmd[0] == '\0')
+ continue;
+
+ if (echo_commands)
+ {
+ result.AppendMessageWithFormat ("%s %s\n",
+ GetPrompt(),
+ cmd);
+ }
+
+ CommandReturnObject tmp_result;
+ // If override_context is not NULL, pass no_context_switching = true for
+ // HandleCommand() since we updated our context already.
+
+ // We might call into a regex or alias command, in which case the add_to_history will get lost. This
+ // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here.
+ if (!add_to_history)
+ m_command_source_depth++;
+ bool success = HandleCommand(cmd, add_to_history, tmp_result,
+ NULL, /* override_context */
+ true, /* repeat_on_empty_command */
+ override_context != NULL /* no_context_switching */);
+ if (!add_to_history)
+ m_command_source_depth--;
+
+ if (print_results)
+ {
+ if (tmp_result.Succeeded())
+ result.AppendMessageWithFormat("%s", tmp_result.GetOutputData());
+ }
+
+ if (!success || !tmp_result.Succeeded())
+ {
+ const char *error_msg = tmp_result.GetErrorData();
+ if (error_msg == NULL || error_msg[0] == '\0')
+ error_msg = "<unknown error>.\n";
+ if (stop_on_error)
+ {
+ result.AppendErrorWithFormat("Aborting reading of commands after command #%zu: '%s' failed with %s",
+ idx, cmd, error_msg);
+ result.SetStatus (eReturnStatusFailed);
+ m_debugger.SetAsyncExecution (old_async_execution);
+ return;
+ }
+ else if (print_results)
+ {
+ result.AppendMessageWithFormat ("Command #%zu '%s' failed with %s",
+ idx + 1,
+ cmd,
+ error_msg);
+ }
+ }
+
+ if (result.GetImmediateOutputStream())
+ result.GetImmediateOutputStream()->Flush();
+
+ if (result.GetImmediateErrorStream())
+ result.GetImmediateErrorStream()->Flush();
+
+ // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
+ // could be running (for instance in Breakpoint Commands.
+ // So we check the return value to see if it is has running in it.
+ if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
+ || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult))
+ {
+ if (stop_on_continue)
+ {
+ // If we caused the target to proceed, and we're going to stop in that case, set the
+ // status in our real result before returning. This is an error if the continue was not the
+ // last command in the set of commands to be run.
+ if (idx != num_lines - 1)
+ result.AppendErrorWithFormat("Aborting reading of commands after command #%zu: '%s' continued the target.\n",
+ idx + 1, cmd);
+ else
+ result.AppendMessageWithFormat ("Command #%zu '%s' continued the target.\n", idx + 1, cmd);
+
+ result.SetStatus(tmp_result.GetStatus());
+ m_debugger.SetAsyncExecution (old_async_execution);
+
+ return;
+ }
+ }
+
+ }
+
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ m_debugger.SetAsyncExecution (old_async_execution);
+
+ return;
+}
+
+void
+CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
+ ExecutionContext *context,
+ bool stop_on_continue,
+ bool stop_on_error,
+ bool echo_command,
+ bool print_result,
+ LazyBool add_to_history,
+ CommandReturnObject &result)
+{
+ if (cmd_file.Exists())
+ {
+ bool success;
+ StringList commands;
+ success = commands.ReadFileLines(cmd_file);
+ if (!success)
+ {
+ result.AppendErrorWithFormat ("Error reading commands from file: %s.\n", cmd_file.GetFilename().AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ return;
+ }
+ m_command_source_depth++;
+ HandleCommands (commands, context, stop_on_continue, stop_on_error, echo_command, print_result, add_to_history, result);
+ m_command_source_depth--;
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n",
+ cmd_file.GetFilename().AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ return;
+ }
+}
+
+ScriptInterpreter *
+CommandInterpreter::GetScriptInterpreter (bool can_create)
+{
+ if (m_script_interpreter_ap.get() != NULL)
+ return m_script_interpreter_ap.get();
+
+ if (!can_create)
+ return NULL;
+
+ // <rdar://problem/11751427>
+ // we need to protect the initialization of the script interpreter
+ // otherwise we could end up with two threads both trying to create
+ // their instance of it, and for some languages (e.g. Python)
+ // this is a bulletproof recipe for disaster!
+ // this needs to be a function-level static because multiple Debugger instances living in the same process
+ // still need to be isolated and not try to initialize Python concurrently
+ static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive);
+ Mutex::Locker interpreter_lock(g_interpreter_mutex);
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf("Initializing the ScriptInterpreter now\n");
+
+ lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
+ switch (script_lang)
+ {
+ case eScriptLanguagePython:
+#ifndef LLDB_DISABLE_PYTHON
+ m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this));
+ break;
+#else
+ // Fall through to the None case when python is disabled
+#endif
+ case eScriptLanguageNone:
+ m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this));
+ break;
+ };
+
+ return m_script_interpreter_ap.get();
+}
+
+
+
+bool
+CommandInterpreter::GetSynchronous ()
+{
+ return m_synchronous_execution;
+}
+
+void
+CommandInterpreter::SetSynchronous (bool value)
+{
+ m_synchronous_execution = value;
+}
+
+void
+CommandInterpreter::OutputFormattedHelpText (Stream &strm,
+ const char *word_text,
+ const char *separator,
+ const char *help_text,
+ size_t max_word_len)
+{
+ const uint32_t max_columns = m_debugger.GetTerminalWidth();
+
+ int indent_size = max_word_len + strlen (separator) + 2;
+
+ strm.IndentMore (indent_size);
+
+ StreamString text_strm;
+ text_strm.Printf ("%-*s %s %s", (int)max_word_len, word_text, separator, help_text);
+
+ size_t len = text_strm.GetSize();
+ const char *text = text_strm.GetData();
+ if (text[len - 1] == '\n')
+ {
+ text_strm.EOL();
+ len = text_strm.GetSize();
+ }
+
+ 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;
+ size_t start = 0;
+ size_t end = start;
+ const size_t final_end = strlen (text);
+
+ 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--;
+ assert (end > 0);
+ }
+
+ const size_t 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);
+}
+
+void
+CommandInterpreter::OutputHelpText (Stream &strm,
+ const char *word_text,
+ const char *separator,
+ const char *help_text,
+ uint32_t max_word_len)
+{
+ int indent_size = max_word_len + strlen (separator) + 2;
+
+ strm.IndentMore (indent_size);
+
+ StreamString text_strm;
+ text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text);
+
+ const uint32_t max_columns = m_debugger.GetTerminalWidth();
+
+ size_t len = text_strm.GetSize();
+ const char *text = text_strm.GetData();
+
+ uint32_t chars_left = max_columns;
+
+ for (uint32_t i = 0; i < len; i++)
+ {
+ if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n')
+ {
+ chars_left = max_columns - indent_size;
+ strm.EOL();
+ strm.Indent();
+ }
+ else
+ {
+ strm.PutChar(text[i]);
+ chars_left--;
+ }
+
+ }
+
+ strm.EOL();
+ strm.IndentLess(indent_size);
+}
+
+void
+CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
+ StringList &commands_help, bool search_builtin_commands, bool search_user_commands)
+{
+ CommandObject::CommandMap::const_iterator pos;
+
+ if (search_builtin_commands)
+ {
+ 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())
+ cmd_obj->AproposAllSubCommands (command_name,
+ search_word,
+ commands_found,
+ commands_help);
+
+ }
+ }
+
+ if (search_user_commands)
+ {
+ for (pos = m_user_dict.begin(); pos != m_user_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())
+ cmd_obj->AproposAllSubCommands (command_name,
+ search_word,
+ commands_found,
+ commands_help);
+
+ }
+ }
+}
+
+
+void
+CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
+{
+ if (override_context != NULL)
+ {
+ m_exe_ctx_ref = *override_context;
+ }
+ else
+ {
+ const bool adopt_selected = true;
+ m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected);
+ }
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp
new file mode 100644
index 0000000..291dc40
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandObject.cpp
@@ -0,0 +1,1174 @@
+//===-- 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/lldb-python.h"
+
+#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/ArchSpec.h"
+#include "lldb/Interpreter/Options.h"
+
+// These are for the Sourcename completers.
+// FIXME: Make a separate file for the completers.
+#include "lldb/Host/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
+(
+ CommandInterpreter &interpreter,
+ const char *name,
+ const char *help,
+ const char *syntax,
+ uint32_t flags
+) :
+ m_interpreter (interpreter),
+ m_cmd_name (name),
+ m_cmd_help_short (),
+ m_cmd_help_long (),
+ m_cmd_syntax (),
+ m_is_alias (false),
+ m_flags (flags),
+ m_arguments(),
+ m_command_override_callback (NULL),
+ m_command_override_baton (NULL)
+{
+ 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 ()
+{
+ if (m_cmd_syntax.length() == 0)
+ {
+ StreamString syntax_str;
+ syntax_str.Printf ("%s", GetCommandName());
+ if (GetOptions() != NULL)
+ syntax_str.Printf (" <cmd-options>");
+ if (m_arguments.size() > 0)
+ {
+ syntax_str.Printf (" ");
+ if (WantsRawCommandString() && GetOptions() && GetOptions()->NumCommandOptions())
+ syntax_str.Printf("-- ");
+ GetFormattedCommandArguments (syntax_str);
+ }
+ m_cmd_syntax = syntax_str.GetData ();
+ }
+
+ return m_cmd_syntax.c_str();
+}
+
+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::SetHelpLong (std::string str)
+{
+ m_cmd_help_long = str;
+}
+
+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;
+}
+
+bool
+CommandObject::ParseOptions
+(
+ Args& args,
+ CommandReturnObject &result
+)
+{
+ // See if the subclass has options?
+ Options *options = GetOptions();
+ if (options != NULL)
+ {
+ Error error;
+ options->NotifyOptionParsingStarting();
+
+ // ParseOptions calls getopt_long_only, 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.Success())
+ error = options->NotifyOptionParsingFinished();
+
+ if (error.Success())
+ {
+ if (options->VerifyOptions (result))
+ return true;
+ }
+ else
+ {
+ const char *error_cstr = error.AsCString();
+ if (error_cstr)
+ {
+ // We got an error string, lets use that
+ result.AppendError(error_cstr);
+ }
+ else
+ {
+ // No error string, output the usage information into result
+ options->GenerateOptionUsage (result.GetErrorStream(), this);
+ }
+ }
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ return true;
+}
+
+
+
+bool
+CommandObject::CheckRequirements (CommandReturnObject &result)
+{
+#ifdef LLDB_CONFIGURATION_DEBUG
+ // Nothing should be stored in m_exe_ctx between running commands as m_exe_ctx
+ // has shared pointers to the target, process, thread and frame and we don't
+ // want any CommandObject instances to keep any of these objects around
+ // longer than for a single command. Every command should call
+ // CommandObject::Cleanup() after it has completed
+ assert (m_exe_ctx.GetTargetPtr() == NULL);
+ assert (m_exe_ctx.GetProcessPtr() == NULL);
+ assert (m_exe_ctx.GetThreadPtr() == NULL);
+ assert (m_exe_ctx.GetFramePtr() == NULL);
+#endif
+
+ // Lock down the interpreter's execution context prior to running the
+ // command so we guarantee the selected target, process, thread and frame
+ // can't go away during the execution
+ m_exe_ctx = m_interpreter.GetExecutionContext();
+
+ const uint32_t flags = GetFlags().Get();
+ if (flags & (eFlagRequiresTarget |
+ eFlagRequiresProcess |
+ eFlagRequiresThread |
+ eFlagRequiresFrame |
+ eFlagTryTargetAPILock ))
+ {
+
+ if ((flags & eFlagRequiresTarget) && !m_exe_ctx.HasTargetScope())
+ {
+ result.AppendError (GetInvalidTargetDescription());
+ return false;
+ }
+
+ if ((flags & eFlagRequiresProcess) && !m_exe_ctx.HasProcessScope())
+ {
+ result.AppendError (GetInvalidProcessDescription());
+ return false;
+ }
+
+ if ((flags & eFlagRequiresThread) && !m_exe_ctx.HasThreadScope())
+ {
+ result.AppendError (GetInvalidThreadDescription());
+ return false;
+ }
+
+ if ((flags & eFlagRequiresFrame) && !m_exe_ctx.HasFrameScope())
+ {
+ result.AppendError (GetInvalidFrameDescription());
+ return false;
+ }
+
+ if ((flags & eFlagRequiresRegContext) && (m_exe_ctx.GetRegisterContext() == NULL))
+ {
+ result.AppendError (GetInvalidRegContextDescription());
+ return false;
+ }
+
+ if (flags & eFlagTryTargetAPILock)
+ {
+ Target *target = m_exe_ctx.GetTargetPtr();
+ if (target)
+ {
+ if (m_api_locker.TryLock (target->GetAPIMutex(), NULL) == false)
+ {
+ result.AppendError ("failed to get API lock");
+ return false;
+ }
+ }
+ }
+ }
+
+ if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused))
+ {
+ Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
+ if (process == NULL)
+ {
+ // A process that is not running is considered paused.
+ if (GetFlags().Test(CommandObject::eFlagProcessMustBeLaunched))
+ {
+ result.AppendError ("Process must exist.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ StateType state = process->GetState();
+ switch (state)
+ {
+ case eStateInvalid:
+ case eStateSuspended:
+ case eStateCrashed:
+ case eStateStopped:
+ break;
+
+ case eStateConnected:
+ case eStateAttaching:
+ case eStateLaunching:
+ case eStateDetached:
+ case eStateExited:
+ case eStateUnloaded:
+ if (GetFlags().Test(CommandObject::eFlagProcessMustBeLaunched))
+ {
+ result.AppendError ("Process must be launched.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ break;
+
+ case eStateRunning:
+ case eStateStepping:
+ if (GetFlags().Test(CommandObject::eFlagProcessMustBePaused))
+ {
+ result.AppendError ("Process is running. Use 'process interrupt' to pause execution.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+void
+CommandObject::Cleanup ()
+{
+ m_exe_ctx.Clear();
+ m_api_locker.Unlock();
+}
+
+
+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 true;
+
+ return map_element.first.find (m_match_str, 0) == 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,
+ bool &word_complete,
+ StringList &matches
+)
+{
+ // Default implmentation of WantsCompletion() is !WantsRawCommandString().
+ // Subclasses who want raw command string but desire, for example,
+ // argument completion should override WantsCompletion() to return true,
+ // instead.
+ if (WantsRawCommandString() && !WantsCompletion())
+ {
+ // 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_only will freak out.
+
+ input.AppendArgument ("<FAKE-VALUE>");
+
+ input.ParseArgsForCompletion (*cur_options, opt_element_vector, cursor_index);
+
+ 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,
+ word_complete,
+ 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,
+ word_complete,
+ matches);
+ }
+}
+
+bool
+CommandObject::HelpTextContainsWord (const char *search_word)
+{
+ std::string options_usage_help;
+
+ bool found_word = false;
+
+ const char *short_help = GetHelp();
+ const char *long_help = GetHelpLong();
+ const char *syntax_help = GetSyntax();
+
+ if (short_help && strcasestr (short_help, search_word))
+ found_word = true;
+ else if (long_help && strcasestr (long_help, search_word))
+ found_word = true;
+ else if (syntax_help && strcasestr (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 (strcasestr (usage_text, search_word))
+ found_word = true;
+ }
+ }
+
+ return found_word;
+}
+
+int
+CommandObject::GetNumArgumentEntries ()
+{
+ return m_arguments.size();
+}
+
+CommandObject::CommandArgumentEntry *
+CommandObject::GetArgumentEntryAtIndex (int idx)
+{
+ if (idx < m_arguments.size())
+ return &(m_arguments[idx]);
+
+ return NULL;
+}
+
+CommandObject::ArgumentTableEntry *
+CommandObject::FindArgumentDataByType (CommandArgumentType arg_type)
+{
+ const ArgumentTableEntry *table = CommandObject::GetArgumentTable();
+
+ for (int i = 0; i < eArgTypeLastArg; ++i)
+ if (table[i].arg_type == arg_type)
+ return (ArgumentTableEntry *) &(table[i]);
+
+ return NULL;
+}
+
+void
+CommandObject::GetArgumentHelp (Stream &str, CommandArgumentType arg_type, CommandInterpreter &interpreter)
+{
+ const ArgumentTableEntry* table = CommandObject::GetArgumentTable();
+ ArgumentTableEntry *entry = (ArgumentTableEntry *) &(table[arg_type]);
+
+ // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up...
+
+ if (entry->arg_type != arg_type)
+ entry = CommandObject::FindArgumentDataByType (arg_type);
+
+ if (!entry)
+ return;
+
+ StreamString name_str;
+ name_str.Printf ("<%s>", entry->arg_name);
+
+ if (entry->help_function)
+ {
+ const char* help_text = entry->help_function();
+ if (!entry->help_function.self_formatting)
+ {
+ interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", help_text,
+ name_str.GetSize());
+ }
+ else
+ {
+ interpreter.OutputHelpText(str, name_str.GetData(), "--", help_text,
+ name_str.GetSize());
+ }
+ }
+ else
+ interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", entry->help_text, name_str.GetSize());
+}
+
+const char *
+CommandObject::GetArgumentName (CommandArgumentType arg_type)
+{
+ ArgumentTableEntry *entry = (ArgumentTableEntry *) &(CommandObject::GetArgumentTable()[arg_type]);
+
+ // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up...
+
+ if (entry->arg_type != arg_type)
+ entry = CommandObject::FindArgumentDataByType (arg_type);
+
+ if (entry)
+ return entry->arg_name;
+
+ StreamString str;
+ str << "Arg name for type (" << arg_type << ") not in arg table!";
+ return str.GetData();
+}
+
+bool
+CommandObject::IsPairType (ArgumentRepetitionType arg_repeat_type)
+{
+ if ((arg_repeat_type == eArgRepeatPairPlain)
+ || (arg_repeat_type == eArgRepeatPairOptional)
+ || (arg_repeat_type == eArgRepeatPairPlus)
+ || (arg_repeat_type == eArgRepeatPairStar)
+ || (arg_repeat_type == eArgRepeatPairRange)
+ || (arg_repeat_type == eArgRepeatPairRangeOptional))
+ return true;
+
+ return false;
+}
+
+static CommandObject::CommandArgumentEntry
+OptSetFiltered(uint32_t opt_set_mask, CommandObject::CommandArgumentEntry &cmd_arg_entry)
+{
+ CommandObject::CommandArgumentEntry ret_val;
+ for (unsigned i = 0; i < cmd_arg_entry.size(); ++i)
+ if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association)
+ ret_val.push_back(cmd_arg_entry[i]);
+ return ret_val;
+}
+
+// Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means take
+// all the argument data into account. On rare cases where some argument sticks
+// with certain option sets, this function returns the option set filtered args.
+void
+CommandObject::GetFormattedCommandArguments (Stream &str, uint32_t opt_set_mask)
+{
+ int num_args = m_arguments.size();
+ for (int i = 0; i < num_args; ++i)
+ {
+ if (i > 0)
+ str.Printf (" ");
+ CommandArgumentEntry arg_entry =
+ opt_set_mask == LLDB_OPT_SET_ALL ? m_arguments[i]
+ : OptSetFiltered(opt_set_mask, m_arguments[i]);
+ int num_alternatives = arg_entry.size();
+
+ if ((num_alternatives == 2)
+ && IsPairType (arg_entry[0].arg_repetition))
+ {
+ const char *first_name = GetArgumentName (arg_entry[0].arg_type);
+ const char *second_name = GetArgumentName (arg_entry[1].arg_type);
+ switch (arg_entry[0].arg_repetition)
+ {
+ case eArgRepeatPairPlain:
+ str.Printf ("<%s> <%s>", first_name, second_name);
+ break;
+ case eArgRepeatPairOptional:
+ str.Printf ("[<%s> <%s>]", first_name, second_name);
+ break;
+ case eArgRepeatPairPlus:
+ str.Printf ("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name, first_name, second_name);
+ break;
+ case eArgRepeatPairStar:
+ str.Printf ("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name, first_name, second_name);
+ break;
+ case eArgRepeatPairRange:
+ str.Printf ("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name, first_name, second_name);
+ break;
+ case eArgRepeatPairRangeOptional:
+ str.Printf ("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name, first_name, second_name);
+ break;
+ // Explicitly test for all the rest of the cases, so if new types get added we will notice the
+ // missing case statement(s).
+ case eArgRepeatPlain:
+ case eArgRepeatOptional:
+ case eArgRepeatPlus:
+ case eArgRepeatStar:
+ case eArgRepeatRange:
+ // These should not be reached, as they should fail the IsPairType test above.
+ break;
+ }
+ }
+ else
+ {
+ StreamString names;
+ for (int j = 0; j < num_alternatives; ++j)
+ {
+ if (j > 0)
+ names.Printf (" | ");
+ names.Printf ("%s", GetArgumentName (arg_entry[j].arg_type));
+ }
+ switch (arg_entry[0].arg_repetition)
+ {
+ case eArgRepeatPlain:
+ str.Printf ("<%s>", names.GetData());
+ break;
+ case eArgRepeatPlus:
+ str.Printf ("<%s> [<%s> [...]]", names.GetData(), names.GetData());
+ break;
+ case eArgRepeatStar:
+ str.Printf ("[<%s> [<%s> [...]]]", names.GetData(), names.GetData());
+ break;
+ case eArgRepeatOptional:
+ str.Printf ("[<%s>]", names.GetData());
+ break;
+ case eArgRepeatRange:
+ str.Printf ("<%s_1> .. <%s_n>", names.GetData(), names.GetData());
+ break;
+ // Explicitly test for all the rest of the cases, so if new types get added we will notice the
+ // missing case statement(s).
+ case eArgRepeatPairPlain:
+ case eArgRepeatPairOptional:
+ case eArgRepeatPairPlus:
+ case eArgRepeatPairStar:
+ case eArgRepeatPairRange:
+ case eArgRepeatPairRangeOptional:
+ // These should not be hit, as they should pass the IsPairType test above, and control should
+ // have gone into the other branch of the if statement.
+ break;
+ }
+ }
+ }
+}
+
+CommandArgumentType
+CommandObject::LookupArgumentName (const char *arg_name)
+{
+ CommandArgumentType return_type = eArgTypeLastArg;
+
+ std::string arg_name_str (arg_name);
+ size_t len = arg_name_str.length();
+ if (arg_name[0] == '<'
+ && arg_name[len-1] == '>')
+ arg_name_str = arg_name_str.substr (1, len-2);
+
+ const ArgumentTableEntry *table = GetArgumentTable();
+ for (int i = 0; i < eArgTypeLastArg; ++i)
+ if (arg_name_str.compare (table[i].arg_name) == 0)
+ return_type = g_arguments_data[i].arg_type;
+
+ return return_type;
+}
+
+static const char *
+RegisterNameHelpTextCallback ()
+{
+ return "Register names can be specified using the architecture specific names. "
+ "They can also be specified using generic names. Not all generic entities have "
+ "registers backing them on all architectures. When they don't the generic name "
+ "will return an error.\n"
+ "The generic names defined in lldb are:\n"
+ "\n"
+ "pc - program counter register\n"
+ "ra - return address register\n"
+ "fp - frame pointer register\n"
+ "sp - stack pointer register\n"
+ "flags - the flags register\n"
+ "arg{1-6} - integer argument passing registers.\n";
+}
+
+static const char *
+BreakpointIDHelpTextCallback ()
+{
+ return "Breakpoint ID's consist major and minor numbers; the major number "
+ "corresponds to the single entity that was created with a 'breakpoint set' "
+ "command; the minor numbers correspond to all the locations that were actually "
+ "found/set based on the major breakpoint. A full breakpoint ID might look like "
+ "3.14, meaning the 14th location set for the 3rd breakpoint. You can specify "
+ "all the locations of a breakpoint by just indicating the major breakpoint "
+ "number. A valid breakpoint id consists either of just the major id number, "
+ "or the major number, a dot, and the location number (e.g. 3 or 3.2 could "
+ "both be valid breakpoint ids).";
+}
+
+static const char *
+BreakpointIDRangeHelpTextCallback ()
+{
+ return "A 'breakpoint id list' is a manner of specifying multiple breakpoints. "
+ "This can be done through several mechanisms. The easiest way is to just "
+ "enter a space-separated list of breakpoint ids. To specify all the "
+ "breakpoint locations under a major breakpoint, you can use the major "
+ "breakpoint number followed by '.*', eg. '5.*' means all the locations under "
+ "breakpoint 5. You can also indicate a range of breakpoints by using "
+ "<start-bp-id> - <end-bp-id>. The start-bp-id and end-bp-id for a range can "
+ "be any valid breakpoint ids. It is not legal, however, to specify a range "
+ "using specific locations that cross major breakpoint numbers. I.e. 3.2 - 3.7"
+ " is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal.";
+}
+
+static const char *
+GDBFormatHelpTextCallback ()
+{
+ return "A GDB format consists of a repeat count, a format letter and a size letter. "
+ "The repeat count is optional and defaults to 1. The format letter is optional "
+ "and defaults to the previous format that was used. The size letter is optional "
+ "and defaults to the previous size that was used.\n"
+ "\n"
+ "Format letters include:\n"
+ "o - octal\n"
+ "x - hexadecimal\n"
+ "d - decimal\n"
+ "u - unsigned decimal\n"
+ "t - binary\n"
+ "f - float\n"
+ "a - address\n"
+ "i - instruction\n"
+ "c - char\n"
+ "s - string\n"
+ "T - OSType\n"
+ "A - float as hex\n"
+ "\n"
+ "Size letters include:\n"
+ "b - 1 byte (byte)\n"
+ "h - 2 bytes (halfword)\n"
+ "w - 4 bytes (word)\n"
+ "g - 8 bytes (giant)\n"
+ "\n"
+ "Example formats:\n"
+ "32xb - show 32 1 byte hexadecimal integer values\n"
+ "16xh - show 16 2 byte hexadecimal integer values\n"
+ "64 - show 64 2 byte hexadecimal integer values (format and size from the last format)\n"
+ "dw - show 1 4 byte decimal integer value\n"
+ ;
+}
+
+static const char *
+FormatHelpTextCallback ()
+{
+
+ static char* help_text_ptr = NULL;
+
+ if (help_text_ptr)
+ return help_text_ptr;
+
+ StreamString sstr;
+ sstr << "One of the format names (or one-character names) that can be used to show a variable's value:\n";
+ for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1))
+ {
+ if (f != eFormatDefault)
+ sstr.PutChar('\n');
+
+ char format_char = FormatManager::GetFormatAsFormatChar(f);
+ if (format_char)
+ sstr.Printf("'%c' or ", format_char);
+
+ sstr.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f));
+ }
+
+ sstr.Flush();
+
+ std::string data = sstr.GetString();
+
+ help_text_ptr = new char[data.length()+1];
+
+ data.copy(help_text_ptr, data.length());
+
+ return help_text_ptr;
+}
+
+static const char *
+LanguageTypeHelpTextCallback ()
+{
+ static char* help_text_ptr = NULL;
+
+ if (help_text_ptr)
+ return help_text_ptr;
+
+ StreamString sstr;
+ sstr << "One of the following languages:\n";
+
+ for (unsigned int l = eLanguageTypeUnknown; l < eNumLanguageTypes; ++l)
+ {
+ sstr << " " << LanguageRuntime::GetNameForLanguageType(static_cast<LanguageType>(l)) << "\n";
+ }
+
+ sstr.Flush();
+
+ std::string data = sstr.GetString();
+
+ help_text_ptr = new char[data.length()+1];
+
+ data.copy(help_text_ptr, data.length());
+
+ return help_text_ptr;
+}
+
+static const char *
+SummaryStringHelpTextCallback()
+{
+ return
+ "A summary string is a way to extract information from variables in order to present them using a summary.\n"
+ "Summary strings contain static text, variables, scopes and control sequences:\n"
+ " - Static text can be any sequence of non-special characters, i.e. anything but '{', '}', '$', or '\\'.\n"
+ " - Variables are sequences of characters beginning with ${, ending with } and that contain symbols in the format described below.\n"
+ " - Scopes are any sequence of text between { and }. Anything included in a scope will only appear in the output summary if there were no errors.\n"
+ " - Control sequences are the usual C/C++ '\\a', '\\n', ..., plus '\\$', '\\{' and '\\}'.\n"
+ "A summary string works by copying static text verbatim, turning control sequences into their character counterpart, expanding variables and trying to expand scopes.\n"
+ "A variable is expanded by giving it a value other than its textual representation, and the way this is done depends on what comes after the ${ marker.\n"
+ "The most common sequence if ${var followed by an expression path, which is the text one would type to access a member of an aggregate types, given a variable of that type"
+ " (e.g. if type T has a member named x, which has a member named y, and if t is of type T, the expression path would be .x.y and the way to fit that into a summary string would be"
+ " ${var.x.y}). You can also use ${*var followed by an expression path and in that case the object referred by the path will be dereferenced before being displayed."
+ " If the object is not a pointer, doing so will cause an error. For additional details on expression paths, you can type 'help expr-path'. \n"
+ "By default, summary strings attempt to display the summary for any variable they reference, and if that fails the value. If neither can be shown, nothing is displayed."
+ "In a summary string, you can also use an array index [n], or a slice-like range [n-m]. This can have two different meanings depending on what kind of object the expression"
+ " path refers to:\n"
+ " - if it is a scalar type (any basic type like int, float, ...) the expression is a bitfield, i.e. the bits indicated by the indexing operator are extracted out of the number"
+ " and displayed as an individual variable\n"
+ " - if it is an array or pointer the array items indicated by the indexing operator are shown as the result of the variable. if the expression is an array, real array items are"
+ " printed; if it is a pointer, the pointer-as-array syntax is used to obtain the values (this means, the latter case can have no range checking)\n"
+ "If you are trying to display an array for which the size is known, you can also use [] instead of giving an exact range. This has the effect of showing items 0 thru size - 1.\n"
+ "Additionally, a variable can contain an (optional) format code, as in ${var.x.y%code}, where code can be any of the valid formats described in 'help format', or one of the"
+ " special symbols only allowed as part of a variable:\n"
+ " %V: show the value of the object by default\n"
+ " %S: show the summary of the object by default\n"
+ " %@: show the runtime-provided object description (for Objective-C, it calls NSPrintForDebugger; for C/C++ it does nothing)\n"
+ " %L: show the location of the object (memory address or a register name)\n"
+ " %#: show the number of children of the object\n"
+ " %T: show the type of the object\n"
+ "Another variable that you can use in summary strings is ${svar . This sequence works exactly like ${var, including the fact that ${*svar is an allowed sequence, but uses"
+ " the object's synthetic children provider instead of the actual objects. For instance, if you are using STL synthetic children providers, the following summary string would"
+ " count the number of actual elements stored in an std::list:\n"
+ "type summary add -s \"${svar%#}\" -x \"std::list<\"";
+}
+
+static const char *
+ExprPathHelpTextCallback()
+{
+ return
+ "An expression path is the sequence of symbols that is used in C/C++ to access a member variable of an aggregate object (class).\n"
+ "For instance, given a class:\n"
+ " class foo {\n"
+ " int a;\n"
+ " int b; .\n"
+ " foo* next;\n"
+ " };\n"
+ "the expression to read item b in the item pointed to by next for foo aFoo would be aFoo.next->b.\n"
+ "Given that aFoo could just be any object of type foo, the string '.next->b' is the expression path, because it can be attached to any foo instance to achieve the effect.\n"
+ "Expression paths in LLDB include dot (.) and arrow (->) operators, and most commands using expression paths have ways to also accept the star (*) operator.\n"
+ "The meaning of these operators is the same as the usual one given to them by the C/C++ standards.\n"
+ "LLDB also has support for indexing ([ ]) in expression paths, and extends the traditional meaning of the square brackets operator to allow bitfield extraction:\n"
+ "for objects of native types (int, float, char, ...) saying '[n-m]' as an expression path (where n and m are any positive integers, e.g. [3-5]) causes LLDB to extract"
+ " bits n thru m from the value of the variable. If n == m, [n] is also allowed as a shortcut syntax. For arrays and pointers, expression paths can only contain one index"
+ " and the meaning of the operation is the same as the one defined by C/C++ (item extraction). Some commands extend bitfield-like syntax for arrays and pointers with the"
+ " meaning of array slicing (taking elements n thru m inside the array or pointed-to memory).";
+}
+
+void
+CommandObject::GenerateHelpText (CommandReturnObject &result)
+{
+ GenerateHelpText(result.GetOutputStream());
+
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+}
+
+void
+CommandObject::GenerateHelpText (Stream &output_strm)
+{
+ CommandInterpreter& interpreter = GetCommandInterpreter();
+ if (GetOptions() != NULL)
+ {
+ if (WantsRawCommandString())
+ {
+ std::string help_text (GetHelp());
+ help_text.append (" This command takes 'raw' input (no need to quote stuff).");
+ interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
+ }
+ else
+ interpreter.OutputFormattedHelpText (output_strm, "", "", GetHelp(), 1);
+ output_strm.Printf ("\nSyntax: %s\n", GetSyntax());
+ GetOptions()->GenerateOptionUsage (output_strm, this);
+ const char *long_help = GetHelpLong();
+ if ((long_help != NULL)
+ && (strlen (long_help) > 0))
+ output_strm.Printf ("\n%s", long_help);
+ if (WantsRawCommandString() && !WantsCompletion())
+ {
+ // Emit the message about using ' -- ' between the end of the command options and the raw input
+ // conditionally, i.e., only if the command object does not want completion.
+ interpreter.OutputFormattedHelpText (output_strm, "", "",
+ "\nIMPORTANT NOTE: Because this command takes 'raw' input, if you use any command options"
+ " you must use ' -- ' between the end of the command options and the beginning of the raw input.", 1);
+ }
+ else if (GetNumArgumentEntries() > 0
+ && GetOptions()
+ && GetOptions()->NumCommandOptions() > 0)
+ {
+ // Also emit a warning about using "--" in case you are using a command that takes options and arguments.
+ interpreter.OutputFormattedHelpText (output_strm, "", "",
+ "\nThis command takes options and free-form arguments. If your arguments resemble"
+ " option specifiers (i.e., they start with a - or --), you must use ' -- ' between"
+ " the end of the command options and the beginning of the arguments.", 1);
+ }
+ }
+ else if (IsMultiwordObject())
+ {
+ if (WantsRawCommandString())
+ {
+ std::string help_text (GetHelp());
+ help_text.append (" This command takes 'raw' input (no need to quote stuff).");
+ interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
+ }
+ else
+ interpreter.OutputFormattedHelpText (output_strm, "", "", GetHelp(), 1);
+ GenerateHelpText (output_strm);
+ }
+ else
+ {
+ const char *long_help = GetHelpLong();
+ if ((long_help != NULL)
+ && (strlen (long_help) > 0))
+ output_strm.Printf ("%s", long_help);
+ else if (WantsRawCommandString())
+ {
+ std::string help_text (GetHelp());
+ help_text.append (" This command takes 'raw' input (no need to quote stuff).");
+ interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
+ }
+ else
+ interpreter.OutputFormattedHelpText (output_strm, "", "", GetHelp(), 1);
+ output_strm.Printf ("\nSyntax: %s\n", GetSyntax());
+ }
+}
+
+void
+CommandObject::AddIDsArgumentData(CommandArgumentEntry &arg, CommandArgumentType ID, CommandArgumentType IDRange)
+{
+ CommandArgumentData id_arg;
+ CommandArgumentData id_range_arg;
+
+ // Create the first variant for the first (and only) argument for this command.
+ id_arg.arg_type = ID;
+ id_arg.arg_repetition = eArgRepeatOptional;
+
+ // Create the second variant for the first (and only) argument for this command.
+ id_range_arg.arg_type = IDRange;
+ id_range_arg.arg_repetition = eArgRepeatOptional;
+
+ // The first (and only) argument for this command could be either an id or an id_range.
+ // Push both variants into the entry for the first argument for this command.
+ arg.push_back(id_arg);
+ arg.push_back(id_range_arg);
+}
+
+const char *
+CommandObject::GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type)
+{
+ if (arg_type >=0 && arg_type < eArgTypeLastArg)
+ return g_arguments_data[arg_type].arg_name;
+ return NULL;
+
+}
+
+const char *
+CommandObject::GetArgumentDescriptionAsCString (const lldb::CommandArgumentType arg_type)
+{
+ if (arg_type >=0 && arg_type < eArgTypeLastArg)
+ return g_arguments_data[arg_type].help_text;
+ return NULL;
+}
+
+bool
+CommandObjectParsed::Execute (const char *args_string, CommandReturnObject &result)
+{
+ CommandOverrideCallback command_callback = GetOverrideCallback();
+ bool handled = false;
+ Args cmd_args (args_string);
+ if (command_callback)
+ {
+ Args full_args (GetCommandName ());
+ full_args.AppendArguments(cmd_args);
+ handled = command_callback (GetOverrideCallbackBaton(), full_args.GetConstArgumentVector());
+ }
+ if (!handled)
+ {
+ for (size_t i = 0; i < cmd_args.GetArgumentCount(); ++i)
+ {
+ const char *tmp_str = cmd_args.GetArgumentAtIndex (i);
+ if (tmp_str[0] == '`') // back-quote
+ cmd_args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str));
+ }
+
+ if (CheckRequirements(result))
+ {
+ if (ParseOptions (cmd_args, result))
+ {
+ // Call the command-specific version of 'Execute', passing it the already processed arguments.
+ handled = DoExecute (cmd_args, result);
+ }
+ }
+
+ Cleanup();
+ }
+ return handled;
+}
+
+bool
+CommandObjectRaw::Execute (const char *args_string, CommandReturnObject &result)
+{
+ CommandOverrideCallback command_callback = GetOverrideCallback();
+ bool handled = false;
+ if (command_callback)
+ {
+ std::string full_command (GetCommandName ());
+ full_command += ' ';
+ full_command += args_string;
+ const char *argv[2] = { NULL, NULL };
+ argv[0] = full_command.c_str();
+ handled = command_callback (GetOverrideCallbackBaton(), argv);
+ }
+ if (!handled)
+ {
+ if (CheckRequirements(result))
+ handled = DoExecute (args_string, result);
+
+ Cleanup();
+ }
+ return handled;
+}
+
+static
+const char *arch_helper()
+{
+ static StreamString g_archs_help;
+ if (g_archs_help.Empty())
+ {
+ StringList archs;
+ ArchSpec::AutoComplete(NULL, archs);
+ g_archs_help.Printf("These are the supported architecture names:\n");
+ archs.Join("\n", g_archs_help);
+ }
+ return g_archs_help.GetData();
+}
+
+CommandObject::ArgumentTableEntry
+CommandObject::g_arguments_data[] =
+{
+ { eArgTypeAddress, "address", CommandCompletions::eNoCompletion, { NULL, false }, "A valid address in the target program's execution space." },
+ { eArgTypeAddressOrExpression, "address-expression", CommandCompletions::eNoCompletion, { NULL, false }, "An expression that resolves to an address." },
+ { eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of an abbreviation (alias) for a debugger command." },
+ { eArgTypeAliasOptions, "options-for-aliased-command", CommandCompletions::eNoCompletion, { NULL, false }, "Command options to be used as part of an alias (abbreviation) definition. (See 'help commands alias' for more information.)" },
+ { eArgTypeArchitecture, "arch", CommandCompletions::eArchitectureCompletion, { arch_helper, true }, "The architecture name, e.g. i386 or x86_64." },
+ { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { NULL, false }, "A Boolean value: 'true' or 'false'" },
+ { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, NULL },
+ { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, NULL },
+ { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { NULL, false }, "Number of bytes to use." },
+ { eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { NULL, false }, "Then name of a class from the debug information in the program." },
+ { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { NULL, false }, "A debugger command (may be multiple words), without any options or arguments." },
+ { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." },
+ { eArgTypeDirectoryName, "directory", CommandCompletions::eDiskDirectoryCompletion, { NULL, false }, "A directory name." },
+ { eArgTypeDisassemblyFlavor, "disassembly-flavor", CommandCompletions::eNoCompletion, { NULL, false }, "A disassembly flavor recognized by your disassembly plugin. Currently the only valid options are \"att\" and \"intel\" for Intel targets" },
+ { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
+ { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
+ { eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, { ExprPathHelpTextCallback, true }, NULL },
+ { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { NULL, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" },
+ { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { NULL, false }, "The name of a file (can include path)." },
+ { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, NULL },
+ { eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, { NULL, false }, "Index into a thread's list of frames." },
+ { eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
+ { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a function." },
+ { eArgTypeFunctionOrSymbol, "function-or-symbol", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a function or symbol." },
+ { eArgTypeGDBFormat, "gdb-format", CommandCompletions::eNoCompletion, { GDBFormatHelpTextCallback, true }, NULL },
+ { eArgTypeIndex, "index", CommandCompletions::eNoCompletion, { NULL, false }, "An index into a list." },
+ { eArgTypeLanguage, "language", CommandCompletions::eNoCompletion, { LanguageTypeHelpTextCallback, true }, NULL },
+ { eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, { NULL, false }, "Line number in a source file." },
+ { eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a category within a log channel, e.g. all (try \"log list\" to see a list of all channels and their categories." },
+ { eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." },
+ { eArgTypeMethod, "method", CommandCompletions::eNoCompletion, { NULL, false }, "A C++ method name." },
+ { eArgTypeName, "name", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
+ { eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
+ { eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, { NULL, false }, "The number of lines to use." },
+ { eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, { NULL, false }, "The number of items per line to display." },
+ { eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
+ { eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
+ { eArgTypeOneLiner, "one-line-command", CommandCompletions::eNoCompletion, { NULL, false }, "A command that is entered as a single line of text." },
+ { eArgTypePid, "pid", CommandCompletions::eNoCompletion, { NULL, false }, "The process ID number." },
+ { eArgTypePlugin, "plugin", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
+ { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the process." },
+ { eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python class." },
+ { eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python function." },
+ { eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { NULL, false }, "Source code written in Python." },
+ { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the thread queue." },
+ { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { RegisterNameHelpTextCallback, true }, NULL },
+ { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { NULL, false }, "A regular expression." },
+ { eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, { NULL, false }, "Arguments to be passed to the target program when it starts executing." },
+ { eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
+ { eArgTypeScriptedCommandSynchronicity, "script-cmd-synchronicity", CommandCompletions::eNoCompletion, { NULL, false }, "The synchronicity to use to run scripted commands with regard to LLDB event system." },
+ { eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, { NULL, false }, "The scripting language to be used for script-based commands. Currently only Python is valid." },
+ { eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, { NULL, false }, "The word for which you wish to search for information about." },
+ { eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, { NULL, false }, "An Objective-C selector name." },
+ { eArgTypeSettingIndex, "setting-index", CommandCompletions::eNoCompletion, { NULL, false }, "An index into a settings variable that is an array (try 'settings list' to see all the possible settings variables and their types)." },
+ { eArgTypeSettingKey, "setting-key", CommandCompletions::eNoCompletion, { NULL, false }, "A key into a settings variables that is a dictionary (try 'settings list' to see all the possible settings variables and their types)." },
+ { eArgTypeSettingPrefix, "setting-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a settable internal debugger variable up to a dot ('.'), e.g. 'target.process.'" },
+ { eArgTypeSettingVariableName, "setting-variable-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a settable internal debugger variable. Type 'settings list' to see a complete list of such variables." },
+ { eArgTypeShlibName, "shlib-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a shared library." },
+ { eArgTypeSourceFile, "source-file", CommandCompletions::eSourceFileCompletion, { NULL, false }, "The name of a source file.." },
+ { eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, { NULL, false }, "Specify a sort order when dumping lists." },
+ { eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
+ { eArgTypeSummaryString, "summary-string", CommandCompletions::eNoCompletion, { SummaryStringHelpTextCallback, true }, NULL },
+ { eArgTypeSymbol, "symbol", CommandCompletions::eSymbolCompletion, { NULL, false }, "Any symbol name (function name, variable, argument, etc.)" },
+ { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, { NULL, false }, "Thread ID number." },
+ { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, { NULL, false }, "Index into the process' list of threads." },
+ { eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, { NULL, false }, "The thread's name." },
+ { eArgTypeUnsignedInteger, "unsigned-integer", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." },
+ { eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, { NULL, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." },
+ { eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a variable in your program." },
+ { eArgTypeValue, "value", CommandCompletions::eNoCompletion, { NULL, false }, "A value could be anything, depending on where and how it is used." },
+ { eArgTypeWidth, "width", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
+ { eArgTypeNone, "none", CommandCompletions::eNoCompletion, { NULL, false }, "No help available for this." },
+ { eArgTypePlatform, "platform-name", CommandCompletions::ePlatformPluginCompletion, { NULL, false }, "The name of an installed platform plug-in . Type 'platform list' to see a complete list of installed platforms." },
+ { eArgTypeWatchpointID, "watchpt-id", CommandCompletions::eNoCompletion, { NULL, false }, "Watchpoint IDs are positive integers." },
+ { eArgTypeWatchpointIDRange, "watchpt-id-list", CommandCompletions::eNoCompletion, { NULL, false }, "For example, '1-3' or '1 to 3'." },
+ { eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, { NULL, false }, "Specify the type for a watchpoint." }
+};
+
+const CommandObject::ArgumentTableEntry*
+CommandObject::GetArgumentTable ()
+{
+ // If this assertion fires, then the table above is out of date with the CommandArgumentType enumeration
+ assert ((sizeof (CommandObject::g_arguments_data) / sizeof (CommandObject::ArgumentTableEntry)) == eArgTypeLastArg);
+ return CommandObject::g_arguments_data;
+}
+
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectRegexCommand.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectRegexCommand.cpp
new file mode 100644
index 0000000..59cf1f0
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectRegexCommand.cpp
@@ -0,0 +1,150 @@
+//===-- 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/lldb-python.h"
+
+#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
+(
+ CommandInterpreter &interpreter,
+ const char *name,
+ const char *help,
+ const char *syntax,
+ uint32_t max_matches,
+ uint32_t completion_type_mask
+) :
+ CommandObjectRaw (interpreter, name, help, syntax),
+ m_max_matches (max_matches),
+ m_completion_type_mask (completion_type_mask),
+ m_entries ()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CommandObjectRegexCommand::~CommandObjectRegexCommand()
+{
+}
+
+
+bool
+CommandObjectRegexCommand::DoExecute
+(
+ const char *command,
+ CommandReturnObject &result
+)
+{
+ if (command)
+ {
+ EntryCollection::const_iterator pos, end = m_entries.end();
+ for (pos = m_entries.begin(); pos != end; ++pos)
+ {
+ RegularExpression::Match regex_match(m_max_matches);
+
+ if (pos->regex.Execute (command, &regex_match))
+ {
+ 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 (regex_match.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_interpreter.GetExpandRegexAliases())
+ result.GetOutputStream().Printf("%s\n", new_command.c_str());
+ // Pass in true for "no context switching". The command that called us should have set up the context
+ // appropriately, we shouldn't have to redo that.
+ return m_interpreter.HandleCommand(new_command.c_str(), eLazyBoolCalculate, result, NULL, true, true);
+ }
+ }
+ result.SetStatus(eReturnStatusFailed);
+ if (GetSyntax() != NULL)
+ result.AppendError (GetSyntax());
+ else
+ 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 expression 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;
+}
+
+int
+CommandObjectRegexCommand::HandleCompletion (Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+{
+ if (m_completion_type_mask)
+ {
+ std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
+ CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
+ m_completion_type_mask,
+ completion_str.c_str(),
+ match_start_point,
+ max_return_elements,
+ NULL,
+ word_complete,
+ matches);
+ return matches.GetSize();
+ }
+ else
+ {
+ matches.Clear();
+ word_complete = false;
+ }
+ return 0;
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.cpp
new file mode 100644
index 0000000..aff507d
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.cpp
@@ -0,0 +1,93 @@
+//===-- CommandObjectScript.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "CommandObjectScript.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/Core/Debugger.h"
+
+#include "lldb/DataFormatters/DataVisualization.h"
+
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectScript
+//-------------------------------------------------------------------------
+
+CommandObjectScript::CommandObjectScript (CommandInterpreter &interpreter, ScriptLanguage script_lang) :
+ CommandObjectRaw (interpreter,
+ "script",
+ "Pass an expression to the script interpreter for evaluation and return the results. Drop into the interactive interpreter if no expression is given.",
+ "script [<script-expression-for-evaluation>]")
+{
+}
+
+CommandObjectScript::~CommandObjectScript ()
+{
+}
+
+bool
+CommandObjectScript::DoExecute
+(
+ const char *command,
+ CommandReturnObject &result
+)
+{
+#ifdef LLDB_DISABLE_PYTHON
+ // if we ever support languages other than Python this simple #ifdef won't work
+ result.AppendError("your copy of LLDB does not support scripting.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+#else
+ if (m_interpreter.GetDebugger().GetScriptLanguage() == lldb::eScriptLanguageNone)
+ {
+ result.AppendError("the script-lang setting is set to none - scripting not available");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ ScriptInterpreter *script_interpreter = m_interpreter.GetScriptInterpreter ();
+
+ if (script_interpreter == NULL)
+ {
+ result.AppendError("no script interpreter");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ DataVisualization::ForceUpdate(); // script might change Python code we use for formatting.. make sure we keep up to date with it
+
+ if (command == NULL || command[0] == '\0')
+ {
+ script_interpreter->ExecuteInterpreterLoop ();
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ return result.Succeeded();
+ }
+
+ // We can do better when reporting the status of one-liner script execution.
+ if (script_interpreter->ExecuteOneLine (command, &result))
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+
+ return result.Succeeded();
+#endif
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.h b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.h
new file mode 100644
index 0000000..fd55fc4
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandObjectScript.h
@@ -0,0 +1,42 @@
+//===-- CommandObjectScript.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectScript_h_
+#define liblldb_CommandObjectScript_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectScript
+//-------------------------------------------------------------------------
+
+class CommandObjectScript : public CommandObjectRaw
+{
+public:
+
+ CommandObjectScript (CommandInterpreter &interpreter,
+ lldb::ScriptLanguage script_lang);
+
+ virtual
+ ~CommandObjectScript ();
+
+protected:
+ virtual bool
+ DoExecute (const char *command, CommandReturnObject &result);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectScript_h_
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/CommandReturnObject.cpp b/contrib/llvm/tools/lldb/source/Interpreter/CommandReturnObject.cpp
new file mode 100644
index 0000000..9c63753
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/CommandReturnObject.cpp
@@ -0,0 +1,219 @@
+//===-- 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/Error.h"
+#include "lldb/Core/StreamString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static void
+DumpStringToStreamWithNewline (Stream &strm, const std::string &s, bool add_newline_if_empty)
+{
+ bool add_newline = false;
+ if (s.empty())
+ {
+ add_newline = add_newline_if_empty;
+ }
+ else
+ {
+ // We already checked for empty above, now make sure there is a newline
+ // in the error, and if there isn't one, add one.
+ strm.Write(s.c_str(), s.size());
+
+ const char last_char = *s.rbegin();
+ add_newline = last_char != '\n' && last_char != '\r';
+
+ }
+ if (add_newline)
+ strm.EOL();
+}
+
+
+CommandReturnObject::CommandReturnObject () :
+ m_out_stream (),
+ m_err_stream (),
+ m_status (eReturnStatusStarted),
+ m_did_change_process_state (false)
+{
+}
+
+CommandReturnObject::~CommandReturnObject ()
+{
+}
+
+void
+CommandReturnObject::AppendErrorWithFormat (const char *format, ...)
+{
+ if (!format)
+ return;
+ va_list args;
+ va_start (args, format);
+ StreamString sstrm;
+ sstrm.PrintfVarArg(format, args);
+ va_end (args);
+
+
+ const std::string &s = sstrm.GetString();
+ if (!s.empty())
+ {
+ Stream &error_strm = GetErrorStream();
+ error_strm.PutCString ("error: ");
+ DumpStringToStreamWithNewline (error_strm, s, false);
+ }
+}
+
+void
+CommandReturnObject::AppendMessageWithFormat (const char *format, ...)
+{
+ if (!format)
+ return;
+ va_list args;
+ va_start (args, format);
+ StreamString sstrm;
+ sstrm.PrintfVarArg(format, args);
+ va_end (args);
+
+ GetOutputStream().Printf("%s", sstrm.GetData());
+}
+
+void
+CommandReturnObject::AppendWarningWithFormat (const char *format, ...)
+{
+ if (!format)
+ return;
+ va_list args;
+ va_start (args, format);
+ StreamString sstrm;
+ sstrm.PrintfVarArg(format, args);
+ va_end (args);
+
+ GetErrorStream().Printf("warning: %s", sstrm.GetData());
+}
+
+void
+CommandReturnObject::AppendMessage (const char *in_string)
+{
+ if (!in_string)
+ return;
+ GetOutputStream().Printf("%s\n", in_string);
+}
+
+void
+CommandReturnObject::AppendWarning (const char *in_string)
+{
+ if (!in_string || *in_string == '\0')
+ return;
+ GetErrorStream().Printf("warning: %s\n", 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)
+{
+ if (in_string && in_string[0])
+ GetErrorStream().PutCString(in_string);
+}
+
+void
+CommandReturnObject::AppendError (const char *in_string)
+{
+ if (!in_string || *in_string == '\0')
+ return;
+ GetErrorStream().Printf ("error: %s\n", in_string);
+}
+
+void
+CommandReturnObject::SetError (const Error &error, const char *fallback_error_cstr)
+{
+ const char *error_cstr = error.AsCString();
+ if (error_cstr == NULL)
+ error_cstr = fallback_error_cstr;
+ SetError(error_cstr);
+}
+
+void
+CommandReturnObject::SetError (const char *error_cstr)
+{
+ if (error_cstr)
+ {
+ AppendError (error_cstr);
+ SetStatus (eReturnStatusFailed);
+ }
+}
+
+// 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)
+{
+ if (in_string && in_string[0])
+ GetErrorStream().PutCString(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()
+{
+ lldb::StreamSP stream_sp;
+ stream_sp = m_out_stream.GetStreamAtIndex (eStreamStringIndex);
+ if (stream_sp)
+ static_cast<StreamString *>(stream_sp.get())->Clear();
+ stream_sp = m_err_stream.GetStreamAtIndex (eStreamStringIndex);
+ if (stream_sp)
+ static_cast<StreamString *>(stream_sp.get())->Clear();
+ m_status = eReturnStatusStarted;
+ m_did_change_process_state = false;
+}
+
+bool
+CommandReturnObject::GetDidChangeProcessState ()
+{
+ return m_did_change_process_state;
+}
+
+void
+CommandReturnObject::SetDidChangeProcessState (bool b)
+{
+ m_did_change_process_state = b;
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupArchitecture.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupArchitecture.cpp
new file mode 100644
index 0000000..af103bb
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupArchitecture.cpp
@@ -0,0 +1,86 @@
+//===-- OptionGroupArchitecture.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/OptionGroupArchitecture.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Utility/Utils.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+OptionGroupArchitecture::OptionGroupArchitecture() :
+ m_arch_str ()
+{
+}
+
+OptionGroupArchitecture::~OptionGroupArchitecture ()
+{
+}
+
+static OptionDefinition
+g_option_table[] =
+{
+ { LLDB_OPT_SET_1 , false, "arch" , 'a', required_argument, NULL, 0, eArgTypeArchitecture , "Specify the architecture for the target."},
+};
+
+uint32_t
+OptionGroupArchitecture::GetNumDefinitions ()
+{
+ return llvm::array_lengthof(g_option_table);
+}
+
+const OptionDefinition *
+OptionGroupArchitecture::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+bool
+OptionGroupArchitecture::GetArchitecture (Platform *platform, ArchSpec &arch)
+{
+ if (m_arch_str.empty())
+ arch.Clear();
+ else
+ arch.SetTriple(m_arch_str.c_str(), platform);
+ return arch.IsValid();
+}
+
+
+Error
+OptionGroupArchitecture::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error;
+ const int short_option = g_option_table[option_idx].short_option;
+
+ switch (short_option)
+ {
+ case 'a':
+ m_arch_str.assign (option_arg);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+OptionGroupArchitecture::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ m_arch_str.clear();
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupBoolean.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupBoolean.cpp
new file mode 100644
index 0000000..5b5b384
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupBoolean.cpp
@@ -0,0 +1,67 @@
+//===-- OptionGroupBoolean.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/OptionGroupBoolean.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb;
+using namespace lldb_private;
+
+OptionGroupBoolean::OptionGroupBoolean (uint32_t usage_mask,
+ bool required,
+ const char *long_option,
+ int short_option,
+ const char *usage_text,
+ bool default_value,
+ bool no_argument_toggle_default) :
+ m_value (default_value, default_value)
+{
+ m_option_definition.usage_mask = usage_mask;
+ m_option_definition.required = required;
+ m_option_definition.long_option = long_option;
+ m_option_definition.short_option = short_option;
+ m_option_definition.option_has_arg = no_argument_toggle_default ? no_argument : required_argument;
+ m_option_definition.enum_values = NULL;
+ m_option_definition.completion_type = 0;
+ m_option_definition.argument_type = eArgTypeBoolean;
+ m_option_definition.usage_text = usage_text;
+}
+
+OptionGroupBoolean::~OptionGroupBoolean ()
+{
+}
+
+Error
+OptionGroupBoolean::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error;
+ if (m_option_definition.option_has_arg == no_argument)
+ {
+ // Not argument, toggle the default value and mark the option as having been set
+ m_value.SetCurrentValue (!m_value.GetDefaultValue());
+ m_value.SetOptionWasSet ();
+ }
+ else
+ {
+ error = m_value.SetValueFromCString (option_arg);
+ }
+ return error;
+}
+
+void
+OptionGroupBoolean::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ m_value.Clear();
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupFile.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupFile.cpp
new file mode 100644
index 0000000..6867395
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupFile.cpp
@@ -0,0 +1,97 @@
+//===-- OptionGroupFile.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/OptionGroupFile.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb;
+using namespace lldb_private;
+
+OptionGroupFile::OptionGroupFile (uint32_t usage_mask,
+ bool required,
+ const char *long_option,
+ int short_option,
+ uint32_t completion_type,
+ lldb::CommandArgumentType argument_type,
+ const char *usage_text) :
+ m_file ()
+{
+ m_option_definition.usage_mask = usage_mask;
+ m_option_definition.required = required;
+ m_option_definition.long_option = long_option;
+ m_option_definition.short_option = short_option;
+ m_option_definition.option_has_arg = required_argument;
+ m_option_definition.enum_values = NULL;
+ m_option_definition.completion_type = completion_type;
+ m_option_definition.argument_type = argument_type;
+ m_option_definition.usage_text = usage_text;
+}
+
+OptionGroupFile::~OptionGroupFile ()
+{
+}
+
+Error
+OptionGroupFile::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error (m_file.SetValueFromCString (option_arg));
+ return error;
+}
+
+void
+OptionGroupFile::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ m_file.Clear();
+}
+
+
+OptionGroupFileList::OptionGroupFileList (uint32_t usage_mask,
+ bool required,
+ const char *long_option,
+ int short_option,
+ uint32_t completion_type,
+ lldb::CommandArgumentType argument_type,
+ const char *usage_text) :
+ m_file_list ()
+{
+ m_option_definition.usage_mask = usage_mask;
+ m_option_definition.required = required;
+ m_option_definition.long_option = long_option;
+ m_option_definition.short_option = short_option;
+ m_option_definition.option_has_arg = required_argument;
+ m_option_definition.enum_values = NULL;
+ m_option_definition.completion_type = completion_type;
+ m_option_definition.argument_type = argument_type;
+ m_option_definition.usage_text = usage_text;
+}
+
+OptionGroupFileList::~OptionGroupFileList ()
+{
+}
+
+Error
+OptionGroupFileList::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error (m_file_list.SetValueFromCString (option_arg));
+ return error;
+}
+
+void
+OptionGroupFileList::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ m_file_list.Clear();
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupFormat.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupFormat.cpp
new file mode 100644
index 0000000..790cbb6
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupFormat.cpp
@@ -0,0 +1,249 @@
+//===-- OptionGroupFormat.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Interpreter/OptionGroupFormat.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/Utils.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+OptionGroupFormat::OptionGroupFormat (lldb::Format default_format,
+ uint64_t default_byte_size,
+ uint64_t default_count) :
+ m_format (default_format, default_format),
+ m_byte_size (default_byte_size, default_byte_size),
+ m_count (default_count, default_count),
+ m_prev_gdb_format('x'),
+ m_prev_gdb_size('w')
+{
+}
+
+OptionGroupFormat::~OptionGroupFormat ()
+{
+}
+
+static OptionDefinition
+g_option_table[] =
+{
+{ LLDB_OPT_SET_1, false, "format" ,'f', required_argument, NULL, 0, eArgTypeFormat , "Specify a format to be used for display."},
+{ LLDB_OPT_SET_2, false, "gdb-format",'G', required_argument, NULL, 0, eArgTypeGDBFormat, "Specify a format using a GDB format specifier string."},
+{ LLDB_OPT_SET_3, false, "size" ,'s', required_argument, NULL, 0, eArgTypeByteSize , "The size in bytes to use when displaying with the selected format."},
+{ LLDB_OPT_SET_4, false, "count" ,'c', required_argument, NULL, 0, eArgTypeCount , "The number of total items to display."},
+};
+
+uint32_t
+OptionGroupFormat::GetNumDefinitions ()
+{
+ if (m_byte_size.GetDefaultValue() < UINT64_MAX)
+ {
+ if (m_count.GetDefaultValue() < UINT64_MAX)
+ return 4;
+ else
+ return 3;
+ }
+ return 2;
+}
+
+const OptionDefinition *
+OptionGroupFormat::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+Error
+OptionGroupFormat::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error;
+ const int short_option = g_option_table[option_idx].short_option;
+
+ switch (short_option)
+ {
+ case 'f':
+ error = m_format.SetValueFromCString (option_arg);
+ break;
+
+ case 'c':
+ if (m_count.GetDefaultValue() == 0)
+ {
+ error.SetErrorString ("--count option is disabled");
+ }
+ else
+ {
+ error = m_count.SetValueFromCString (option_arg);
+ if (m_count.GetCurrentValue() == 0)
+ error.SetErrorStringWithFormat("invalid --count option value '%s'", option_arg);
+ }
+ break;
+
+ case 's':
+ if (m_byte_size.GetDefaultValue() == 0)
+ {
+ error.SetErrorString ("--size option is disabled");
+ }
+ else
+ {
+ error = m_byte_size.SetValueFromCString (option_arg);
+ if (m_byte_size.GetCurrentValue() == 0)
+ error.SetErrorStringWithFormat("invalid --size option value '%s'", option_arg);
+ }
+ break;
+
+ case 'G':
+ {
+ char *end = NULL;
+ const char *gdb_format_cstr = option_arg;
+ uint64_t count = 0;
+ if (::isdigit (gdb_format_cstr[0]))
+ {
+ count = strtoull (gdb_format_cstr, &end, 0);
+
+ if (option_arg != end)
+ gdb_format_cstr = end; // We have a valid count, advance the string position
+ else
+ count = 0;
+ }
+
+ Format format = eFormatDefault;
+ uint32_t byte_size = 0;
+
+ while (ParserGDBFormatLetter (interpreter, gdb_format_cstr[0], format, byte_size))
+ {
+ ++gdb_format_cstr;
+ }
+
+ // We the first character of the "gdb_format_cstr" is not the
+ // NULL terminator, we didn't consume the entire string and
+ // something is wrong. Also, if none of the format, size or count
+ // was specified correctly, then abort.
+ if (gdb_format_cstr[0] || (format == eFormatInvalid && byte_size == 0 && count == 0))
+ {
+ // Nothing got set correctly
+ error.SetErrorStringWithFormat ("invalid gdb format string '%s'", option_arg);
+ return error;
+ }
+
+ // At least one of the format, size or count was set correctly.
+ // Anything that wasn't set correctly should be set to the
+ // previous default
+ if (format == eFormatInvalid)
+ ParserGDBFormatLetter (interpreter, m_prev_gdb_format, format, byte_size);
+
+ const bool byte_size_enabled = m_byte_size.GetDefaultValue() < UINT64_MAX;
+ const bool count_enabled = m_count.GetDefaultValue() < UINT64_MAX;
+ if (byte_size_enabled)
+ {
+ // Byte size is enabled
+ if (byte_size == 0)
+ ParserGDBFormatLetter (interpreter, m_prev_gdb_size, format, byte_size);
+ }
+ else
+ {
+ // Byte size is disabled, make sure it wasn't specified
+ if (byte_size > 0)
+ {
+ error.SetErrorString ("this command doesn't support specifying a byte size");
+ return error;
+ }
+ }
+
+ if (count_enabled)
+ {
+ // Count is enabled and was not set, set it to the default for gdb format statements (which is 1).
+ if (count == 0)
+ count = 1;
+ }
+ else
+ {
+ // Count is disabled, make sure it wasn't specified
+ if (count > 0)
+ {
+ error.SetErrorString ("this command doesn't support specifying a count");
+ return error;
+ }
+ }
+
+ m_format.SetCurrentValue (format);
+ m_format.SetOptionWasSet ();
+ if (byte_size_enabled)
+ {
+ m_byte_size.SetCurrentValue (byte_size);
+ m_byte_size.SetOptionWasSet ();
+ }
+ if (count_enabled)
+ {
+ m_count.SetCurrentValue(count);
+ m_count.SetOptionWasSet ();
+ }
+ }
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+}
+
+bool
+OptionGroupFormat::ParserGDBFormatLetter (CommandInterpreter &interpreter, char format_letter, Format &format, uint32_t &byte_size)
+{
+ m_has_gdb_format = true;
+ switch (format_letter)
+ {
+ case 'o': format = eFormatOctal; m_prev_gdb_format = format_letter; return true;
+ case 'x': format = eFormatHex; m_prev_gdb_format = format_letter; return true;
+ case 'd': format = eFormatDecimal; m_prev_gdb_format = format_letter; return true;
+ case 'u': format = eFormatUnsigned; m_prev_gdb_format = format_letter; return true;
+ case 't': format = eFormatBinary; m_prev_gdb_format = format_letter; return true;
+ case 'f': format = eFormatFloat; m_prev_gdb_format = format_letter; return true;
+ case 'a': format = eFormatAddressInfo;
+ {
+ ExecutionContext exe_ctx(interpreter.GetExecutionContext());
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ byte_size = target->GetArchitecture().GetAddressByteSize();
+ m_prev_gdb_format = format_letter;
+ return true;
+ }
+ case 'i': format = eFormatInstruction; m_prev_gdb_format = format_letter; return true;
+ case 'c': format = eFormatChar; m_prev_gdb_format = format_letter; return true;
+ case 's': format = eFormatCString; m_prev_gdb_format = format_letter; return true;
+ case 'T': format = eFormatOSType; m_prev_gdb_format = format_letter; return true;
+ case 'A': format = eFormatHexFloat; m_prev_gdb_format = format_letter; return true;
+ case 'b': byte_size = 1; m_prev_gdb_size = format_letter; return true;
+ case 'h': byte_size = 2; m_prev_gdb_size = format_letter; return true;
+ case 'w': byte_size = 4; m_prev_gdb_size = format_letter; return true;
+ case 'g': byte_size = 8; m_prev_gdb_size = format_letter; return true;
+ default: break;
+ }
+ return false;
+}
+
+void
+OptionGroupFormat::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ m_format.Clear();
+ m_byte_size.Clear();
+ m_count.Clear();
+ m_has_gdb_format = false;
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupOutputFile.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupOutputFile.cpp
new file mode 100644
index 0000000..aa01bf5
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupOutputFile.cpp
@@ -0,0 +1,81 @@
+//===-- OptionGroupOutputFile.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/OptionGroupOutputFile.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Utility/Utils.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+OptionGroupOutputFile::OptionGroupOutputFile() :
+ m_file (),
+ m_append (false, false)
+{
+}
+
+OptionGroupOutputFile::~OptionGroupOutputFile ()
+{
+}
+
+static OptionDefinition
+g_option_table[] =
+{
+ { LLDB_OPT_SET_1 , false, "outfile", 'o', required_argument, NULL, 0, eArgTypeFilename , "Specify a path for capturing command output."},
+ { LLDB_OPT_SET_1 , false, "append-outfile" , 'apnd', no_argument, NULL, 0, eArgTypeNone , "Append to the the file specified with '--outfile <path>'."},
+};
+
+uint32_t
+OptionGroupOutputFile::GetNumDefinitions ()
+{
+ return llvm::array_lengthof(g_option_table);
+}
+
+const OptionDefinition *
+OptionGroupOutputFile::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+Error
+OptionGroupOutputFile::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error;
+ const int short_option = g_option_table[option_idx].short_option;
+
+ switch (short_option)
+ {
+ case 'o':
+ error = m_file.SetValueFromCString (option_arg);
+ break;
+
+ case 'apnd':
+ m_append.SetCurrentValue(true);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+OptionGroupOutputFile::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ m_file.Clear();
+ m_append.Clear();
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupPlatform.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupPlatform.cpp
new file mode 100644
index 0000000..a54edaf
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupPlatform.cpp
@@ -0,0 +1,149 @@
+//===-- OptionGroupPlatform.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Interpreter/OptionGroupPlatform.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/Platform.h"
+#include "lldb/Utility/Utils.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+PlatformSP
+OptionGroupPlatform::CreatePlatformWithOptions (CommandInterpreter &interpreter,
+ const ArchSpec &arch,
+ bool make_selected,
+ Error& error,
+ ArchSpec &platform_arch) const
+{
+ PlatformSP platform_sp;
+
+ if (!m_platform_name.empty())
+ {
+ platform_sp = Platform::Create (m_platform_name.c_str(), error);
+ if (platform_sp)
+ {
+ if (platform_arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch))
+ {
+ error.SetErrorStringWithFormat ("platform '%s' doesn't support '%s'",
+ platform_sp->GetName().GetCString(),
+ arch.GetTriple().getTriple().c_str());
+ platform_sp.reset();
+ return platform_sp;
+ }
+ }
+ }
+ else if (arch.IsValid())
+ {
+ platform_sp = Platform::Create (arch, &platform_arch, error);
+ }
+
+ if (platform_sp)
+ {
+ interpreter.GetDebugger().GetPlatformList().Append (platform_sp, make_selected);
+ if (m_os_version_major != UINT32_MAX)
+ {
+ platform_sp->SetOSVersion (m_os_version_major,
+ m_os_version_minor,
+ m_os_version_update);
+ }
+
+ if (m_sdk_sysroot)
+ platform_sp->SetSDKRootDirectory (m_sdk_sysroot);
+
+ if (m_sdk_build)
+ platform_sp->SetSDKBuild (m_sdk_build);
+ }
+
+ return platform_sp;
+}
+
+void
+OptionGroupPlatform::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ m_platform_name.clear();
+ m_sdk_sysroot.Clear();
+ m_sdk_build.Clear();
+ m_os_version_major = UINT32_MAX;
+ m_os_version_minor = UINT32_MAX;
+ m_os_version_update = UINT32_MAX;
+}
+
+static OptionDefinition
+g_option_table[] =
+{
+ { LLDB_OPT_SET_ALL, false, "platform", 'p', required_argument, NULL, 0, eArgTypePlatform, "Specify name of the platform to use for this target, creating the platform if necessary."},
+ { LLDB_OPT_SET_ALL, false, "version" , 'v', required_argument, NULL, 0, eArgTypeNone, "Specify the initial SDK version to use prior to connecting." },
+ { LLDB_OPT_SET_ALL, false, "build" , 'b', required_argument, NULL, 0, eArgTypeNone, "Specify the initial SDK build number." },
+ { LLDB_OPT_SET_ALL, false, "sysroot" , 'S', required_argument, NULL, 0, eArgTypeFilename, "Specify the SDK root directory that contains a root of all remote system files." }
+};
+
+const OptionDefinition*
+OptionGroupPlatform::GetDefinitions ()
+{
+ if (m_include_platform_option)
+ return g_option_table;
+ return g_option_table + 1;
+}
+
+uint32_t
+OptionGroupPlatform::GetNumDefinitions ()
+{
+ if (m_include_platform_option)
+ return llvm::array_lengthof(g_option_table);
+ return llvm::array_lengthof(g_option_table) - 1;
+}
+
+
+Error
+OptionGroupPlatform::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error;
+ if (!m_include_platform_option)
+ ++option_idx;
+
+ const int short_option = g_option_table[option_idx].short_option;
+
+ switch (short_option)
+ {
+ case 'p':
+ m_platform_name.assign (option_arg);
+ break;
+
+ case 'v':
+ if (Args::StringToVersion (option_arg,
+ m_os_version_major,
+ m_os_version_minor,
+ m_os_version_update) == option_arg)
+ error.SetErrorStringWithFormat ("invalid version string '%s'", option_arg);
+ break;
+
+ case 'b':
+ m_sdk_build.SetCString (option_arg);
+ break;
+
+ case 'S':
+ m_sdk_sysroot.SetCString (option_arg);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+ return error;
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupString.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupString.cpp
new file mode 100644
index 0000000..ee96239
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupString.cpp
@@ -0,0 +1,58 @@
+//===-- OptionGroupString.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/OptionGroupString.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb;
+using namespace lldb_private;
+
+OptionGroupString::OptionGroupString (uint32_t usage_mask,
+ bool required,
+ const char *long_option,
+ int short_option,
+ uint32_t completion_type,
+ lldb::CommandArgumentType argument_type,
+ const char *usage_text,
+ const char *default_value) :
+ m_value (default_value, default_value)
+{
+ m_option_definition.usage_mask = usage_mask;
+ m_option_definition.required = required;
+ m_option_definition.long_option = long_option;
+ m_option_definition.short_option = short_option;
+ m_option_definition.option_has_arg = required_argument;
+ m_option_definition.enum_values = NULL;
+ m_option_definition.completion_type = completion_type;
+ m_option_definition.argument_type = argument_type;
+ m_option_definition.usage_text = usage_text;
+}
+
+OptionGroupString::~OptionGroupString ()
+{
+}
+
+Error
+OptionGroupString::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error (m_value.SetValueFromCString (option_arg));
+ return error;
+}
+
+void
+OptionGroupString::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ m_value.Clear();
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupUInt64.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupUInt64.cpp
new file mode 100644
index 0000000..e6996f7
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupUInt64.cpp
@@ -0,0 +1,58 @@
+//===-- OptionGroupUInt64.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/OptionGroupUInt64.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb;
+using namespace lldb_private;
+
+OptionGroupUInt64::OptionGroupUInt64 (uint32_t usage_mask,
+ bool required,
+ const char *long_option,
+ int short_option,
+ uint32_t completion_type,
+ lldb::CommandArgumentType argument_type,
+ const char *usage_text,
+ uint64_t default_value) :
+ m_value (default_value, default_value)
+{
+ m_option_definition.usage_mask = usage_mask;
+ m_option_definition.required = required;
+ m_option_definition.long_option = long_option;
+ m_option_definition.short_option = short_option;
+ m_option_definition.option_has_arg = required_argument;
+ m_option_definition.enum_values = NULL;
+ m_option_definition.completion_type = completion_type;
+ m_option_definition.argument_type = argument_type;
+ m_option_definition.usage_text = usage_text;
+}
+
+OptionGroupUInt64::~OptionGroupUInt64 ()
+{
+}
+
+Error
+OptionGroupUInt64::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error (m_value.SetValueFromCString (option_arg));
+ return error;
+}
+
+void
+OptionGroupUInt64::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ m_value.Clear();
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupUUID.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupUUID.cpp
new file mode 100644
index 0000000..14bdc84
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupUUID.cpp
@@ -0,0 +1,76 @@
+//===-- OptionGroupUUID.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/OptionGroupUUID.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Utility/Utils.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+OptionGroupUUID::OptionGroupUUID() :
+ m_uuid ()
+{
+}
+
+OptionGroupUUID::~OptionGroupUUID ()
+{
+}
+
+static OptionDefinition
+g_option_table[] =
+{
+ { LLDB_OPT_SET_1 , false, "uuid", 'u', required_argument, NULL, 0, eArgTypeNone, "A module UUID value."},
+};
+
+uint32_t
+OptionGroupUUID::GetNumDefinitions ()
+{
+ return llvm::array_lengthof(g_option_table);
+}
+
+const OptionDefinition *
+OptionGroupUUID::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+Error
+OptionGroupUUID::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error;
+ const int short_option = g_option_table[option_idx].short_option;
+
+ switch (short_option)
+ {
+ case 'u':
+ error = m_uuid.SetValueFromCString (option_arg);
+ if (error.Success())
+ m_uuid.SetOptionWasSet();
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+OptionGroupUUID::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ m_uuid.Clear();
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
new file mode 100644
index 0000000..22a7f37
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupValueObjectDisplay.cpp
@@ -0,0 +1,181 @@
+//===-- OptionGroupValueObjectDisplay.cpp -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/Target.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Utility/Utils.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+OptionGroupValueObjectDisplay::OptionGroupValueObjectDisplay()
+{
+}
+
+OptionGroupValueObjectDisplay::~OptionGroupValueObjectDisplay ()
+{
+}
+
+static OptionDefinition
+g_option_table[] =
+{
+ { LLDB_OPT_SET_1, false, "dynamic-type", 'd', required_argument, g_dynamic_value_types, 0, eArgTypeNone, "Show the object as its full dynamic type, not its static type, if available."},
+ { LLDB_OPT_SET_1, false, "synthetic-type", 'S', required_argument, NULL, 0, eArgTypeBoolean, "Show the object obeying its synthetic provider, if available."},
+ { LLDB_OPT_SET_1, false, "depth", 'D', required_argument, NULL, 0, eArgTypeCount, "Set the max recurse depth when dumping aggregate types (default is infinity)."},
+ { LLDB_OPT_SET_1, false, "flat", 'F', no_argument, NULL, 0, eArgTypeNone, "Display results in a flat format that uses expression paths for each variable or member."},
+ { LLDB_OPT_SET_1, false, "location", 'L', no_argument, NULL, 0, eArgTypeNone, "Show variable location information."},
+ { LLDB_OPT_SET_1, false, "object-description", 'O', no_argument, NULL, 0, eArgTypeNone, "Print as an Objective-C object."},
+ { LLDB_OPT_SET_1, false, "ptr-depth", 'P', required_argument, NULL, 0, eArgTypeCount, "The number of pointers to be traversed when dumping values (default is zero)."},
+ { LLDB_OPT_SET_1, false, "show-types", 'T', no_argument, NULL, 0, eArgTypeNone, "Show variable types when dumping values."},
+ { LLDB_OPT_SET_1, false, "no-summary-depth", 'Y', optional_argument, NULL, 0, eArgTypeCount, "Set the depth at which omitting summary information stops (default is 1)."},
+ { LLDB_OPT_SET_1, false, "raw-output", 'R', no_argument, NULL, 0, eArgTypeNone, "Don't use formatting options."},
+ { LLDB_OPT_SET_1, false, "show-all-children", 'A', no_argument, NULL, 0, eArgTypeNone, "Ignore the upper bound on the number of children to show."},
+ { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+};
+
+uint32_t
+OptionGroupValueObjectDisplay::GetNumDefinitions ()
+{
+ return llvm::array_lengthof(g_option_table);
+}
+
+const OptionDefinition *
+OptionGroupValueObjectDisplay::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+
+Error
+OptionGroupValueObjectDisplay::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error;
+ const int short_option = g_option_table[option_idx].short_option;
+ bool success = false;
+
+ switch (short_option)
+ {
+ case 'd':
+ {
+ int32_t result;
+ result = Args::StringToOptionEnum (option_arg, g_dynamic_value_types, 2, error);
+ if (error.Success())
+ use_dynamic = (lldb::DynamicValueType) result;
+ }
+ break;
+ case 'T': show_types = true; break;
+ case 'L': show_location= true; break;
+ case 'F': flat_output = true; break;
+ case 'O': use_objc = true; break;
+ case 'R': be_raw = true; break;
+ case 'A': ignore_cap = true; break;
+
+ case 'D':
+ max_depth = Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid max depth '%s'", option_arg);
+ break;
+
+ case 'P':
+ ptr_depth = Args::StringToUInt32 (option_arg, 0, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid pointer depth '%s'", option_arg);
+ break;
+
+ case 'Y':
+ if (option_arg)
+ {
+ no_summary_depth = Args::StringToUInt32 (option_arg, 0, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid pointer depth '%s'", option_arg);
+ }
+ else
+ no_summary_depth = 1;
+ break;
+
+ case 'S':
+ use_synth = Args::StringToBoolean(option_arg, true, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid synthetic-type '%s'", option_arg);
+ break;
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+OptionGroupValueObjectDisplay::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ // If these defaults change, be sure to modify AnyOptionWasSet().
+ show_types = false;
+ no_summary_depth = 0;
+ show_location = false;
+ flat_output = false;
+ use_objc = false;
+ max_depth = UINT32_MAX;
+ ptr_depth = 0;
+ use_synth = true;
+ be_raw = false;
+ ignore_cap = false;
+
+ Target *target = interpreter.GetExecutionContext().GetTargetPtr();
+ if (target != NULL)
+ use_dynamic = target->GetPreferDynamicValue();
+ else
+ {
+ // If we don't have any targets, then dynamic values won't do us much good.
+ use_dynamic = lldb::eNoDynamicValues;
+ }
+}
+
+ValueObject::DumpValueObjectOptions
+OptionGroupValueObjectDisplay::GetAsDumpOptions (bool objc_is_compact,
+ lldb::Format format,
+ lldb::TypeSummaryImplSP summary_sp)
+{
+ ValueObject::DumpValueObjectOptions options;
+ options.SetMaximumPointerDepth(ptr_depth);
+ if (use_objc)
+ options.SetShowSummary(false);
+ else
+ options.SetOmitSummaryDepth(no_summary_depth);
+ options.SetMaximumDepth(max_depth)
+ .SetShowTypes(show_types)
+ .SetShowLocation(show_location)
+ .SetUseObjectiveC(use_objc)
+ .SetUseDynamicType(use_dynamic)
+ .SetUseSyntheticValue(use_synth)
+ .SetFlatOutput(flat_output)
+ .SetIgnoreCap(ignore_cap)
+ .SetFormat(format)
+ .SetSummary(summary_sp);
+
+ if (objc_is_compact)
+ options.SetHideRootType(use_objc)
+ .SetHideName(use_objc)
+ .SetHideValue(use_objc);
+
+ if (be_raw)
+ options.SetRawDisplay(true);
+
+ return options;
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupVariable.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupVariable.cpp
new file mode 100644
index 0000000..316747e
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupVariable.cpp
@@ -0,0 +1,144 @@
+//===-- OptionGroupVariable.cpp -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Interpreter/OptionGroupVariable.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Error.h"
+#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/Utils.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// if you add any options here, remember to update the counters in OptionGroupVariable::GetNumDefinitions()
+static OptionDefinition
+g_option_table[] =
+{
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-args", 'a', no_argument, NULL, 0, eArgTypeNone, "Omit function arguments."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-locals", 'l', no_argument, NULL, 0, eArgTypeNone, "Omit local variables."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-globals", 'g', no_argument, NULL, 0, eArgTypeNone, "Show the current frame source file global and static variables."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-declaration",'c', no_argument, NULL, 0, eArgTypeNone, "Show variable declaration information (source file and line where the variable was declared)."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "regex", 'r', no_argument, NULL, 0, eArgTypeRegularExpression, "The <variable-name> argument for name lookups are regular expressions."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "scope", 's', no_argument, NULL, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."},
+ { LLDB_OPT_SET_1, false, "summary", 'y', required_argument, NULL, 0, eArgTypeName, "Specify the summary that the variable output should use."},
+ { LLDB_OPT_SET_2, false, "summary-string", 'z', required_argument, NULL, 0, eArgTypeName, "Specify a summary string to use to format the variable output."},
+};
+
+static Error
+ValidateNamedSummary (const char* str, void*)
+{
+ if (!str || !str[0])
+ return Error("must specify a valid named summary");
+ TypeSummaryImplSP summary_sp;
+ if (DataVisualization::NamedSummaryFormats::GetSummaryFormat(ConstString(str), summary_sp) == false)
+ return Error("must specify a valid named summary");
+ return Error();
+}
+
+static Error
+ValidateSummaryString (const char* str, void*)
+{
+ if (!str || !str[0])
+ return Error("must specify a non-empty summary string");
+ return Error();
+}
+
+OptionGroupVariable::OptionGroupVariable (bool show_frame_options) :
+ OptionGroup(),
+ include_frame_options (show_frame_options),
+ summary(ValidateNamedSummary),
+ summary_string(ValidateSummaryString)
+{
+}
+
+OptionGroupVariable::~OptionGroupVariable ()
+{
+}
+
+Error
+OptionGroupVariable::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error;
+ if (!include_frame_options)
+ option_idx += 3;
+ const int short_option = g_option_table[option_idx].short_option;
+ switch (short_option)
+ {
+ case 'r': use_regex = true; break;
+ case 'a': show_args = false; break;
+ case 'l': show_locals = false; break;
+ case 'g': show_globals = true; break;
+ case 'c': show_decl = true; break;
+ case 's':
+ show_scope = true;
+ break;
+ case 'y':
+ error = summary.SetCurrentValue(option_arg);
+ break;
+ case 'z':
+ error = summary_string.SetCurrentValue(option_arg);
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+OptionGroupVariable::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ show_args = true; // Frame option only
+ show_locals = true; // Frame option only
+ show_globals = false; // Frame option only
+ show_decl = false;
+ use_regex = false;
+ show_scope = false;
+ summary.Clear();
+ summary_string.Clear();
+}
+
+#define NUM_FRAME_OPTS 3
+
+const OptionDefinition*
+OptionGroupVariable::GetDefinitions ()
+{
+ // Show the "--no-args", "--no-locals" and "--show-globals"
+ // options if we are showing frame specific options
+ if (include_frame_options)
+ return g_option_table;
+
+ // Skip the "--no-args", "--no-locals" and "--show-globals"
+ // options if we are not showing frame specific options (globals only)
+ return &g_option_table[NUM_FRAME_OPTS];
+}
+
+uint32_t
+OptionGroupVariable::GetNumDefinitions ()
+{
+ // Count the "--no-args", "--no-locals" and "--show-globals"
+ // options if we are showing frame specific options.
+ if (include_frame_options)
+ return llvm::array_lengthof(g_option_table);
+ else
+ return llvm::array_lengthof(g_option_table) - NUM_FRAME_OPTS;
+}
+
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupWatchpoint.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupWatchpoint.cpp
new file mode 100644
index 0000000..9eef37a
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionGroupWatchpoint.cpp
@@ -0,0 +1,121 @@
+//===-- OptionGroupWatchpoint.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/OptionGroupWatchpoint.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-enumerations.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Utility/Utils.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static OptionEnumValueElement g_watch_type[] =
+{
+ { OptionGroupWatchpoint::eWatchRead, "read", "Watch for read"},
+ { OptionGroupWatchpoint::eWatchWrite, "write", "Watch for write"},
+ { OptionGroupWatchpoint::eWatchReadWrite, "read_write", "Watch for read/write"},
+ { 0, NULL, NULL }
+};
+
+static OptionEnumValueElement g_watch_size[] =
+{
+ { 1, "1", "Watch for byte size of 1"},
+ { 2, "2", "Watch for byte size of 2"},
+ { 4, "4", "Watch for byte size of 4"},
+ { 8, "8", "Watch for byte size of 8"},
+ { 0, NULL, NULL }
+};
+
+static OptionDefinition
+g_option_table[] =
+{
+ { LLDB_OPT_SET_1, false, "watch", 'w', required_argument, g_watch_type, 0, eArgTypeWatchType, "Specify the type of watching to perform."},
+ { LLDB_OPT_SET_1, false, "xsize", 'x', required_argument, g_watch_size, 0, eArgTypeByteSize, "Number of bytes to use to watch a region."}
+};
+
+
+bool
+OptionGroupWatchpoint::IsWatchSizeSupported(uint32_t watch_size)
+{
+ for (uint32_t i = 0; i < llvm::array_lengthof(g_watch_size); ++i)
+ {
+ if (g_watch_size[i].value == 0)
+ break;
+ if (watch_size == g_watch_size[i].value)
+ return true;
+ }
+ return false;
+}
+
+OptionGroupWatchpoint::OptionGroupWatchpoint () :
+ OptionGroup()
+{
+}
+
+OptionGroupWatchpoint::~OptionGroupWatchpoint ()
+{
+}
+
+Error
+OptionGroupWatchpoint::SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+{
+ Error error;
+ const int short_option = g_option_table[option_idx].short_option;
+ switch (short_option)
+ {
+ case 'w':
+ {
+ WatchType tmp_watch_type;
+ tmp_watch_type = (WatchType) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
+ if (error.Success())
+ {
+ watch_type = tmp_watch_type;
+ watch_type_specified = true;
+ }
+ break;
+ }
+ case 'x':
+ watch_size = (uint32_t) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+OptionGroupWatchpoint::OptionParsingStarting (CommandInterpreter &interpreter)
+{
+ watch_type_specified = false;
+ watch_type = eWatchInvalid;
+ watch_size = 0;
+}
+
+
+const OptionDefinition*
+OptionGroupWatchpoint::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+uint32_t
+OptionGroupWatchpoint::GetNumDefinitions ()
+{
+ return llvm::array_lengthof(g_option_table);
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValue.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValue.cpp
new file mode 100644
index 0000000..1f6b03d
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValue.cpp
@@ -0,0 +1,633 @@
+//===-- OptionValue.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/OptionValue.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/StringList.h"
+#include "lldb/Interpreter/OptionValues.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+//-------------------------------------------------------------------------
+// Get this value as a uint64_t value if it is encoded as a boolean,
+// uint64_t or int64_t. Other types will cause "fail_value" to be
+// returned
+//-------------------------------------------------------------------------
+uint64_t
+OptionValue::GetUInt64Value (uint64_t fail_value, bool *success_ptr)
+{
+ if (success_ptr)
+ *success_ptr = true;
+ switch (GetType())
+ {
+ case OptionValue::eTypeBoolean: return static_cast<OptionValueBoolean *>(this)->GetCurrentValue();
+ case OptionValue::eTypeSInt64: return static_cast<OptionValueSInt64 *>(this)->GetCurrentValue();
+ case OptionValue::eTypeUInt64: return static_cast<OptionValueUInt64 *>(this)->GetCurrentValue();
+ default:
+ break;
+ }
+ if (success_ptr)
+ *success_ptr = false;
+ return fail_value;
+}
+
+Error
+OptionValue::SetSubValue (const ExecutionContext *exe_ctx,
+ VarSetOperationType op,
+ const char *name,
+ const char *value)
+{
+ Error error;
+ error.SetErrorStringWithFormat("SetSubValue is not supported");
+ return error;
+}
+
+
+OptionValueBoolean *
+OptionValue::GetAsBoolean ()
+{
+ if (GetType () == OptionValue::eTypeBoolean)
+ return static_cast<OptionValueBoolean *>(this);
+ return NULL;
+}
+
+const OptionValueBoolean *
+OptionValue::GetAsBoolean () const
+{
+ if (GetType () == OptionValue::eTypeBoolean)
+ return static_cast<const OptionValueBoolean *>(this);
+ return NULL;
+}
+
+
+OptionValueFileSpec *
+OptionValue::GetAsFileSpec ()
+{
+ if (GetType () == OptionValue::eTypeFileSpec)
+ return static_cast<OptionValueFileSpec *>(this);
+ return NULL;
+
+}
+
+const OptionValueFileSpec *
+OptionValue::GetAsFileSpec () const
+{
+ if (GetType () == OptionValue::eTypeFileSpec)
+ return static_cast<const OptionValueFileSpec *>(this);
+ return NULL;
+
+}
+
+OptionValueFileSpecList *
+OptionValue::GetAsFileSpecList ()
+{
+ if (GetType () == OptionValue::eTypeFileSpecList)
+ return static_cast<OptionValueFileSpecList *>(this);
+ return NULL;
+
+}
+
+const OptionValueFileSpecList *
+OptionValue::GetAsFileSpecList () const
+{
+ if (GetType () == OptionValue::eTypeFileSpecList)
+ return static_cast<const OptionValueFileSpecList *>(this);
+ return NULL;
+
+}
+
+OptionValueArch *
+OptionValue::GetAsArch ()
+{
+ if (GetType () == OptionValue::eTypeArch)
+ return static_cast<OptionValueArch *>(this);
+ return NULL;
+}
+
+
+const OptionValueArch *
+OptionValue::GetAsArch () const
+{
+ if (GetType () == OptionValue::eTypeArch)
+ return static_cast<const OptionValueArch *>(this);
+ return NULL;
+}
+
+OptionValueArray *
+OptionValue::GetAsArray ()
+{
+ if (GetType () == OptionValue::eTypeArray)
+ return static_cast<OptionValueArray *>(this);
+ return NULL;
+}
+
+
+const OptionValueArray *
+OptionValue::GetAsArray () const
+{
+ if (GetType () == OptionValue::eTypeArray)
+ return static_cast<const OptionValueArray *>(this);
+ return NULL;
+}
+
+OptionValueArgs *
+OptionValue::GetAsArgs ()
+{
+ if (GetType () == OptionValue::eTypeArgs)
+ return static_cast<OptionValueArgs *>(this);
+ return NULL;
+}
+
+
+const OptionValueArgs *
+OptionValue::GetAsArgs () const
+{
+ if (GetType () == OptionValue::eTypeArgs)
+ return static_cast<const OptionValueArgs *>(this);
+ return NULL;
+}
+
+OptionValueDictionary *
+OptionValue::GetAsDictionary ()
+{
+ if (GetType () == OptionValue::eTypeDictionary)
+ return static_cast<OptionValueDictionary *>(this);
+ return NULL;
+}
+
+const OptionValueDictionary *
+OptionValue::GetAsDictionary () const
+{
+ if (GetType () == OptionValue::eTypeDictionary)
+ return static_cast<const OptionValueDictionary *>(this);
+ return NULL;
+}
+
+OptionValueEnumeration *
+OptionValue::GetAsEnumeration ()
+{
+ if (GetType () == OptionValue::eTypeEnum)
+ return static_cast<OptionValueEnumeration *>(this);
+ return NULL;
+}
+
+const OptionValueEnumeration *
+OptionValue::GetAsEnumeration () const
+{
+ if (GetType () == OptionValue::eTypeEnum)
+ return static_cast<const OptionValueEnumeration *>(this);
+ return NULL;
+}
+
+OptionValueFormat *
+OptionValue::GetAsFormat ()
+{
+ if (GetType () == OptionValue::eTypeFormat)
+ return static_cast<OptionValueFormat *>(this);
+ return NULL;
+}
+
+const OptionValueFormat *
+OptionValue::GetAsFormat () const
+{
+ if (GetType () == OptionValue::eTypeFormat)
+ return static_cast<const OptionValueFormat *>(this);
+ return NULL;
+}
+
+OptionValuePathMappings *
+OptionValue::GetAsPathMappings ()
+{
+ if (GetType () == OptionValue::eTypePathMap)
+ return static_cast<OptionValuePathMappings *>(this);
+ return NULL;
+}
+
+const OptionValuePathMappings *
+OptionValue::GetAsPathMappings () const
+{
+ if (GetType () == OptionValue::eTypePathMap)
+ return static_cast<const OptionValuePathMappings *>(this);
+ return NULL;
+}
+
+OptionValueProperties *
+OptionValue::GetAsProperties ()
+{
+ if (GetType () == OptionValue::eTypeProperties)
+ return static_cast<OptionValueProperties *>(this);
+ return NULL;
+}
+
+const OptionValueProperties *
+OptionValue::GetAsProperties () const
+{
+ if (GetType () == OptionValue::eTypeProperties)
+ return static_cast<const OptionValueProperties *>(this);
+ return NULL;
+}
+
+OptionValueRegex *
+OptionValue::GetAsRegex ()
+{
+ if (GetType () == OptionValue::eTypeRegex)
+ return static_cast<OptionValueRegex *>(this);
+ return NULL;
+}
+
+const OptionValueRegex *
+OptionValue::GetAsRegex () const
+{
+ if (GetType () == OptionValue::eTypeRegex)
+ return static_cast<const OptionValueRegex *>(this);
+ return NULL;
+}
+
+OptionValueSInt64 *
+OptionValue::GetAsSInt64 ()
+{
+ if (GetType () == OptionValue::eTypeSInt64)
+ return static_cast<OptionValueSInt64 *>(this);
+ return NULL;
+}
+
+const OptionValueSInt64 *
+OptionValue::GetAsSInt64 () const
+{
+ if (GetType () == OptionValue::eTypeSInt64)
+ return static_cast<const OptionValueSInt64 *>(this);
+ return NULL;
+}
+
+OptionValueString *
+OptionValue::GetAsString ()
+{
+ if (GetType () == OptionValue::eTypeString)
+ return static_cast<OptionValueString *>(this);
+ return NULL;
+}
+
+const OptionValueString *
+OptionValue::GetAsString () const
+{
+ if (GetType () == OptionValue::eTypeString)
+ return static_cast<const OptionValueString *>(this);
+ return NULL;
+}
+
+OptionValueUInt64 *
+OptionValue::GetAsUInt64 ()
+{
+ if (GetType () == OptionValue::eTypeUInt64)
+ return static_cast<OptionValueUInt64 *>(this);
+ return NULL;
+}
+
+const OptionValueUInt64 *
+OptionValue::GetAsUInt64 () const
+{
+ if (GetType () == OptionValue::eTypeUInt64)
+ return static_cast<const OptionValueUInt64 *>(this);
+ return NULL;
+}
+
+OptionValueUUID *
+OptionValue::GetAsUUID ()
+{
+ if (GetType () == OptionValue::eTypeUUID)
+ return static_cast<OptionValueUUID *>(this);
+ return NULL;
+
+}
+
+const OptionValueUUID *
+OptionValue::GetAsUUID () const
+{
+ if (GetType () == OptionValue::eTypeUUID)
+ return static_cast<const OptionValueUUID *>(this);
+ return NULL;
+
+}
+
+bool
+OptionValue::GetBooleanValue (bool fail_value) const
+{
+ const OptionValueBoolean *option_value = GetAsBoolean ();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return fail_value;
+}
+
+bool
+OptionValue::SetBooleanValue (bool new_value)
+{
+ OptionValueBoolean *option_value = GetAsBoolean ();
+ if (option_value)
+ {
+ option_value->SetCurrentValue(new_value);
+ return true;
+ }
+ return false;
+}
+
+int64_t
+OptionValue::GetEnumerationValue (int64_t fail_value) const
+{
+ const OptionValueEnumeration *option_value = GetAsEnumeration();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return fail_value;
+}
+
+bool
+OptionValue::SetEnumerationValue (int64_t value)
+{
+ OptionValueEnumeration *option_value = GetAsEnumeration();
+ if (option_value)
+ {
+ option_value->SetCurrentValue(value);
+ return true;
+ }
+ return false;
+}
+
+FileSpec
+OptionValue::GetFileSpecValue () const
+{
+ const OptionValueFileSpec *option_value = GetAsFileSpec ();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return FileSpec();
+}
+
+
+bool
+OptionValue::SetFileSpecValue (const FileSpec &file_spec)
+{
+ OptionValueFileSpec *option_value = GetAsFileSpec ();
+ if (option_value)
+ {
+ option_value->SetCurrentValue(file_spec, false);
+ return true;
+ }
+ return false;
+}
+
+FileSpecList
+OptionValue::GetFileSpecListValue () const
+{
+ const OptionValueFileSpecList *option_value = GetAsFileSpecList ();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return FileSpecList();
+}
+
+
+lldb::Format
+OptionValue::GetFormatValue (lldb::Format fail_value) const
+{
+ const OptionValueFormat *option_value = GetAsFormat ();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return fail_value;
+}
+
+bool
+OptionValue::SetFormatValue (lldb::Format new_value)
+{
+ OptionValueFormat *option_value = GetAsFormat ();
+ if (option_value)
+ {
+ option_value->SetCurrentValue(new_value);
+ return true;
+ }
+ return false;
+}
+
+const RegularExpression *
+OptionValue::GetRegexValue () const
+{
+ const OptionValueRegex *option_value = GetAsRegex ();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return NULL;
+}
+
+
+int64_t
+OptionValue::GetSInt64Value (int64_t fail_value) const
+{
+ const OptionValueSInt64 *option_value = GetAsSInt64 ();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return fail_value;
+}
+
+bool
+OptionValue::SetSInt64Value (int64_t new_value)
+{
+ OptionValueSInt64 *option_value = GetAsSInt64 ();
+ if (option_value)
+ {
+ option_value->SetCurrentValue(new_value);
+ return true;
+ }
+ return false;
+}
+
+const char *
+OptionValue::GetStringValue (const char *fail_value) const
+{
+ const OptionValueString *option_value = GetAsString ();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return fail_value;
+}
+
+bool
+OptionValue::SetStringValue (const char *new_value)
+{
+ OptionValueString *option_value = GetAsString ();
+ if (option_value)
+ {
+ option_value->SetCurrentValue(new_value);
+ return true;
+ }
+ return false;
+}
+
+uint64_t
+OptionValue::GetUInt64Value (uint64_t fail_value) const
+{
+ const OptionValueUInt64 *option_value = GetAsUInt64 ();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return fail_value;
+}
+
+bool
+OptionValue::SetUInt64Value (uint64_t new_value)
+{
+ OptionValueUInt64 *option_value = GetAsUInt64 ();
+ if (option_value)
+ {
+ option_value->SetCurrentValue(new_value);
+ return true;
+ }
+ return false;
+}
+
+UUID
+OptionValue::GetUUIDValue () const
+{
+ const OptionValueUUID *option_value = GetAsUUID();
+ if (option_value)
+ return option_value->GetCurrentValue();
+ return UUID();
+}
+
+bool
+OptionValue::SetUUIDValue (const UUID &uuid)
+{
+ OptionValueUUID *option_value = GetAsUUID();
+ if (option_value)
+ {
+ option_value->SetCurrentValue(uuid);
+ return true;
+ }
+ return false;
+}
+
+const char *
+OptionValue::GetBuiltinTypeAsCString (Type t)
+{
+ switch (t)
+ {
+ case eTypeInvalid: return "invalid";
+ case eTypeArch: return "arch";
+ case eTypeArgs: return "arguments";
+ case eTypeArray: return "array";
+ case eTypeBoolean: return "boolean";
+ case eTypeDictionary: return "dictionary";
+ case eTypeEnum: return "enum";
+ case eTypeFileSpec: return "file";
+ case eTypeFileSpecList: return "file-list";
+ case eTypeFormat: return "format";
+ case eTypePathMap: return "path-map";
+ case eTypeProperties: return "properties";
+ case eTypeRegex: return "regex";
+ case eTypeSInt64: return "int";
+ case eTypeString: return "string";
+ case eTypeUInt64: return "unsigned";
+ case eTypeUUID: return "uuid";
+ }
+ return NULL;
+}
+
+
+lldb::OptionValueSP
+OptionValue::CreateValueFromCStringForTypeMask (const char *value_cstr, uint32_t type_mask, Error &error)
+{
+ // If only 1 bit is set in the type mask for a dictionary or array
+ // then we know how to decode a value from a cstring
+ lldb::OptionValueSP value_sp;
+ switch (type_mask)
+ {
+ case 1u << eTypeArch: value_sp.reset(new OptionValueArch()); break;
+ case 1u << eTypeBoolean: value_sp.reset(new OptionValueBoolean(false)); break;
+ case 1u << eTypeFileSpec: value_sp.reset(new OptionValueFileSpec()); break;
+ case 1u << eTypeFormat: value_sp.reset(new OptionValueFormat(eFormatInvalid)); break;
+ case 1u << eTypeSInt64: value_sp.reset(new OptionValueSInt64()); break;
+ case 1u << eTypeString: value_sp.reset(new OptionValueString()); break;
+ case 1u << eTypeUInt64: value_sp.reset(new OptionValueUInt64()); break;
+ case 1u << eTypeUUID: value_sp.reset(new OptionValueUUID()); break;
+ }
+
+ if (value_sp)
+ error = value_sp->SetValueFromCString (value_cstr, eVarSetOperationAssign);
+ else
+ error.SetErrorString("unsupported type mask");
+ return value_sp;
+}
+
+bool
+OptionValue::DumpQualifiedName (Stream &strm) const
+{
+ bool dumped_something = false;
+ lldb::OptionValueSP m_parent_sp(m_parent_wp.lock());
+ if (m_parent_sp)
+ {
+ if (m_parent_sp->DumpQualifiedName(strm))
+ dumped_something = true;
+ }
+ ConstString name (GetName());
+ if (name)
+ {
+ if (dumped_something)
+ strm.PutChar('.');
+ else
+ dumped_something = true;
+ strm << name;
+ }
+ return dumped_something;
+}
+
+size_t
+OptionValue::AutoComplete (CommandInterpreter &interpreter,
+ const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+{
+ word_complete = false;
+ matches.Clear();
+ return matches.GetSize();
+}
+
+Error
+OptionValue::SetValueFromCString (const char *value, VarSetOperationType op)
+{
+ Error error;
+ switch (op)
+ {
+ case eVarSetOperationReplace:
+ error.SetErrorStringWithFormat ("%s objects do not support the 'replace' operation", GetTypeAsCString());
+ break;
+ case eVarSetOperationInsertBefore:
+ error.SetErrorStringWithFormat ("%s objects do not support the 'insert-before' operation", GetTypeAsCString());
+ break;
+ case eVarSetOperationInsertAfter:
+ error.SetErrorStringWithFormat ("%s objects do not support the 'insert-after' operation", GetTypeAsCString());
+ break;
+ case eVarSetOperationRemove:
+ error.SetErrorStringWithFormat ("%s objects do not support the 'remove' operation", GetTypeAsCString());
+ break;
+ case eVarSetOperationAppend:
+ error.SetErrorStringWithFormat ("%s objects do not support the 'append' operation", GetTypeAsCString());
+ break;
+ case eVarSetOperationClear:
+ error.SetErrorStringWithFormat ("%s objects do not support the 'clear' operation", GetTypeAsCString());
+ break;
+ case eVarSetOperationAssign:
+ error.SetErrorStringWithFormat ("%s objects do not support the 'assign' operation", GetTypeAsCString());
+ break;
+ case eVarSetOperationInvalid:
+ error.SetErrorStringWithFormat ("invalid operation performed on a %s object", GetTypeAsCString());
+ break;
+ }
+ return error;
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArch.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArch.cpp
new file mode 100644
index 0000000..92fedff
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArch.cpp
@@ -0,0 +1,111 @@
+//===-- OptionValueArch.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Interpreter/OptionValueArch.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/State.h"
+#include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+OptionValueArch::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ if (dump_mask & eDumpOptionType)
+ strm.Printf ("(%s)", GetTypeAsCString ());
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.PutCString (" = ");
+
+ if (m_current_value.IsValid())
+ {
+ const char *arch_name = m_current_value.GetArchitectureName();
+ if (arch_name)
+ strm.PutCString (arch_name);
+ }
+ }
+}
+
+Error
+OptionValueArch::SetValueFromCString (const char *value_cstr, VarSetOperationType op)
+{
+ Error error;
+ switch (op)
+ {
+ case eVarSetOperationClear:
+ Clear();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign:
+ if (value_cstr && value_cstr[0])
+ {
+ if (m_current_value.SetTriple (value_cstr))
+ m_value_was_set = true;
+ else
+ error.SetErrorStringWithFormat("unsupported architecture '%s'", value_cstr);
+ }
+ else
+ {
+ error.SetErrorString("invalid value string");
+ }
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationRemove:
+ case eVarSetOperationAppend:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromCString (value_cstr, op);
+ break;
+ }
+ return error;
+}
+
+lldb::OptionValueSP
+OptionValueArch::DeepCopy () const
+{
+ return OptionValueSP(new OptionValueArch(*this));
+}
+
+
+size_t
+OptionValueArch::AutoComplete (CommandInterpreter &interpreter,
+ const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+{
+ word_complete = false;
+ matches.Clear();
+ CommandCompletions::InvokeCommonCompletionCallbacks (interpreter,
+ CommandCompletions::eArchitectureCompletion,
+ s,
+ match_start_point,
+ max_return_elements,
+ NULL,
+ word_complete,
+ matches);
+ return matches.GetSize();
+}
+
+
+
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArgs.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArgs.cpp
new file mode 100644
index 0000000..e28d884
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArgs.cpp
@@ -0,0 +1,38 @@
+//===-- OptionValueArgs.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/OptionValueArgs.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/Args.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+size_t
+OptionValueArgs::GetArgs (Args &args)
+{
+ const uint32_t size = m_values.size();
+ std::vector<const char *> argv;
+ for (uint32_t i = 0; i<size; ++i)
+ {
+ const char *string_value = m_values[i]->GetStringValue ();
+ if (string_value)
+ argv.push_back(string_value);
+ }
+
+ if (argv.empty())
+ args.Clear();
+ else
+ args.SetArguments(argv.size(), &argv[0]);
+ return args.GetArgumentCount();
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArray.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArray.cpp
new file mode 100644
index 0000000..9a01558
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueArray.cpp
@@ -0,0 +1,350 @@
+//===-- OptionValueArray.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/OptionValueArray.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+#include "lldb/Interpreter/Args.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+OptionValueArray::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ const Type array_element_type = ConvertTypeMaskToType (m_type_mask);
+ if (dump_mask & eDumpOptionType)
+ {
+ if ((GetType() == eTypeArray) && (m_type_mask != eTypeInvalid))
+ strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(array_element_type));
+ else
+ strm.Printf ("(%s)", GetTypeAsCString());
+ }
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.Printf (" =%s", (m_values.size() > 0) ? "\n" : "");
+ strm.IndentMore();
+ const uint32_t size = m_values.size();
+ for (uint32_t i = 0; i<size; ++i)
+ {
+ strm.Indent();
+ strm.Printf("[%u]: ", i);
+ const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
+ switch (array_element_type)
+ {
+ default:
+ case eTypeArray:
+ case eTypeDictionary:
+ case eTypeProperties:
+ case eTypeFileSpecList:
+ case eTypePathMap:
+ m_values[i]->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
+ break;
+
+ case eTypeBoolean:
+ case eTypeEnum:
+ case eTypeFileSpec:
+ case eTypeFormat:
+ case eTypeSInt64:
+ case eTypeString:
+ case eTypeUInt64:
+ case eTypeUUID:
+ // No need to show the type for dictionaries of simple items
+ m_values[i]->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options);
+ break;
+ }
+ if (i < (size - 1))
+ strm.EOL();
+ }
+ strm.IndentLess();
+ }
+}
+
+Error
+OptionValueArray::SetValueFromCString (const char *value, VarSetOperationType op)
+{
+ Args args(value);
+ return SetArgs (args, op);
+}
+
+
+lldb::OptionValueSP
+OptionValueArray::GetSubValue (const ExecutionContext *exe_ctx,
+ const char *name,
+ bool will_modify,
+ Error &error) const
+{
+ if (name && name[0] == '[')
+ {
+ const char *end_bracket = strchr (name+1, ']');
+ if (end_bracket)
+ {
+ const char *sub_value = NULL;
+ if (end_bracket[1])
+ sub_value = end_bracket + 1;
+ std::string index_str (name+1, end_bracket);
+ const size_t array_count = m_values.size();
+ int32_t idx = Args::StringToSInt32(index_str.c_str(), INT32_MAX, 0, NULL);
+ if (idx != INT32_MAX)
+ {
+ ;
+ uint32_t new_idx = UINT32_MAX;
+ if (idx < 0)
+ {
+ // Access from the end of the array if the index is negative
+ new_idx = array_count - idx;
+ }
+ else
+ {
+ // Just a standard index
+ new_idx = idx;
+ }
+
+ if (new_idx < array_count)
+ {
+ if (m_values[new_idx])
+ {
+ if (sub_value)
+ return m_values[new_idx]->GetSubValue (exe_ctx, sub_value, will_modify, error);
+ else
+ return m_values[new_idx];
+ }
+ }
+ else
+ {
+ if (array_count == 0)
+ error.SetErrorStringWithFormat("index %i is not valid for an empty array", idx);
+ else if (idx > 0)
+ error.SetErrorStringWithFormat("index %i out of range, valid values are 0 through %" PRIu64, idx, (uint64_t)(array_count - 1));
+ else
+ error.SetErrorStringWithFormat("negative index %i out of range, valid values are -1 through -%" PRIu64, idx, (uint64_t)array_count);
+ }
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("invalid value path '%s', %s values only support '[<index>]' subvalues where <index> is a positive or negative array index", name, GetTypeAsCString());
+ }
+ return OptionValueSP();
+}
+
+
+size_t
+OptionValueArray::GetArgs (Args &args) const
+{
+ const uint32_t size = m_values.size();
+ std::vector<const char *> argv;
+ for (uint32_t i = 0; i<size; ++i)
+ {
+ const char *string_value = m_values[i]->GetStringValue ();
+ if (string_value)
+ argv.push_back(string_value);
+ }
+
+ if (argv.empty())
+ args.Clear();
+ else
+ args.SetArguments(argv.size(), &argv[0]);
+ return args.GetArgumentCount();
+}
+
+Error
+OptionValueArray::SetArgs (const Args &args, VarSetOperationType op)
+{
+ Error error;
+ const size_t argc = args.GetArgumentCount();
+ switch (op)
+ {
+ case eVarSetOperationInvalid:
+ error.SetErrorString("unsupported operation");
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ if (argc > 1)
+ {
+ uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
+ const uint32_t count = GetSize();
+ if (idx > count)
+ {
+ error.SetErrorStringWithFormat("invalid insert array index %u, index must be 0 through %u", idx, count);
+ }
+ else
+ {
+ if (op == eVarSetOperationInsertAfter)
+ ++idx;
+ for (size_t i=1; i<argc; ++i, ++idx)
+ {
+ lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
+ m_type_mask,
+ error));
+ if (value_sp)
+ {
+ if (error.Fail())
+ return error;
+ if (idx >= m_values.size())
+ m_values.push_back(value_sp);
+ else
+ m_values.insert(m_values.begin() + idx, value_sp);
+ }
+ else
+ {
+ error.SetErrorString("array of complex types must subclass OptionValueArray");
+ return error;
+ }
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("insert operation takes an array index followed by one or more values");
+ }
+ break;
+
+ case eVarSetOperationRemove:
+ if (argc > 0)
+ {
+ const uint32_t size = m_values.size();
+ std::vector<int> remove_indexes;
+ bool all_indexes_valid = true;
+ size_t i;
+ for (i=0; i<argc; ++i)
+ {
+ const int idx = Args::StringToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
+ if (idx >= size)
+ {
+ all_indexes_valid = false;
+ break;
+ }
+ else
+ remove_indexes.push_back(idx);
+ }
+
+ if (all_indexes_valid)
+ {
+ size_t num_remove_indexes = remove_indexes.size();
+ if (num_remove_indexes)
+ {
+ // Sort and then erase in reverse so indexes are always valid
+ if (num_remove_indexes > 1)
+ {
+ std::sort(remove_indexes.begin(), remove_indexes.end());
+ for (std::vector<int>::const_reverse_iterator pos = remove_indexes.rbegin(), end = remove_indexes.rend(); pos != end; ++pos)
+ {
+ m_values.erase(m_values.begin() + *pos);
+ }
+ }
+ else
+ {
+ // Only one index
+ m_values.erase(m_values.begin() + remove_indexes.front());
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i));
+ }
+ }
+ else
+ {
+ error.SetErrorString("remove operation takes one or more array indices");
+ }
+ break;
+
+ case eVarSetOperationClear:
+ Clear ();
+ break;
+
+ case eVarSetOperationReplace:
+ if (argc > 1)
+ {
+ uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
+ const uint32_t count = GetSize();
+ if (idx > count)
+ {
+ error.SetErrorStringWithFormat("invalid replace array index %u, index must be 0 through %u", idx, count);
+ }
+ else
+ {
+ for (size_t i=1; i<argc; ++i, ++idx)
+ {
+ lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
+ m_type_mask,
+ error));
+ if (value_sp)
+ {
+ if (error.Fail())
+ return error;
+ if (idx < count)
+ m_values[idx] = value_sp;
+ else
+ m_values.push_back(value_sp);
+ }
+ else
+ {
+ error.SetErrorString("array of complex types must subclass OptionValueArray");
+ return error;
+ }
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("replace operation takes an array index followed by one or more values");
+ }
+ break;
+
+ case eVarSetOperationAssign:
+ m_values.clear();
+ // Fall through to append case
+ case eVarSetOperationAppend:
+ for (size_t i=0; i<argc; ++i)
+ {
+ lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
+ m_type_mask,
+ error));
+ if (value_sp)
+ {
+ if (error.Fail())
+ return error;
+ m_value_was_set = true;
+ AppendValue(value_sp);
+ }
+ else
+ {
+ error.SetErrorString("array of complex types must subclass OptionValueArray");
+ }
+ }
+ break;
+ }
+ return error;
+}
+
+lldb::OptionValueSP
+OptionValueArray::DeepCopy () const
+{
+ OptionValueArray *copied_array = new OptionValueArray (m_type_mask, m_raw_value_dump);
+ lldb::OptionValueSP copied_value_sp(copied_array);
+ const uint32_t size = m_values.size();
+ for (uint32_t i = 0; i<size; ++i)
+ {
+ copied_array->AppendValue (m_values[i]->DeepCopy());
+ }
+ return copied_value_sp;
+}
+
+
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueBoolean.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueBoolean.cpp
new file mode 100644
index 0000000..6471943
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueBoolean.cpp
@@ -0,0 +1,135 @@
+//===-- OptionValueBoolean.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/OptionValueBoolean.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Interpreter/Args.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+OptionValueBoolean::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ if (dump_mask & eDumpOptionType)
+ strm.Printf ("(%s)", GetTypeAsCString ());
+// if (dump_mask & eDumpOptionName)
+// DumpQualifiedName (strm);
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.PutCString (" = ");
+ strm.PutCString (m_current_value ? "true" : "false");
+ }
+}
+
+Error
+OptionValueBoolean::SetValueFromCString (const char *value_cstr,
+ VarSetOperationType op)
+{
+ Error error;
+ switch (op)
+ {
+ case eVarSetOperationClear:
+ Clear();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign:
+ {
+ bool success = false;
+ bool value = Args::StringToBoolean(value_cstr, false, &success);
+ if (success)
+ {
+ m_value_was_set = true;
+ m_current_value = value;
+ }
+ else
+ {
+ if (value_cstr == NULL)
+ error.SetErrorString ("invalid boolean string value: NULL");
+ else if (value_cstr[0] == '\0')
+ error.SetErrorString ("invalid boolean string value <empty>");
+ else
+ error.SetErrorStringWithFormat ("invalid boolean string value: '%s'", value_cstr);
+ }
+ }
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationRemove:
+ case eVarSetOperationAppend:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromCString (value_cstr, op);
+ break;
+ }
+ return error;
+}
+
+lldb::OptionValueSP
+OptionValueBoolean::DeepCopy () const
+{
+ return OptionValueSP(new OptionValueBoolean(*this));
+}
+
+size_t
+OptionValueBoolean::AutoComplete (CommandInterpreter &interpreter,
+ const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+{
+ word_complete = false;
+ matches.Clear();
+ struct StringEntry {
+ const char *string;
+ const size_t length;
+ };
+ static const StringEntry g_autocomplete_entries[] =
+ {
+ { "true" , 4 },
+ { "false", 5 },
+ { "on" , 2 },
+ { "off" , 3 },
+ { "yes" , 3 },
+ { "no" , 2 },
+ { "1" , 1 },
+ { "0" , 1 },
+ };
+ const size_t k_num_autocomplete_entries = sizeof(g_autocomplete_entries)/sizeof(StringEntry);
+
+ if (s && s[0])
+ {
+ const size_t s_len = strlen(s);
+ for (size_t i=0; i<k_num_autocomplete_entries; ++i)
+ {
+ if (s_len <= g_autocomplete_entries[i].length)
+ if (::strncasecmp(s, g_autocomplete_entries[i].string, s_len) == 0)
+ matches.AppendString(g_autocomplete_entries[i].string);
+ }
+ }
+ else
+ {
+ // only suggest "true" or "false" by default
+ for (size_t i=0; i<2; ++i)
+ matches.AppendString(g_autocomplete_entries[i].string);
+ }
+ return matches.GetSize();
+}
+
+
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp
new file mode 100644
index 0000000..61f8aba
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueDictionary.cpp
@@ -0,0 +1,436 @@
+//===-- OptionValueDictionary.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Interpreter/OptionValueDictionary.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/ADT/StringRef.h"
+// Project includes
+#include "lldb/Core/State.h"
+#include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/OptionValueString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+OptionValueDictionary::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ const Type dict_type = ConvertTypeMaskToType (m_type_mask);
+ if (dump_mask & eDumpOptionType)
+ {
+ if (m_type_mask != eTypeInvalid)
+ strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(dict_type));
+ else
+ strm.Printf ("(%s)", GetTypeAsCString());
+ }
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.PutCString (" =");
+
+ collection::iterator pos, end = m_values.end();
+
+ strm.IndentMore();
+
+ for (pos = m_values.begin(); pos != end; ++pos)
+ {
+ OptionValue *option_value = pos->second.get();
+ strm.EOL();
+ strm.Indent(pos->first.GetCString());
+
+ const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
+ switch (dict_type)
+ {
+ default:
+ case eTypeArray:
+ case eTypeDictionary:
+ case eTypeProperties:
+ case eTypeFileSpecList:
+ case eTypePathMap:
+ strm.PutChar (' ');
+ option_value->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
+ break;
+
+ case eTypeBoolean:
+ case eTypeEnum:
+ case eTypeFileSpec:
+ case eTypeFormat:
+ case eTypeSInt64:
+ case eTypeString:
+ case eTypeUInt64:
+ case eTypeUUID:
+ // No need to show the type for dictionaries of simple items
+ strm.PutCString("=");
+ option_value->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options);
+ break;
+ }
+ }
+ strm.IndentLess();
+ }
+
+}
+
+size_t
+OptionValueDictionary::GetArgs (Args &args) const
+{
+ args.Clear();
+ collection::const_iterator pos, end = m_values.end();
+ for (pos = m_values.begin(); pos != end; ++pos)
+ {
+ StreamString strm;
+ strm.Printf("%s=", pos->first.GetCString());
+ pos->second->DumpValue(NULL, strm, eDumpOptionValue|eDumpOptionRaw);
+ args.AppendArgument(strm.GetString().c_str());
+ }
+ return args.GetArgumentCount();
+}
+
+Error
+OptionValueDictionary::SetArgs (const Args &args, VarSetOperationType op)
+{
+ Error error;
+ const size_t argc = args.GetArgumentCount();
+ switch (op)
+ {
+ case eVarSetOperationClear:
+ Clear();
+ break;
+
+ case eVarSetOperationAppend:
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign:
+ if (argc > 0)
+ {
+ for (size_t i=0; i<argc; ++i)
+ {
+ llvm::StringRef key_and_value(args.GetArgumentAtIndex(i));
+ if (!key_and_value.empty())
+ {
+ std::pair<llvm::StringRef, llvm::StringRef> kvp(key_and_value.split('='));
+ llvm::StringRef key = kvp.first;
+ bool key_valid = false;
+ if (!key.empty())
+ {
+ if (key.front() == '[')
+ {
+ // Key name starts with '[', so the the key value must be in single or double quotes like:
+ // ['<key>']
+ // ["<key>"]
+ if ((key.size() > 2) && (key.back() == ']'))
+ {
+ // Strip leading '[' and trailing ']'
+ key = key.substr(1, key.size()-2);
+ const char quote_char = key.front();
+ if ((quote_char == '\'') || (quote_char == '"'))
+ {
+ if ((key.size() > 2) && (key.back() == quote_char))
+ {
+ // Strip the quotes
+ key = key.substr(1, key.size()-2);
+ key_valid = true;
+ }
+ }
+ else
+ {
+ // square brackets, no quotes
+ key_valid = true;
+ }
+ }
+ }
+ else
+ {
+ // No square brackets or quotes
+ key_valid = true;
+ }
+ }
+ if (!key_valid)
+ {
+ error.SetErrorStringWithFormat("invalid key \"%s\", the key must be a bare string or surrounded by brackets with optional quotes: [<key>] or ['<key>'] or [\"<key>\"]", kvp.first.str().c_str());
+ return error;
+ }
+
+ lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (kvp.second.data(),
+ m_type_mask,
+ error));
+ if (value_sp)
+ {
+ if (error.Fail())
+ return error;
+ m_value_was_set = true;
+ SetValueForKey (ConstString(key), value_sp, true);
+ }
+ else
+ {
+ error.SetErrorString("dictionaries that can contain multiple types must subclass OptionValueArray");
+ }
+ }
+ else
+ {
+ error.SetErrorString("empty argument");
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("assign operation takes one or more key=value arguments");
+ }
+ break;
+
+ case eVarSetOperationRemove:
+ if (argc > 0)
+ {
+ for (size_t i=0; i<argc; ++i)
+ {
+ ConstString key(args.GetArgumentAtIndex(i));
+ if (!DeleteValueForKey(key))
+ {
+ error.SetErrorStringWithFormat("no value found named '%s', aborting remove operation", key.GetCString());
+ break;
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("remove operation takes one or more key arguments");
+ }
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromCString (NULL, op);
+ break;
+ }
+ return error;
+}
+
+Error
+OptionValueDictionary::SetValueFromCString (const char *value_cstr, VarSetOperationType op)
+{
+ Args args(value_cstr);
+ return SetArgs (args, op);
+}
+
+lldb::OptionValueSP
+OptionValueDictionary::GetSubValue (const ExecutionContext *exe_ctx, const char *name, bool will_modify, Error &error) const
+{
+ lldb::OptionValueSP value_sp;
+
+ if (name && name[0])
+ {
+ const char *sub_name = NULL;
+ ConstString key;
+ const char *open_bracket = ::strchr (name, '[');
+
+ if (open_bracket)
+ {
+ const char *key_start = open_bracket + 1;
+ const char *key_end = NULL;
+ switch (open_bracket[1])
+ {
+ case '\'':
+ ++key_start;
+ key_end = strchr(key_start, '\'');
+ if (key_end)
+ {
+ if (key_end[1] == ']')
+ {
+ if (key_end[2])
+ sub_name = key_end + 2;
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("invalid value path '%s', single quoted key names must be formatted as ['<key>'] where <key> is a string that doesn't contain quotes", name);
+ return value_sp;
+ }
+ }
+ else
+ {
+ error.SetErrorString ("missing '] key name terminator, key name started with ['");
+ return value_sp;
+ }
+ break;
+ case '"':
+ ++key_start;
+ key_end = strchr(key_start, '"');
+ if (key_end)
+ {
+ if (key_end[1] == ']')
+ {
+ if (key_end[2])
+ sub_name = key_end + 2;
+ break;
+ }
+ error.SetErrorStringWithFormat ("invalid value path '%s', double quoted key names must be formatted as [\"<key>\"] where <key> is a string that doesn't contain quotes", name);
+ return value_sp;
+ }
+ else
+ {
+ error.SetErrorString ("missing \"] key name terminator, key name started with [\"");
+ return value_sp;
+ }
+ break;
+
+ default:
+ key_end = strchr(key_start, ']');
+ if (key_end)
+ {
+ if (key_end[1])
+ sub_name = key_end + 1;
+ }
+ else
+ {
+ error.SetErrorString ("missing ] key name terminator, key name started with [");
+ return value_sp;
+ }
+ break;
+ }
+
+ if (key_start && key_end)
+ {
+ key.SetCStringWithLength (key_start, key_end - key_start);
+
+ value_sp = GetValueForKey (key);
+ if (value_sp)
+ {
+ if (sub_name)
+ return value_sp->GetSubValue (exe_ctx, sub_name, will_modify, error);
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("dictionary does not contain a value for the key name '%s'", key.GetCString());
+ }
+ }
+ }
+ if (!value_sp && error.AsCString() == NULL)
+ {
+ error.SetErrorStringWithFormat ("invalid value path '%s', %s values only support '[<key>]' subvalues where <key> a string value optionally delimitted by single or double quotes",
+ name,
+ GetTypeAsCString());
+ }
+ }
+ return value_sp;
+}
+
+Error
+OptionValueDictionary::SetSubValue (const ExecutionContext *exe_ctx, VarSetOperationType op, const char *name, const char *value)
+{
+ Error error;
+ const bool will_modify = true;
+ lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error));
+ if (value_sp)
+ error = value_sp->SetValueFromCString(value, op);
+ else
+ {
+ if (error.AsCString() == NULL)
+ error.SetErrorStringWithFormat("invalid value path '%s'", name);
+ }
+ return error;
+}
+
+
+lldb::OptionValueSP
+OptionValueDictionary::GetValueForKey (const ConstString &key) const
+{
+ lldb::OptionValueSP value_sp;
+ collection::const_iterator pos = m_values.find (key);
+ if (pos != m_values.end())
+ value_sp = pos->second;
+ return value_sp;
+}
+
+const char *
+OptionValueDictionary::GetStringValueForKey (const ConstString &key)
+{
+ collection::const_iterator pos = m_values.find (key);
+ if (pos != m_values.end())
+ {
+ OptionValueString *string_value = pos->second->GetAsString();
+ if (string_value)
+ return string_value->GetCurrentValue();
+ }
+ return NULL;
+}
+
+
+bool
+OptionValueDictionary::SetStringValueForKey (const ConstString &key,
+ const char *value,
+ bool can_replace)
+{
+ collection::const_iterator pos = m_values.find (key);
+ if (pos != m_values.end())
+ {
+ if (!can_replace)
+ return false;
+ if (pos->second->GetType() == OptionValue::eTypeString)
+ {
+ pos->second->SetValueFromCString(value);
+ return true;
+ }
+ }
+ m_values[key] = OptionValueSP (new OptionValueString (value));
+ return true;
+
+}
+
+bool
+OptionValueDictionary::SetValueForKey (const ConstString &key,
+ const lldb::OptionValueSP &value_sp,
+ bool can_replace)
+{
+ // Make sure the value_sp object is allowed to contain
+ // values of the type passed in...
+ if (value_sp && (m_type_mask & value_sp->GetTypeAsMask()))
+ {
+ if (!can_replace)
+ {
+ collection::const_iterator pos = m_values.find (key);
+ if (pos != m_values.end())
+ return false;
+ }
+ m_values[key] = value_sp;
+ return true;
+ }
+ return false;
+}
+
+bool
+OptionValueDictionary::DeleteValueForKey (const ConstString &key)
+{
+ collection::iterator pos = m_values.find (key);
+ if (pos != m_values.end())
+ {
+ m_values.erase(pos);
+ return true;
+ }
+ return false;
+}
+
+lldb::OptionValueSP
+OptionValueDictionary::DeepCopy () const
+{
+ OptionValueDictionary *copied_dict = new OptionValueDictionary (m_type_mask, m_raw_value_dump);
+ lldb::OptionValueSP copied_value_sp(copied_dict);
+ collection::const_iterator pos, end = m_values.end();
+ for (pos = m_values.begin(); pos != end; ++pos)
+ {
+ StreamString strm;
+ strm.Printf("%s=", pos->first.GetCString());
+ copied_dict->SetValueForKey (pos->first, pos->second->DeepCopy(), true);
+ }
+ return copied_value_sp;
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueEnumeration.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueEnumeration.cpp
new file mode 100644
index 0000000..f282235
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueEnumeration.cpp
@@ -0,0 +1,166 @@
+//===-- OptionValueEnumeration.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/OptionValueEnumeration.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/StringList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+OptionValueEnumeration::OptionValueEnumeration (const OptionEnumValueElement *enumerators,
+ enum_type value) :
+ OptionValue(),
+ m_current_value (value),
+ m_default_value (value),
+ m_enumerations ()
+{
+ SetEnumerations(enumerators);
+}
+
+OptionValueEnumeration::~OptionValueEnumeration()
+{
+}
+
+void
+OptionValueEnumeration::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ if (dump_mask & eDumpOptionType)
+ strm.Printf ("(%s)", GetTypeAsCString ());
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.PutCString (" = ");
+ const size_t count = m_enumerations.GetSize ();
+ for (size_t i=0; i<count; ++i)
+ {
+ if (m_enumerations.GetValueAtIndexUnchecked(i).value == m_current_value)
+ {
+ strm.PutCString(m_enumerations.GetCStringAtIndex(i));
+ return;
+ }
+ }
+ strm.Printf("%" PRIu64, (uint64_t)m_current_value);
+ }
+}
+
+Error
+OptionValueEnumeration::SetValueFromCString (const char *value, VarSetOperationType op)
+{
+ Error error;
+ switch (op)
+ {
+ case eVarSetOperationClear:
+ Clear ();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign:
+ if (value && value[0])
+ {
+ ConstString const_enumerator_name(value);
+ const EnumerationMapEntry *enumerator_entry = m_enumerations.FindFirstValueForName (const_enumerator_name.GetCString());
+ if (enumerator_entry)
+ {
+ m_current_value = enumerator_entry->value.value;
+ }
+ else
+ {
+ StreamString error_strm;
+ error_strm.Printf("invalid enumeration value '%s'", value);
+ const size_t count = m_enumerations.GetSize ();
+ if (count)
+ {
+ error_strm.Printf(", valid values are: %s", m_enumerations.GetCStringAtIndex(0));
+ for (size_t i=1; i<count; ++i)
+ {
+ error_strm.Printf (", %s", m_enumerations.GetCStringAtIndex(i));
+ }
+ }
+ error.SetErrorString(error_strm.GetData());
+ }
+ }
+ else
+ {
+ error.SetErrorString("invalid enumeration value");
+ }
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationRemove:
+ case eVarSetOperationAppend:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromCString (value, op);
+ break;
+ }
+ return error;
+}
+
+void
+OptionValueEnumeration::SetEnumerations (const OptionEnumValueElement *enumerators)
+{
+ m_enumerations.Clear();
+ if (enumerators)
+ {
+ for (size_t i=0; enumerators[i].string_value != NULL; ++i)
+ {
+ ConstString const_enumerator_name(enumerators[i].string_value);
+ EnumeratorInfo enumerator_info = { enumerators[i].value, enumerators[i].usage };
+ m_enumerations.Append (const_enumerator_name.GetCString(), enumerator_info);
+ }
+ m_enumerations.Sort();
+ }
+}
+
+
+lldb::OptionValueSP
+OptionValueEnumeration::DeepCopy () const
+{
+ return OptionValueSP(new OptionValueEnumeration(*this));
+}
+
+size_t
+OptionValueEnumeration::AutoComplete (CommandInterpreter &interpreter,
+ const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+{
+ word_complete = false;
+ matches.Clear();
+
+ const uint32_t num_enumerators = m_enumerations.GetSize();
+ if (s && s[0])
+ {
+ const size_t s_len = strlen(s);
+ for (size_t i=0; i<num_enumerators; ++i)
+ {
+ const char *name = m_enumerations.GetCStringAtIndex(i);
+ if (::strncmp(s, name, s_len) == 0)
+ matches.AppendString(name);
+ }
+ }
+ else
+ {
+ // only suggest "true" or "false" by default
+ for (size_t i=0; i<num_enumerators; ++i)
+ matches.AppendString(m_enumerations.GetCStringAtIndex(i));
+ }
+ return matches.GetSize();
+}
+
+
+
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpec.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpec.cpp
new file mode 100644
index 0000000..e56b48b
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpec.cpp
@@ -0,0 +1,159 @@
+//===-- OptionValueFileSpec.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Interpreter/OptionValueFileSpec.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/State.h"
+#include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+OptionValueFileSpec::OptionValueFileSpec () :
+ OptionValue(),
+ m_current_value (),
+ m_default_value (),
+ m_data_sp(),
+ m_completion_mask (CommandCompletions::eDiskFileCompletion)
+{
+}
+
+OptionValueFileSpec::OptionValueFileSpec (const FileSpec &value) :
+ OptionValue(),
+ m_current_value (value),
+ m_default_value (value),
+ m_data_sp(),
+ m_completion_mask (CommandCompletions::eDiskFileCompletion)
+{
+}
+
+OptionValueFileSpec::OptionValueFileSpec (const FileSpec &current_value,
+ const FileSpec &default_value) :
+ OptionValue(),
+ m_current_value (current_value),
+ m_default_value (default_value),
+ m_data_sp(),
+ m_completion_mask (CommandCompletions::eDiskFileCompletion)
+{
+}
+
+void
+OptionValueFileSpec::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ if (dump_mask & eDumpOptionType)
+ strm.Printf ("(%s)", GetTypeAsCString ());
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.PutCString (" = ");
+
+ if (m_current_value)
+ {
+ strm << '"' << m_current_value.GetPath().c_str() << '"';
+ }
+ }
+}
+
+Error
+OptionValueFileSpec::SetValueFromCString (const char *value_cstr,
+ VarSetOperationType op)
+{
+ Error error;
+ switch (op)
+ {
+ case eVarSetOperationClear:
+ Clear ();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign:
+ if (value_cstr && value_cstr[0])
+ {
+ Args args(value_cstr);
+ if (args.GetArgumentCount() == 1)
+ {
+ const char *path = args.GetArgumentAtIndex(0);
+ m_value_was_set = true;
+ m_current_value.SetFile(path, true);
+ }
+ else
+ {
+ error.SetErrorString("please supply a single path argument for this file or quote the path if it contains spaces");
+ }
+ }
+ else
+ {
+ error.SetErrorString("invalid value string");
+ }
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationRemove:
+ case eVarSetOperationAppend:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromCString (value_cstr, op);
+ break;
+ }
+ return error;
+}
+
+lldb::OptionValueSP
+OptionValueFileSpec::DeepCopy () const
+{
+ return OptionValueSP(new OptionValueFileSpec(*this));
+}
+
+
+size_t
+OptionValueFileSpec::AutoComplete (CommandInterpreter &interpreter,
+ const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+{
+ word_complete = false;
+ matches.Clear();
+ CommandCompletions::InvokeCommonCompletionCallbacks (interpreter,
+ m_completion_mask,
+ s,
+ match_start_point,
+ max_return_elements,
+ NULL,
+ word_complete,
+ matches);
+ return matches.GetSize();
+}
+
+
+
+const lldb::DataBufferSP &
+OptionValueFileSpec::GetFileContents(bool null_terminate)
+{
+ if (!m_data_sp && m_current_value)
+ {
+ if (null_terminate)
+ m_data_sp = m_current_value.ReadFileContentsAsCString();
+ else
+ m_data_sp = m_current_value.ReadFileContents();
+ }
+ return m_data_sp;
+}
+
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp
new file mode 100644
index 0000000..e493c70
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFileSpecLIst.cpp
@@ -0,0 +1,186 @@
+//===-- OptionValueFileSpecList.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/OptionValueFileSpecList.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+#include "lldb/Interpreter/Args.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+OptionValueFileSpecList::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ if (dump_mask & eDumpOptionType)
+ strm.Printf ("(%s)", GetTypeAsCString ());
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.Printf (" =%s", m_current_value.GetSize() > 0 ? "\n" : "");
+ strm.IndentMore();
+ const uint32_t size = m_current_value.GetSize();
+ for (uint32_t i = 0; i<size; ++i)
+ {
+ strm.Indent();
+ strm.Printf("[%u]: ", i);
+ m_current_value.GetFileSpecAtIndex(i).Dump(&strm);
+ }
+ strm.IndentLess();
+ }
+}
+
+Error
+OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperationType op)
+{
+ Error error;
+ Args args(value);
+ const size_t argc = args.GetArgumentCount();
+
+ switch (op)
+ {
+ case eVarSetOperationClear:
+ Clear ();
+ break;
+
+ case eVarSetOperationReplace:
+ if (argc > 1)
+ {
+ uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
+ const uint32_t count = m_current_value.GetSize();
+ if (idx > count)
+ {
+ error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
+ }
+ else
+ {
+ for (size_t i=1; i<argc; ++i, ++idx)
+ {
+ FileSpec file (args.GetArgumentAtIndex(i), false);
+ if (idx < count)
+ m_current_value.Replace(idx, file);
+ else
+ m_current_value.Append(file);
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("replace operation takes an array index followed by one or more values");
+ }
+ break;
+
+
+
+ case eVarSetOperationAssign:
+ m_current_value.Clear();
+ // Fall through to append case
+ case eVarSetOperationAppend:
+ if (argc > 0)
+ {
+ m_value_was_set = true;
+ for (size_t i=0; i<argc; ++i)
+ {
+ FileSpec file (args.GetArgumentAtIndex(i), false);
+ m_current_value.Append(file);
+ }
+ }
+ else
+ {
+ error.SetErrorString("assign operation takes at least one file path argument");
+ }
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ if (argc > 1)
+ {
+ uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
+ const uint32_t count = m_current_value.GetSize();
+ if (idx > count)
+ {
+ error.SetErrorStringWithFormat("invalid insert file list index %u, index must be 0 through %u", idx, count);
+ }
+ else
+ {
+ if (op == eVarSetOperationInsertAfter)
+ ++idx;
+ for (size_t i=1; i<argc; ++i, ++idx)
+ {
+ FileSpec file (args.GetArgumentAtIndex(i), false);
+ m_current_value.Insert (idx, file);
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("insert operation takes an array index followed by one or more values");
+ }
+ break;
+
+ case eVarSetOperationRemove:
+ if (argc > 0)
+ {
+ std::vector<int> remove_indexes;
+ bool all_indexes_valid = true;
+ size_t i;
+ for (i=0; all_indexes_valid && i<argc; ++i)
+ {
+ const int idx = Args::StringToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
+ if (idx == INT32_MAX)
+ all_indexes_valid = false;
+ else
+ remove_indexes.push_back(idx);
+ }
+
+ if (all_indexes_valid)
+ {
+ size_t num_remove_indexes = remove_indexes.size();
+ if (num_remove_indexes)
+ {
+ // Sort and then erase in reverse so indexes are always valid
+ std::sort(remove_indexes.begin(), remove_indexes.end());
+ for (size_t j=num_remove_indexes-1; j<num_remove_indexes; ++j)
+ {
+ m_current_value.Remove (j);
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i));
+ }
+ }
+ else
+ {
+ error.SetErrorString("remove operation takes one or more array index");
+ }
+ break;
+
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromCString (value, op);
+ break;
+ }
+ return error;
+
+ m_value_was_set = true;
+ return Error();
+}
+
+lldb::OptionValueSP
+OptionValueFileSpecList::DeepCopy () const
+{
+ return OptionValueSP(new OptionValueFileSpecList(*this));
+}
+
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormat.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormat.cpp
new file mode 100644
index 0000000..34d3672
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueFormat.cpp
@@ -0,0 +1,78 @@
+//===-- OptionValueFormat.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Interpreter/OptionValueFormat.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+#include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/Interpreter/Args.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+OptionValueFormat::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ if (dump_mask & eDumpOptionType)
+ strm.Printf ("(%s)", GetTypeAsCString ());
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.PutCString (" = ");
+ strm.PutCString (FormatManager::GetFormatAsCString (m_current_value));
+ }
+}
+
+Error
+OptionValueFormat::SetValueFromCString (const char *value_cstr, VarSetOperationType op)
+{
+ Error error;
+ switch (op)
+ {
+ case eVarSetOperationClear:
+ Clear();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign:
+ {
+ Format new_format;
+ error = Args::StringToFormat (value_cstr, new_format, NULL);
+ if (error.Success())
+ {
+ m_value_was_set = true;
+ m_current_value = new_format;
+ }
+ }
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationRemove:
+ case eVarSetOperationAppend:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromCString (value_cstr, op);
+ break;
+ }
+ return error;
+}
+
+
+lldb::OptionValueSP
+OptionValueFormat::DeepCopy () const
+{
+ return OptionValueSP(new OptionValueFormat(*this));
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValuePathMappings.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValuePathMappings.cpp
new file mode 100644
index 0000000..88a0eb7
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValuePathMappings.cpp
@@ -0,0 +1,185 @@
+//===-- OptionValuePathMappings.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/OptionValuePathMappings.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+#include "lldb/Interpreter/Args.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+OptionValuePathMappings::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ if (dump_mask & eDumpOptionType)
+ strm.Printf ("(%s)", GetTypeAsCString ());
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.Printf (" =%s", (m_path_mappings.GetSize() > 0) ? "\n" : "");
+ m_path_mappings.Dump(&strm);
+ }
+}
+
+Error
+OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperationType op)
+{
+ Error error;
+ Args args(value);
+ const size_t argc = args.GetArgumentCount();
+
+ switch (op)
+ {
+ case eVarSetOperationClear:
+ Clear ();
+ break;
+
+ case eVarSetOperationReplace:
+ // Must be at least one index + 1 pair of paths, and the pair count must be even
+ if (argc >= 3 && (((argc - 1) & 1) == 0))
+ {
+ uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
+ const uint32_t count = m_path_mappings.GetSize();
+ if (idx > count)
+ {
+ error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
+ }
+ else
+ {
+ for (size_t i=1; i<argc; i += 2, ++idx)
+ {
+ ConstString a(args.GetArgumentAtIndex(i));
+ ConstString b(args.GetArgumentAtIndex(i+1));
+ if (!m_path_mappings.Replace (a, b, idx, m_notify_changes))
+ m_path_mappings.Append(a, b, m_notify_changes);
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("replace operation takes an array index followed by one or more path pairs");
+ }
+ break;
+
+
+
+ case eVarSetOperationAssign:
+ if (argc < 2 || (argc & 1))
+ {
+ error.SetErrorString("assign operation takes one or more path pairs");
+ break;
+ }
+ m_path_mappings.Clear(m_notify_changes);
+ // Fall through to append case
+ case eVarSetOperationAppend:
+ if (argc < 2 || (argc & 1))
+ {
+ error.SetErrorString("append operation takes one or more path pairs");
+ break;
+ }
+ else
+ {
+ for (size_t i=0; i<argc; i += 2)
+ {
+ ConstString a(args.GetArgumentAtIndex(i));
+ ConstString b(args.GetArgumentAtIndex(i+1));
+ m_path_mappings.Append(a, b, m_notify_changes);
+ m_value_was_set = true;
+ }
+ }
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ // Must be at least one index + 1 pair of paths, and the pair count must be even
+ if (argc >= 3 && (((argc - 1) & 1) == 0))
+ {
+ uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
+ const uint32_t count = m_path_mappings.GetSize();
+ if (idx > count)
+ {
+ error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
+ }
+ else
+ {
+ if (op == eVarSetOperationInsertAfter)
+ ++idx;
+ for (size_t i=1; i<argc; i += 2, ++idx)
+ {
+ ConstString a(args.GetArgumentAtIndex(i));
+ ConstString b(args.GetArgumentAtIndex(i+1));
+ m_path_mappings.Insert (a, b, idx, m_notify_changes);
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("insert operation takes an array index followed by one or more path pairs");
+ }
+ break;
+
+ case eVarSetOperationRemove:
+ if (argc > 0)
+ {
+ std::vector<int> remove_indexes;
+ bool all_indexes_valid = true;
+ size_t i;
+ for (i=0; all_indexes_valid && i<argc; ++i)
+ {
+ const int idx = Args::StringToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
+ if (idx == INT32_MAX)
+ all_indexes_valid = false;
+ else
+ remove_indexes.push_back(idx);
+ }
+
+ if (all_indexes_valid)
+ {
+ size_t num_remove_indexes = remove_indexes.size();
+ if (num_remove_indexes)
+ {
+ // Sort and then erase in reverse so indexes are always valid
+ std::sort(remove_indexes.begin(), remove_indexes.end());
+ for (size_t j=num_remove_indexes-1; j<num_remove_indexes; ++j)
+ {
+ m_path_mappings.Remove (j, m_notify_changes);
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i));
+ }
+ }
+ else
+ {
+ error.SetErrorString("remove operation takes one or more array index");
+ }
+ break;
+
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromCString (value, op);
+ break;
+ }
+ return error;
+
+ m_value_was_set = true;
+ return Error();
+}
+
+lldb::OptionValueSP
+OptionValuePathMappings::DeepCopy () const
+{
+ return OptionValueSP(new OptionValuePathMappings(*this));
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp
new file mode 100644
index 0000000..0df3782
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueProperties.cpp
@@ -0,0 +1,762 @@
+//===-- OptionValueProperties.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/OptionValueProperties.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Flags.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Core/UserSettingsController.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/OptionValues.h"
+#include "lldb/Interpreter/Property.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+OptionValueProperties::OptionValueProperties (const ConstString &name) :
+ OptionValue (),
+ m_name (name),
+ m_properties (),
+ m_name_to_index ()
+{
+}
+
+OptionValueProperties::OptionValueProperties (const OptionValueProperties &global_properties) :
+ OptionValue (global_properties),
+ m_name (global_properties.m_name),
+ m_properties (global_properties.m_properties),
+ m_name_to_index (global_properties.m_name_to_index)
+{
+ // We now have an exact copy of "global_properties". We need to now
+ // find all non-global settings and copy the property values so that
+ // all non-global settings get new OptionValue instances created for
+ // them.
+ const size_t num_properties = m_properties.size();
+ for (size_t i=0; i<num_properties; ++i)
+ {
+ // Duplicate any values that are not global when contructing properties from
+ // a global copy
+ if (m_properties[i].IsGlobal() == false)
+ {
+ lldb::OptionValueSP new_value_sp (m_properties[i].GetValue()->DeepCopy());
+ m_properties[i].SetOptionValue(new_value_sp);
+ }
+ }
+}
+
+
+
+size_t
+OptionValueProperties::GetNumProperties() const
+{
+ return m_properties.size();
+}
+
+
+void
+OptionValueProperties::Initialize (const PropertyDefinition *defs)
+{
+ for (size_t i=0; defs[i].name; ++i)
+ {
+ Property property(defs[i]);
+ assert(property.IsValid());
+ m_name_to_index.Append(property.GetName().GetCString(),m_properties.size());
+ property.GetValue()->SetParent(shared_from_this());
+ m_properties.push_back(property);
+ }
+ m_name_to_index.Sort();
+}
+
+void
+OptionValueProperties::AppendProperty(const ConstString &name,
+ const ConstString &desc,
+ bool is_global,
+ const OptionValueSP &value_sp)
+{
+ Property property(name, desc, is_global, value_sp);
+ m_name_to_index.Append(name.GetCString(),m_properties.size());
+ m_properties.push_back(property);
+ value_sp->SetParent (shared_from_this());
+ m_name_to_index.Sort();
+}
+
+
+
+//bool
+//OptionValueProperties::GetQualifiedName (Stream &strm)
+//{
+// bool dumped_something = false;
+//// lldb::OptionValuePropertiesSP parent_sp(GetParent ());
+//// if (parent_sp)
+//// {
+//// parent_sp->GetQualifiedName (strm);
+//// strm.PutChar('.');
+//// dumped_something = true;
+//// }
+// if (m_name)
+// {
+// strm << m_name;
+// dumped_something = true;
+// }
+// return dumped_something;
+//}
+//
+lldb::OptionValueSP
+OptionValueProperties::GetValueForKey (const ExecutionContext *exe_ctx,
+ const ConstString &key,
+ bool will_modify) const
+{
+ lldb::OptionValueSP value_sp;
+ size_t idx = m_name_to_index.Find (key.GetCString(), SIZE_MAX);
+ if (idx < m_properties.size())
+ value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue();
+ return value_sp;
+}
+
+lldb::OptionValueSP
+OptionValueProperties::GetSubValue (const ExecutionContext *exe_ctx,
+ const char *name,
+ bool will_modify,
+ Error &error) const
+{
+ lldb::OptionValueSP value_sp;
+
+ if (name && name[0])
+ {
+ const char *sub_name = NULL;
+ ConstString key;
+ size_t key_len = ::strcspn (name, ".[{");
+
+ if (name[key_len])
+ {
+ key.SetCStringWithLength (name, key_len);
+ sub_name = name + key_len;
+ }
+ else
+ key.SetCString (name);
+
+ value_sp = GetValueForKey (exe_ctx, key, will_modify);
+ if (sub_name && value_sp)
+ {
+ switch (sub_name[0])
+ {
+ case '.':
+ return value_sp->GetSubValue (exe_ctx, sub_name + 1, will_modify, error);
+
+ case '{':
+ // Predicate matching for predicates like
+ // "<setting-name>{<predicate>}"
+ // strings are parsed by the current OptionValueProperties subclass
+ // to mean whatever they want to. For instance a subclass of
+ // OptionValueProperties for a lldb_private::Target might implement:
+ // "target.run-args{arch==i386}" -- only set run args if the arch is i386
+ // "target.run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the path matches
+ // "target.run-args{basename==test&&arch==x86_64}" -- only set run args if exectable basename is "test" and arch is "x86_64"
+ if (sub_name[1])
+ {
+ const char *predicate_start = sub_name + 1;
+ const char *predicate_end = strchr(predicate_start, '}');
+ if (predicate_end)
+ {
+ std::string predicate(predicate_start, predicate_end);
+ if (PredicateMatches(exe_ctx, predicate.c_str()))
+ {
+ if (predicate_end[1])
+ {
+ // Still more subvalue string to evaluate
+ return value_sp->GetSubValue (exe_ctx, predicate_end + 1, will_modify, error);
+ }
+ else
+ {
+ // We have a match!
+ break;
+ }
+ }
+ }
+ }
+ // Predicate didn't match or wasn't correctly formed
+ value_sp.reset();
+ break;
+
+ case '[':
+ // Array or dictionary access for subvalues like:
+ // "[12]" -- access 12th array element
+ // "['hello']" -- dictionary access of key named hello
+ return value_sp->GetSubValue (exe_ctx, sub_name, will_modify, error);
+
+ default:
+ value_sp.reset();
+ break;
+ }
+ }
+ }
+ return value_sp;
+}
+
+Error
+OptionValueProperties::SetSubValue (const ExecutionContext *exe_ctx,
+ VarSetOperationType op,
+ const char *name,
+ const char *value)
+{
+ Error error;
+ const bool will_modify = true;
+ lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error));
+ if (value_sp)
+ error = value_sp->SetValueFromCString(value, op);
+ else
+ {
+ if (error.AsCString() == NULL)
+ error.SetErrorStringWithFormat("invalid value path '%s'", name);
+ }
+ return error;
+}
+
+
+ConstString
+OptionValueProperties::GetPropertyNameAtIndex (uint32_t idx) const
+{
+ const Property *property = GetPropertyAtIndex(NULL, false, idx);
+ if (property)
+ return property->GetName();
+ return ConstString();
+
+}
+
+const char *
+OptionValueProperties::GetPropertyDescriptionAtIndex (uint32_t idx) const
+{
+ const Property *property = GetPropertyAtIndex(NULL, false, idx);
+ if (property)
+ return property->GetDescription();
+ return NULL;
+}
+
+uint32_t
+OptionValueProperties::GetPropertyIndex (const ConstString &name) const
+{
+ return m_name_to_index.Find (name.GetCString(), SIZE_MAX);
+}
+
+const Property *
+OptionValueProperties::GetProperty (const ExecutionContext *exe_ctx, bool will_modify, const ConstString &name) const
+{
+ return GetPropertyAtIndex (exe_ctx, will_modify, m_name_to_index.Find (name.GetCString(), SIZE_MAX));
+}
+
+const Property *
+OptionValueProperties::GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
+{
+ return ProtectedGetPropertyAtIndex (idx);
+}
+
+lldb::OptionValueSP
+OptionValueProperties::GetPropertyValueAtIndex (const ExecutionContext *exe_ctx,
+ bool will_modify,
+ uint32_t idx) const
+{
+ const Property *setting = GetPropertyAtIndex (exe_ctx, will_modify, idx);
+ if (setting)
+ return setting->GetValue();
+ return OptionValueSP();
+}
+
+OptionValuePathMappings *
+OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
+{
+ OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx));
+ if (value_sp)
+ return value_sp->GetAsPathMappings();
+ return NULL;
+}
+
+OptionValueFileSpecList *
+OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
+{
+ OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx));
+ if (value_sp)
+ return value_sp->GetAsFileSpecList();
+ return NULL;
+}
+
+OptionValueArch *
+OptionValueProperties::GetPropertyAtIndexAsOptionValueArch (const ExecutionContext *exe_ctx, uint32_t idx) const
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
+ if (property)
+ return property->GetValue()->GetAsArch();
+ return NULL;
+}
+
+bool
+OptionValueProperties::GetPropertyAtIndexAsArgs (const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ {
+ const OptionValueArray *array = value->GetAsArray();
+ if (array)
+ return array->GetArgs(args);
+ else
+ {
+ const OptionValueDictionary *dict = value->GetAsDictionary();
+ if (dict)
+ return dict->GetArgs(args);
+ }
+ }
+ }
+ return false;
+}
+
+bool
+OptionValueProperties::SetPropertyAtIndexFromArgs (const ExecutionContext *exe_ctx, uint32_t idx, const Args &args)
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ {
+ OptionValueArray *array = value->GetAsArray();
+ if (array)
+ return array->SetArgs(args, eVarSetOperationAssign).Success();
+ else
+ {
+ OptionValueDictionary *dict = value->GetAsDictionary();
+ if (dict)
+ return dict->SetArgs(args, eVarSetOperationAssign).Success();
+ }
+ }
+ }
+ return false;
+}
+
+bool
+OptionValueProperties::GetPropertyAtIndexAsBoolean (const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->GetBooleanValue(fail_value);
+ }
+ return fail_value;
+}
+
+bool
+OptionValueProperties::SetPropertyAtIndexAsBoolean (const ExecutionContext *exe_ctx, uint32_t idx, bool new_value)
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ {
+ value->SetBooleanValue(new_value);
+ return true;
+ }
+ }
+ return false;
+}
+
+OptionValueDictionary *
+OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary (const ExecutionContext *exe_ctx, uint32_t idx) const
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
+ if (property)
+ return property->GetValue()->GetAsDictionary();
+ return NULL;
+}
+
+int64_t
+OptionValueProperties::GetPropertyAtIndexAsEnumeration (const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->GetEnumerationValue(fail_value);
+ }
+ return fail_value;
+}
+
+bool
+OptionValueProperties::SetPropertyAtIndexAsEnumeration (const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value)
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->SetEnumerationValue(new_value);
+ }
+ return false;
+}
+
+
+OptionValueFileSpec *
+OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->GetAsFileSpec();
+ }
+ return NULL;
+}
+
+
+FileSpec
+OptionValueProperties::GetPropertyAtIndexAsFileSpec (const ExecutionContext *exe_ctx, uint32_t idx) const
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->GetFileSpecValue();
+ }
+ return FileSpec();
+}
+
+
+bool
+OptionValueProperties::SetPropertyAtIndexAsFileSpec (const ExecutionContext *exe_ctx, uint32_t idx, const FileSpec &new_file_spec)
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->SetFileSpecValue(new_file_spec);
+ }
+ return false;
+}
+
+const RegularExpression *
+OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex (const ExecutionContext *exe_ctx, uint32_t idx) const
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->GetRegexValue();
+ }
+ return NULL;
+}
+
+OptionValueSInt64 *
+OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64 (const ExecutionContext *exe_ctx, uint32_t idx) const
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->GetAsSInt64();
+ }
+ return NULL;
+}
+
+int64_t
+OptionValueProperties::GetPropertyAtIndexAsSInt64 (const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->GetSInt64Value(fail_value);
+ }
+ return fail_value;
+}
+
+bool
+OptionValueProperties::SetPropertyAtIndexAsSInt64 (const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value)
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->SetSInt64Value(new_value);
+ }
+ return false;
+}
+
+const char *
+OptionValueProperties::GetPropertyAtIndexAsString (const ExecutionContext *exe_ctx, uint32_t idx, const char *fail_value) const
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->GetStringValue(fail_value);
+ }
+ return fail_value;
+}
+
+bool
+OptionValueProperties::SetPropertyAtIndexAsString (const ExecutionContext *exe_ctx, uint32_t idx, const char *new_value)
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->SetStringValue(new_value);
+ }
+ return false;
+}
+
+OptionValueString *
+OptionValueProperties::GetPropertyAtIndexAsOptionValueString (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
+{
+ OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx));
+ if (value_sp)
+ return value_sp->GetAsString();
+ return NULL;
+}
+
+
+uint64_t
+OptionValueProperties::GetPropertyAtIndexAsUInt64 (const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->GetUInt64Value(fail_value);
+ }
+ return fail_value;
+}
+
+bool
+OptionValueProperties::SetPropertyAtIndexAsUInt64 (const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value)
+{
+ const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
+ if (property)
+ {
+ OptionValue *value = property->GetValue().get();
+ if (value)
+ return value->SetUInt64Value(new_value);
+ }
+ return false;
+}
+
+bool
+OptionValueProperties::Clear ()
+{
+ const size_t num_properties = m_properties.size();
+ for (size_t i=0; i<num_properties; ++i)
+ m_properties[i].GetValue()->Clear();
+ return true;
+}
+
+
+Error
+OptionValueProperties::SetValueFromCString (const char *value, VarSetOperationType op)
+{
+ Error error;
+
+// Args args(value_cstr);
+// const size_t argc = args.GetArgumentCount();
+ switch (op)
+ {
+ case eVarSetOperationClear:
+ Clear ();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign:
+ case eVarSetOperationRemove:
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationAppend:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromCString (value, op);
+ break;
+ }
+
+ return error;
+}
+
+void
+OptionValueProperties::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ const size_t num_properties = m_properties.size();
+ for (size_t i=0; i<num_properties; ++i)
+ {
+ const Property *property = GetPropertyAtIndex(exe_ctx, false, i);
+ if (property)
+ {
+ OptionValue *option_value = property->GetValue().get();
+ assert (option_value);
+ const bool transparent_value = option_value->ValueIsTransparent ();
+ property->Dump (exe_ctx,
+ strm,
+ dump_mask);
+ if (!transparent_value)
+ strm.EOL();
+ }
+ }
+}
+
+Error
+OptionValueProperties::DumpPropertyValue (const ExecutionContext *exe_ctx,
+ Stream &strm,
+ const char *property_path,
+ uint32_t dump_mask)
+{
+ Error error;
+ const bool will_modify = false;
+ lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, property_path, will_modify, error));
+ if (value_sp)
+ {
+ if (!value_sp->ValueIsTransparent ())
+ {
+ if (dump_mask & eDumpOptionName)
+ strm.PutCString (property_path);
+ if (dump_mask & ~eDumpOptionName)
+ strm.PutChar (' ');
+ }
+ value_sp->DumpValue (exe_ctx, strm, dump_mask);
+ }
+ return error;
+}
+
+lldb::OptionValueSP
+OptionValueProperties::DeepCopy () const
+{
+ assert(!"this shouldn't happen");
+}
+
+const Property *
+OptionValueProperties::GetPropertyAtPath (const ExecutionContext *exe_ctx,
+ bool will_modify,
+ const char *name) const
+{
+ const Property *property = NULL;
+ if (name && name[0])
+ {
+ const char *sub_name = NULL;
+ ConstString key;
+ size_t key_len = ::strcspn (name, ".[{");
+
+ if (name[key_len])
+ {
+ key.SetCStringWithLength (name, key_len);
+ sub_name = name + key_len;
+ }
+ else
+ key.SetCString (name);
+
+ property = GetProperty (exe_ctx, will_modify, key);
+ if (sub_name && property)
+ {
+ if (sub_name[0] == '.')
+ {
+ OptionValueProperties *sub_properties = property->GetValue()->GetAsProperties();
+ if (sub_properties)
+ return sub_properties->GetPropertyAtPath(exe_ctx, will_modify, sub_name + 1);
+ }
+ property = NULL;
+ }
+ }
+ return property;
+}
+
+void
+OptionValueProperties::DumpAllDescriptions (CommandInterpreter &interpreter,
+ Stream &strm) const
+{
+ size_t max_name_len = 0;
+ const size_t num_properties = m_properties.size();
+ for (size_t i=0; i<num_properties; ++i)
+ {
+ const Property *property = ProtectedGetPropertyAtIndex(i);
+ if (property)
+ max_name_len = std::max<size_t>(property->GetName().GetLength(), max_name_len);
+ }
+ for (size_t i=0; i<num_properties; ++i)
+ {
+ const Property *property = ProtectedGetPropertyAtIndex(i);
+ if (property)
+ property->DumpDescription (interpreter, strm, max_name_len, false);
+ }
+}
+
+void
+OptionValueProperties::Apropos (const char *keyword, std::vector<const Property *> &matching_properties) const
+{
+ const size_t num_properties = m_properties.size();
+ StreamString strm;
+ for (size_t i=0; i<num_properties; ++i)
+ {
+ const Property *property = ProtectedGetPropertyAtIndex(i);
+ if (property)
+ {
+ const OptionValueProperties *properties = property->GetValue()->GetAsProperties();
+ if (properties)
+ {
+ properties->Apropos (keyword, matching_properties);
+ }
+ else
+ {
+ bool match = false;
+ const char *name = property->GetName().GetCString();
+ if (name && ::strcasestr(name, keyword))
+ match = true;
+ else
+ {
+ const char *desc = property->GetDescription();
+ if (desc && ::strcasestr(desc, keyword))
+ match = true;
+ }
+ if (match)
+ {
+ matching_properties.push_back (property);
+ }
+ }
+ }
+ }
+}
+
+lldb::OptionValuePropertiesSP
+OptionValueProperties::GetSubProperty (const ExecutionContext *exe_ctx,
+ const ConstString &name)
+{
+ lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false));
+ if (option_value_sp)
+ {
+ OptionValueProperties *ov_properties = option_value_sp->GetAsProperties ();
+ if (ov_properties)
+ return ov_properties->shared_from_this();
+ }
+ return lldb::OptionValuePropertiesSP();
+}
+
+
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueRegex.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueRegex.cpp
new file mode 100644
index 0000000..f1ba0ed
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueRegex.cpp
@@ -0,0 +1,86 @@
+//===-- OptionValueRegex.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/OptionValueRegex.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+OptionValueRegex::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ if (dump_mask & eDumpOptionType)
+ strm.Printf ("(%s)", GetTypeAsCString ());
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.PutCString (" = ");
+ if (m_regex.IsValid())
+ {
+ const char *regex_text = m_regex.GetText();
+ if (regex_text && regex_text[0])
+ strm.Printf ("%s", regex_text);
+ }
+ else
+ {
+
+ }
+ }
+}
+
+Error
+OptionValueRegex::SetValueFromCString (const char *value_cstr,
+ VarSetOperationType op)
+{
+ Error error;
+ switch (op)
+ {
+ case eVarSetOperationInvalid:
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationRemove:
+ case eVarSetOperationAppend:
+ error = OptionValue::SetValueFromCString (value_cstr, op);
+ break;
+
+ case eVarSetOperationClear:
+ Clear();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign:
+ if (m_regex.Compile (value_cstr, m_regex.GetCompileFlags()))
+ {
+ m_value_was_set = true;
+ }
+ else
+ {
+ char regex_error[1024];
+ if (m_regex.GetErrorAsCString(regex_error, sizeof(regex_error)))
+ error.SetErrorString (regex_error);
+ else
+ error.SetErrorStringWithFormat ("regex error %u", m_regex.GetErrorCode());
+ }
+ break;
+ }
+ return error;
+}
+
+
+lldb::OptionValueSP
+OptionValueRegex::DeepCopy () const
+{
+ return OptionValueSP(new OptionValueRegex(m_regex.GetText(), m_regex.GetCompileFlags()));
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueSInt64.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueSInt64.cpp
new file mode 100644
index 0000000..04bf930
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueSInt64.cpp
@@ -0,0 +1,89 @@
+//===-- OptionValueSInt64.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/OptionValueSInt64.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+#include "lldb/Interpreter/Args.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+OptionValueSInt64::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ //printf ("%p: DumpValue (exe_ctx=%p, strm, mask) m_current_value = %" PRIi64 "\n", this, exe_ctx, m_current_value);
+ if (dump_mask & eDumpOptionType)
+ strm.Printf ("(%s)", GetTypeAsCString ());
+// if (dump_mask & eDumpOptionName)
+// DumpQualifiedName (strm);
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.PutCString (" = ");
+ strm.Printf ("%" PRIi64, m_current_value);
+ }
+}
+
+Error
+OptionValueSInt64::SetValueFromCString (const char *value_cstr, VarSetOperationType op)
+{
+ //printf ("%p: SetValueFromCString (s=\"%s\", op=%i)\n", this, value_cstr, op);
+ Error error;
+ switch (op)
+ {
+ case eVarSetOperationClear:
+ Clear();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign:
+ {
+ bool success = false;
+ int64_t value = Args::StringToSInt64 (value_cstr, 0, 0, &success);
+ if (success)
+ {
+ if (value >= m_min_value && value <= m_max_value)
+ {
+ m_value_was_set = true;
+ m_current_value = value;
+ }
+ else
+ error.SetErrorStringWithFormat ("%" PRIi64 " is out of range, valid values must be between %" PRIi64 " and %" PRIi64 ".",
+ value,
+ m_min_value,
+ m_max_value);
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("invalid int64_t string value: '%s'", value_cstr);
+ }
+ }
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationRemove:
+ case eVarSetOperationAppend:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromCString (value_cstr, op);
+ break;
+ }
+ return error;
+}
+
+lldb::OptionValueSP
+OptionValueSInt64::DeepCopy () const
+{
+ return OptionValueSP(new OptionValueSInt64(*this));
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueString.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueString.cpp
new file mode 100644
index 0000000..df047bd
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueString.cpp
@@ -0,0 +1,186 @@
+//===-- OptionValueString.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/OptionValueString.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+#include "lldb/Interpreter/Args.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+OptionValueString::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ if (dump_mask & eDumpOptionType)
+ strm.Printf ("(%s)", GetTypeAsCString ());
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.PutCString (" = ");
+ if (!m_current_value.empty() || m_value_was_set)
+ {
+ if (m_options.Test (eOptionEncodeCharacterEscapeSequences))
+ {
+ std::string expanded_escape_value;
+ Args::ExpandEscapedCharacters(m_current_value.c_str(), expanded_escape_value);
+ if (dump_mask & eDumpOptionRaw)
+ strm.Printf ("%s", expanded_escape_value.c_str());
+ else
+ strm.Printf ("\"%s\"", expanded_escape_value.c_str());
+ }
+ else
+ {
+ if (dump_mask & eDumpOptionRaw)
+ strm.Printf ("%s", m_current_value.c_str());
+ else
+ strm.Printf ("\"%s\"", m_current_value.c_str());
+ }
+ }
+ }
+}
+
+Error
+OptionValueString::SetValueFromCString (const char *value_cstr,
+ VarSetOperationType op)
+{
+ Error error;
+
+ std::string value_str_no_quotes;
+ if (value_cstr)
+ {
+ switch (value_cstr[0])
+ {
+ case '"':
+ case '\'':
+ {
+ size_t len = strlen(value_cstr);
+ if (len <= 1 || value_cstr[len-1] != value_cstr[0])
+ {
+ error.SetErrorString("mismatched quotes");
+ return error;
+ }
+ value_str_no_quotes.assign (value_cstr + 1, len - 2);
+ value_cstr = value_str_no_quotes.c_str();
+ }
+ break;
+ }
+ }
+
+ switch (op)
+ {
+ case eVarSetOperationInvalid:
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationRemove:
+ if (m_validator)
+ {
+ error = m_validator(value_cstr,m_validator_baton);
+ if (error.Fail())
+ return error;
+ }
+ error = OptionValue::SetValueFromCString (value_cstr, op);
+ break;
+
+ case eVarSetOperationAppend:
+ {
+ std::string new_value(m_current_value);
+ if (value_cstr && value_cstr[0])
+ {
+ if (m_options.Test (eOptionEncodeCharacterEscapeSequences))
+ {
+ std::string str;
+ Args::EncodeEscapeSequences (value_cstr, str);
+ new_value.append(str);
+ }
+ else
+ new_value.append(value_cstr);
+ }
+ if (m_validator)
+ {
+ error = m_validator(new_value.c_str(),m_validator_baton);
+ if (error.Fail())
+ return error;
+ }
+ m_current_value.assign(new_value);
+ }
+ break;
+
+ case eVarSetOperationClear:
+ Clear ();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign:
+ if (m_validator)
+ {
+ error = m_validator(value_cstr,m_validator_baton);
+ if (error.Fail())
+ return error;
+ }
+ m_value_was_set = true;
+ if (m_options.Test (eOptionEncodeCharacterEscapeSequences))
+ {
+ Args::EncodeEscapeSequences (value_cstr, m_current_value);
+ }
+ else
+ {
+ SetCurrentValue (value_cstr);
+ }
+ break;
+ }
+ return error;
+}
+
+
+lldb::OptionValueSP
+OptionValueString::DeepCopy () const
+{
+ return OptionValueSP(new OptionValueString(*this));
+}
+
+Error
+OptionValueString::SetCurrentValue (const char *value)
+{
+ if (m_validator)
+ {
+ Error error(m_validator(value,m_validator_baton));
+ if (error.Fail())
+ return error;
+ }
+ if (value && value[0])
+ m_current_value.assign (value);
+ else
+ m_current_value.clear();
+ return Error();
+}
+
+Error
+OptionValueString::AppendToCurrentValue (const char *value)
+{
+ if (value && value[0])
+ {
+ if (m_validator)
+ {
+ std::string new_value(m_current_value);
+ new_value.append(value);
+ Error error(m_validator(value,m_validator_baton));
+ if (error.Fail())
+ return error;
+ m_current_value.assign(new_value);
+ }
+ else
+ m_current_value.append (value);
+ }
+ return Error();
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUInt64.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUInt64.cpp
new file mode 100644
index 0000000..56b3a1c
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUInt64.cpp
@@ -0,0 +1,89 @@
+//===-- OptionValueUInt64.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/OptionValueUInt64.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Stream.h"
+#include "lldb/Interpreter/Args.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+lldb::OptionValueSP
+OptionValueUInt64::Create (const char *value_cstr, Error &error)
+{
+ lldb::OptionValueSP value_sp (new OptionValueUInt64());
+ error = value_sp->SetValueFromCString (value_cstr);
+ if (error.Fail())
+ value_sp.reset();
+ return value_sp;
+}
+
+
+void
+OptionValueUInt64::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ if (dump_mask & eDumpOptionType)
+ strm.Printf ("(%s)", GetTypeAsCString ());
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.PutCString (" = ");
+ strm.Printf ("%" PRIu64, m_current_value);
+ }
+}
+
+Error
+OptionValueUInt64::SetValueFromCString (const char *value_cstr, VarSetOperationType op)
+{
+ Error error;
+ switch (op)
+ {
+ case eVarSetOperationClear:
+ Clear ();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign:
+ {
+ bool success = false;
+ uint64_t value = Args::StringToUInt64 (value_cstr, 0, 0, &success);
+ if (success)
+ {
+ m_value_was_set = true;
+ m_current_value = value;
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("invalid uint64_t string value: '%s'", value_cstr);
+ }
+ }
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationRemove:
+ case eVarSetOperationAppend:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromCString (value_cstr, op);
+ break;
+ }
+ return error;
+}
+
+lldb::OptionValueSP
+OptionValueUInt64::DeepCopy () const
+{
+ return OptionValueSP(new OptionValueUInt64(*this));
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUUID.cpp b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUUID.cpp
new file mode 100644
index 0000000..340f1e5
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/OptionValueUUID.cpp
@@ -0,0 +1,123 @@
+//===-- OptionValueUUID.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Interpreter/OptionValueUUID.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+OptionValueUUID::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
+{
+ if (dump_mask & eDumpOptionType)
+ strm.Printf ("(%s)", GetTypeAsCString ());
+ if (dump_mask & eDumpOptionValue)
+ {
+ if (dump_mask & eDumpOptionType)
+ strm.PutCString (" = ");
+ m_uuid.Dump (&strm);
+ }
+}
+
+Error
+OptionValueUUID::SetValueFromCString (const char *value_cstr,
+ VarSetOperationType op)
+{
+ Error error;
+ switch (op)
+ {
+ case eVarSetOperationClear:
+ Clear();
+ break;
+
+ case eVarSetOperationReplace:
+ case eVarSetOperationAssign:
+ {
+ if (m_uuid.SetFromCString(value_cstr) == 0)
+ error.SetErrorStringWithFormat ("invalid uuid string value '%s'", value_cstr);
+ else
+ m_value_was_set = true;
+ }
+ break;
+
+ case eVarSetOperationInsertBefore:
+ case eVarSetOperationInsertAfter:
+ case eVarSetOperationRemove:
+ case eVarSetOperationAppend:
+ case eVarSetOperationInvalid:
+ error = OptionValue::SetValueFromCString (value_cstr, op);
+ break;
+ }
+ return error;
+}
+
+lldb::OptionValueSP
+OptionValueUUID::DeepCopy () const
+{
+ return OptionValueSP(new OptionValueUUID(*this));
+}
+
+size_t
+OptionValueUUID::AutoComplete (CommandInterpreter &interpreter,
+ const char *s,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+{
+ word_complete = false;
+ matches.Clear();
+ ExecutionContext exe_ctx(interpreter.GetExecutionContext());
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ {
+ const size_t num_modules = target->GetImages().GetSize();
+ if (num_modules > 0)
+ {
+ UUID::ValueType uuid_bytes;
+ const size_t num_bytes_decoded = UUID::DecodeUUIDBytesFromCString(s, uuid_bytes, NULL);
+ for (size_t i=0; i<num_modules; ++i)
+ {
+ ModuleSP module_sp (target->GetImages().GetModuleAtIndex(i));
+ if (module_sp)
+ {
+ const UUID &module_uuid = module_sp->GetUUID();
+ if (module_uuid.IsValid())
+ {
+ bool add_uuid = false;
+ if (num_bytes_decoded == 0)
+ add_uuid = true;
+ else
+ add_uuid = ::memcmp(module_uuid.GetBytes(), uuid_bytes, num_bytes_decoded) == 0;
+ if (add_uuid)
+ {
+ std::string uuid_str;
+ uuid_str = module_uuid.GetAsString();
+ if (!uuid_str.empty())
+ matches.AppendString(uuid_str.c_str());
+ }
+ }
+ }
+ }
+ }
+ }
+ return matches.GetSize();
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/Options.cpp b/contrib/llvm/tools/lldb/source/Interpreter/Options.cpp
new file mode 100644
index 0000000..293d753
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/Options.cpp
@@ -0,0 +1,1077 @@
+//===-- Options.cpp ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Interpreter/Options.h"
+
+// C Includes
+// C++ Includes
+#include <algorithm>
+#include <bitset>
+#include <map>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// Options
+//-------------------------------------------------------------------------
+Options::Options (CommandInterpreter &interpreter) :
+ m_interpreter (interpreter),
+ m_getopt_table ()
+{
+ BuildValidOptionSets();
+}
+
+Options::~Options ()
+{
+}
+
+void
+Options::NotifyOptionParsingStarting ()
+{
+ m_seen_options.clear();
+ // Let the subclass reset its option values
+ OptionParsingStarting ();
+}
+
+Error
+Options::NotifyOptionParsingFinished ()
+{
+ return OptionParsingFinished ();
+}
+
+void
+Options::OptionSeen (int option_idx)
+{
+ m_seen_options.insert (option_idx);
+}
+
+// Returns true is set_a is a subset of set_b; Otherwise returns false.
+
+bool
+Options::IsASubset (const OptionSet& set_a, const OptionSet& set_b)
+{
+ bool is_a_subset = true;
+ OptionSet::const_iterator pos_a;
+ OptionSet::const_iterator pos_b;
+
+ // set_a is a subset of set_b if every member of set_a is also a member of set_b
+
+ for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a)
+ {
+ pos_b = set_b.find(*pos_a);
+ if (pos_b == set_b.end())
+ is_a_subset = false;
+ }
+
+ return is_a_subset;
+}
+
+// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) && !ElementOf (x, set_b) }
+
+size_t
+Options::OptionsSetDiff (const OptionSet& set_a, const OptionSet& set_b, OptionSet& diffs)
+{
+ size_t num_diffs = 0;
+ OptionSet::const_iterator pos_a;
+ OptionSet::const_iterator pos_b;
+
+ for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a)
+ {
+ pos_b = set_b.find(*pos_a);
+ if (pos_b == set_b.end())
+ {
+ ++num_diffs;
+ diffs.insert(*pos_a);
+ }
+ }
+
+ return num_diffs;
+}
+
+// Returns the union of set_a and set_b. Does not put duplicate members into the union.
+
+void
+Options::OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set)
+{
+ OptionSet::const_iterator pos;
+ OptionSet::iterator pos_union;
+
+ // Put all the elements of set_a into the union.
+
+ for (pos = set_a.begin(); pos != set_a.end(); ++pos)
+ union_set.insert(*pos);
+
+ // Put all the elements of set_b that are not already there into the union.
+ for (pos = set_b.begin(); pos != set_b.end(); ++pos)
+ {
+ pos_union = union_set.find(*pos);
+ if (pos_union == union_set.end())
+ union_set.insert(*pos);
+ }
+}
+
+bool
+Options::VerifyOptions (CommandReturnObject &result)
+{
+ bool options_are_valid = false;
+
+ int num_levels = GetRequiredOptions().size();
+ if (num_levels)
+ {
+ for (int i = 0; i < num_levels && !options_are_valid; ++i)
+ {
+ // This is the correct set of options if: 1). m_seen_options contains all of m_required_options[i]
+ // (i.e. all the required options at this level are a subset of m_seen_options); AND
+ // 2). { m_seen_options - m_required_options[i] is a subset of m_options_options[i] (i.e. all the rest of
+ // m_seen_options are in the set of optional options at this level.
+
+ // Check to see if all of m_required_options[i] are a subset of m_seen_options
+ if (IsASubset (GetRequiredOptions()[i], m_seen_options))
+ {
+ // Construct the set difference: remaining_options = {m_seen_options} - {m_required_options[i]}
+ OptionSet remaining_options;
+ OptionsSetDiff (m_seen_options, GetRequiredOptions()[i], remaining_options);
+ // Check to see if remaining_options is a subset of m_optional_options[i]
+ if (IsASubset (remaining_options, GetOptionalOptions()[i]))
+ options_are_valid = true;
+ }
+ }
+ }
+ else
+ {
+ options_are_valid = true;
+ }
+
+ if (options_are_valid)
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendError ("invalid combination of options for the given command");
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ return options_are_valid;
+}
+
+// This is called in the Options constructor, though we could call it lazily if that ends up being
+// a performance problem.
+
+void
+Options::BuildValidOptionSets ()
+{
+ // Check to see if we already did this.
+ if (m_required_options.size() != 0)
+ return;
+
+ // Check to see if there are any options.
+ int num_options = NumCommandOptions ();
+ if (num_options == 0)
+ return;
+
+ const OptionDefinition *opt_defs = GetDefinitions();
+ m_required_options.resize(1);
+ m_optional_options.resize(1);
+
+ // First count the number of option sets we've got. Ignore LLDB_ALL_OPTION_SETS...
+
+ uint32_t num_option_sets = 0;
+
+ for (int i = 0; i < num_options; i++)
+ {
+ uint32_t this_usage_mask = opt_defs[i].usage_mask;
+ if (this_usage_mask == LLDB_OPT_SET_ALL)
+ {
+ if (num_option_sets == 0)
+ num_option_sets = 1;
+ }
+ else
+ {
+ for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
+ {
+ if (this_usage_mask & (1 << j))
+ {
+ if (num_option_sets <= j)
+ num_option_sets = j + 1;
+ }
+ }
+ }
+ }
+
+ if (num_option_sets > 0)
+ {
+ m_required_options.resize(num_option_sets);
+ m_optional_options.resize(num_option_sets);
+
+ for (int i = 0; i < num_options; ++i)
+ {
+ for (uint32_t j = 0; j < num_option_sets; j++)
+ {
+ if (opt_defs[i].usage_mask & 1 << j)
+ {
+ if (opt_defs[i].required)
+ m_required_options[j].insert(opt_defs[i].short_option);
+ else
+ m_optional_options[j].insert(opt_defs[i].short_option);
+ }
+ }
+ }
+ }
+}
+
+uint32_t
+Options::NumCommandOptions ()
+{
+ const OptionDefinition *opt_defs = GetDefinitions ();
+ if (opt_defs == NULL)
+ return 0;
+
+ int i = 0;
+
+ if (opt_defs != NULL)
+ {
+ while (opt_defs[i].long_option != NULL)
+ ++i;
+ }
+
+ return i;
+}
+
+struct option *
+Options::GetLongOptions ()
+{
+ // Check to see if this has already been done.
+ if (m_getopt_table.empty())
+ {
+ // Check to see if there are any options.
+ const uint32_t num_options = NumCommandOptions();
+ if (num_options == 0)
+ return NULL;
+
+ uint32_t i;
+ const OptionDefinition *opt_defs = GetDefinitions();
+
+ std::map<int, uint32_t> option_seen;
+
+ m_getopt_table.resize(num_options + 1);
+ for (i = 0; i < num_options; ++i)
+ {
+ const int short_opt = opt_defs[i].short_option;
+
+ m_getopt_table[i].name = opt_defs[i].long_option;
+ m_getopt_table[i].has_arg = opt_defs[i].option_has_arg;
+ m_getopt_table[i].flag = NULL;
+ m_getopt_table[i].val = short_opt;
+
+ if (option_seen.find(short_opt) == option_seen.end())
+ {
+ option_seen[short_opt] = i;
+ }
+ else if (short_opt)
+ {
+ m_getopt_table[i].val = 0;
+ std::map<int, uint32_t>::const_iterator pos = option_seen.find(short_opt);
+ StreamString strm;
+ if (isprint8(short_opt))
+ Host::SystemLog (Host::eSystemLogError, "option[%u] --%s has a short option -%c that conflicts with option[%u] --%s, short option won't be used for --%s\n",
+ i,
+ opt_defs[i].long_option,
+ short_opt,
+ pos->second,
+ m_getopt_table[pos->second].name,
+ opt_defs[i].long_option);
+ else
+ Host::SystemLog (Host::eSystemLogError, "option[%u] --%s has a short option 0x%x that conflicts with option[%u] --%s, short option won't be used for --%s\n",
+ i,
+ opt_defs[i].long_option,
+ short_opt,
+ pos->second,
+ m_getopt_table[pos->second].name,
+ opt_defs[i].long_option);
+ }
+ }
+
+ //getopt_long_only requires a NULL final entry in the table:
+
+ m_getopt_table[i].name = NULL;
+ m_getopt_table[i].has_arg = 0;
+ m_getopt_table[i].flag = NULL;
+ m_getopt_table[i].val = 0;
+ }
+
+ if (m_getopt_table.empty())
+ return NULL;
+
+ return &m_getopt_table.front();
+}
+
+
+// This function takes INDENT, which tells how many spaces to output at the front of each line; SPACES, which is
+// a string containing 80 spaces; and TEXT, which is the text that is to be output. It outputs the text, on
+// multiple lines if necessary, to RESULT, with INDENT spaces at the front of each line. It breaks lines on spaces,
+// tabs or newlines, shortening the line if necessary to not break in the middle of a word. It assumes that each
+// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
+
+
+void
+Options::OutputFormattedUsageText
+(
+ Stream &strm,
+ const char *text,
+ uint32_t output_max_columns
+)
+{
+ int len = strlen (text);
+
+ // Will it all fit on one line?
+
+ if ((len + strm.GetIndentLevel()) < output_max_columns)
+ {
+ // Output it as a single line.
+ strm.Indent (text);
+ strm.EOL();
+ }
+ else
+ {
+ // We need to break it up into multiple lines.
+
+ int text_width = output_max_columns - strm.GetIndentLevel() - 1;
+ int start = 0;
+ int end = start;
+ int final_end = strlen (text);
+ int sub_len;
+
+ while (end < final_end)
+ {
+ // Don't start the 'text' on a space, since we're already outputting the indentation.
+ 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();
+ strm.Indent();
+ assert (start < final_end);
+ assert (start + sub_len <= final_end);
+ strm.Write(text + start, sub_len);
+ start = end + 1;
+ }
+ strm.EOL();
+ }
+}
+
+bool
+Options::SupportsLongOption (const char *long_option)
+{
+ if (long_option && long_option[0])
+ {
+ const OptionDefinition *opt_defs = GetDefinitions ();
+ if (opt_defs)
+ {
+ const char *long_option_name = long_option;
+ if (long_option[0] == '-' && long_option[1] == '-')
+ long_option_name += 2;
+
+ for (uint32_t i = 0; opt_defs[i].long_option; ++i)
+ {
+ if (strcmp(opt_defs[i].long_option, long_option_name) == 0)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+enum OptionDisplayType
+{
+ eDisplayBestOption,
+ eDisplayShortOption,
+ eDisplayLongOption
+};
+
+static bool
+PrintOption (const OptionDefinition &opt_def,
+ OptionDisplayType display_type,
+ const char *header,
+ const char *footer,
+ bool show_optional,
+ Stream &strm)
+{
+ const bool has_short_option = isprint8(opt_def.short_option) != 0;
+
+ if (display_type == eDisplayShortOption && !has_short_option)
+ return false;
+
+ if (header && header[0])
+ strm.PutCString(header);
+
+ if (show_optional && !opt_def.required)
+ strm.PutChar('[');
+ const bool show_short_option = has_short_option && display_type != eDisplayLongOption;
+ if (show_short_option)
+ strm.Printf ("-%c", opt_def.short_option);
+ else
+ strm.Printf ("--%s", opt_def.long_option);
+ switch (opt_def.option_has_arg)
+ {
+ case no_argument:
+ break;
+ case required_argument:
+ strm.Printf (" <%s>", CommandObject::GetArgumentName (opt_def.argument_type));
+ break;
+
+ case optional_argument:
+ strm.Printf ("%s[<%s>]",
+ show_short_option ? "" : "=",
+ CommandObject::GetArgumentName (opt_def.argument_type));
+ break;
+ }
+ if (show_optional && !opt_def.required)
+ strm.PutChar(']');
+ if (footer && footer[0])
+ strm.PutCString(footer);
+ return true;
+}
+
+void
+Options::GenerateOptionUsage
+(
+ Stream &strm,
+ CommandObject *cmd
+)
+{
+ const uint32_t screen_width = m_interpreter.GetDebugger().GetTerminalWidth();
+
+ const OptionDefinition *opt_defs = GetDefinitions();
+ const uint32_t save_indent_level = strm.GetIndentLevel();
+ const char *name;
+
+ StreamString arguments_str;
+
+ if (cmd)
+ {
+ name = cmd->GetCommandName();
+ cmd->GetFormattedCommandArguments (arguments_str);
+ }
+ else
+ name = "";
+
+ strm.PutCString ("\nCommand Options Usage:\n");
+
+ strm.IndentMore(2);
+
+ // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
+ // <cmd> [options-for-level-1]
+ // etc.
+
+ const uint32_t num_options = NumCommandOptions();
+ if (num_options == 0)
+ return;
+
+ uint32_t num_option_sets = GetRequiredOptions().size();
+
+ uint32_t i;
+
+ for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set)
+ {
+ uint32_t opt_set_mask;
+
+ opt_set_mask = 1 << opt_set;
+ if (opt_set > 0)
+ strm.Printf ("\n");
+ strm.Indent (name);
+
+ // Different option sets may require different args.
+ StreamString args_str;
+ if (cmd)
+ cmd->GetFormattedCommandArguments(args_str, opt_set_mask);
+
+ // First go through and print all options that take no arguments as
+ // a single string. If a command has "-a" "-b" and "-c", this will show
+ // up as [-abc]
+
+ std::set<int> options;
+ std::set<int>::const_iterator options_pos, options_end;
+ for (i = 0; i < num_options; ++i)
+ {
+ if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
+ {
+ // Add current option to the end of out_stream.
+
+ if (opt_defs[i].required == true &&
+ opt_defs[i].option_has_arg == no_argument)
+ {
+ options.insert (opt_defs[i].short_option);
+ }
+ }
+ }
+
+ if (options.empty() == false)
+ {
+ // We have some required options with no arguments
+ strm.PutCString(" -");
+ for (i=0; i<2; ++i)
+ for (options_pos = options.begin(), options_end = options.end();
+ options_pos != options_end;
+ ++options_pos)
+ {
+ if (i==0 && ::islower (*options_pos))
+ continue;
+ if (i==1 && ::isupper (*options_pos))
+ continue;
+ strm << (char)*options_pos;
+ }
+ }
+
+ for (i = 0, options.clear(); i < num_options; ++i)
+ {
+ if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
+ {
+ // Add current option to the end of out_stream.
+
+ if (opt_defs[i].required == false &&
+ opt_defs[i].option_has_arg == no_argument)
+ {
+ options.insert (opt_defs[i].short_option);
+ }
+ }
+ }
+
+ if (options.empty() == false)
+ {
+ // We have some required options with no arguments
+ strm.PutCString(" [-");
+ for (i=0; i<2; ++i)
+ for (options_pos = options.begin(), options_end = options.end();
+ options_pos != options_end;
+ ++options_pos)
+ {
+ if (i==0 && ::islower (*options_pos))
+ continue;
+ if (i==1 && ::isupper (*options_pos))
+ continue;
+ strm << (char)*options_pos;
+ }
+ strm.PutChar(']');
+ }
+
+ // First go through and print the required options (list them up front).
+
+ for (i = 0; i < num_options; ++i)
+ {
+ if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
+ {
+ if (opt_defs[i].required && opt_defs[i].option_has_arg != no_argument)
+ PrintOption (opt_defs[i], eDisplayBestOption, " ", NULL, true, strm);
+ }
+ }
+
+ // Now go through again, and this time only print the optional options.
+
+ for (i = 0; i < num_options; ++i)
+ {
+ if (opt_defs[i].usage_mask & opt_set_mask)
+ {
+ // Add current option to the end of out_stream.
+
+ if (!opt_defs[i].required && opt_defs[i].option_has_arg != no_argument)
+ PrintOption (opt_defs[i], eDisplayBestOption, " ", NULL, true, strm);
+ }
+ }
+
+ if (args_str.GetSize() > 0)
+ {
+ if (cmd->WantsRawCommandString())
+ strm.Printf(" --");
+
+ strm.Printf (" %s", args_str.GetData());
+ }
+ }
+
+ if (cmd &&
+ cmd->WantsRawCommandString() &&
+ arguments_str.GetSize() > 0)
+ {
+ strm.PutChar('\n');
+ strm.Indent(name);
+ strm.Printf(" %s", arguments_str.GetData());
+ }
+
+ strm.Printf ("\n\n");
+
+ // Now print out all the detailed information about the various options: long form, short form and help text:
+ // --long_name <argument> ( -short <argument> )
+ // help text
+
+ // This variable is used to keep track of which options' info we've printed out, because some options can be in
+ // more than one usage level, but we only want to print the long form of its information once.
+
+ std::multimap<int, uint32_t> options_seen;
+ strm.IndentMore (5);
+
+ // Put the unique command options in a vector & sort it, so we can output them alphabetically (by short_option)
+ // when writing out detailed help for each option.
+
+ for (i = 0; i < num_options; ++i)
+ options_seen.insert(std::make_pair(opt_defs[i].short_option, i));
+
+ // Go through the unique'd and alphabetically sorted vector of options, find the table entry for each option
+ // and write out the detailed help information for that option.
+
+ bool first_option_printed = false;;
+
+ for (auto pos : options_seen)
+ {
+ i = pos.second;
+ //Print out the help information for this option.
+
+ // Put a newline separation between arguments
+ if (first_option_printed)
+ strm.EOL();
+ else
+ first_option_printed = true;
+
+ CommandArgumentType arg_type = opt_defs[i].argument_type;
+
+ StreamString arg_name_str;
+ arg_name_str.Printf ("<%s>", CommandObject::GetArgumentName (arg_type));
+
+ strm.Indent ();
+ if (opt_defs[i].short_option && isprint8(opt_defs[i].short_option))
+ {
+ PrintOption (opt_defs[i], eDisplayShortOption, NULL, NULL, false, strm);
+ PrintOption (opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm);
+ }
+ else
+ {
+ // Short option is not printable, just print long option
+ PrintOption (opt_defs[i], eDisplayLongOption, NULL, NULL, false, strm);
+ }
+ strm.EOL();
+
+ strm.IndentMore (5);
+
+ if (opt_defs[i].usage_text)
+ OutputFormattedUsageText (strm,
+ opt_defs[i].usage_text,
+ screen_width);
+ if (opt_defs[i].enum_values != NULL)
+ {
+ strm.Indent ();
+ strm.Printf("Values: ");
+ for (int k = 0; opt_defs[i].enum_values[k].string_value != NULL; k++)
+ {
+ if (k == 0)
+ strm.Printf("%s", opt_defs[i].enum_values[k].string_value);
+ else
+ strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value);
+ }
+ strm.EOL();
+ }
+ strm.IndentLess (5);
+ }
+
+ // Restore the indent level
+ strm.SetIndentLevel (save_indent_level);
+}
+
+// This function is called when we have been given a potentially incomplete set of
+// options, such as when an alias has been defined (more options might be added at
+// at the time the alias is invoked). We need to verify that the options in the set
+// m_seen_options are all part of a set that may be used together, but m_seen_options
+// may be missing some of the "required" options.
+
+bool
+Options::VerifyPartialOptions (CommandReturnObject &result)
+{
+ bool options_are_valid = false;
+
+ int num_levels = GetRequiredOptions().size();
+ if (num_levels)
+ {
+ for (int i = 0; i < num_levels && !options_are_valid; ++i)
+ {
+ // In this case we are treating all options as optional rather than required.
+ // Therefore a set of options is correct if m_seen_options is a subset of the
+ // union of m_required_options and m_optional_options.
+ OptionSet union_set;
+ OptionsSetUnion (GetRequiredOptions()[i], GetOptionalOptions()[i], union_set);
+ if (IsASubset (m_seen_options, union_set))
+ options_are_valid = true;
+ }
+ }
+
+ return options_are_valid;
+}
+
+bool
+Options::HandleOptionCompletion
+(
+ Args &input,
+ OptionElementVector &opt_element_vector,
+ int cursor_index,
+ int char_pos,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ lldb_private::StringList &matches
+)
+{
+ word_complete = true;
+
+ // For now we just scan the completions to see if the cursor position is in
+ // an option or its argument. Otherwise we'll call HandleArgumentCompletion.
+ // In the future we can use completion to validate options as well if we want.
+
+ const OptionDefinition *opt_defs = GetDefinitions();
+
+ std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index));
+ cur_opt_std_str.erase(char_pos);
+ const char *cur_opt_str = cur_opt_std_str.c_str();
+
+ for (size_t i = 0; i < opt_element_vector.size(); i++)
+ {
+ int opt_pos = opt_element_vector[i].opt_pos;
+ int opt_arg_pos = opt_element_vector[i].opt_arg_pos;
+ int opt_defs_index = opt_element_vector[i].opt_defs_index;
+ if (opt_pos == cursor_index)
+ {
+ // We're completing the option itself.
+
+ if (opt_defs_index == OptionArgElement::eBareDash)
+ {
+ // We're completing a bare dash. That means all options are open.
+ // FIXME: We should scan the other options provided and only complete options
+ // within the option group they belong to.
+ char opt_str[3] = {'-', 'a', '\0'};
+
+ for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
+ {
+ opt_str[1] = opt_defs[j].short_option;
+ matches.AppendString (opt_str);
+ }
+ return true;
+ }
+ else if (opt_defs_index == OptionArgElement::eBareDoubleDash)
+ {
+ std::string full_name ("--");
+ for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
+ {
+ full_name.erase(full_name.begin() + 2, full_name.end());
+ full_name.append (opt_defs[j].long_option);
+ matches.AppendString (full_name.c_str());
+ }
+ return true;
+ }
+ else if (opt_defs_index != OptionArgElement::eUnrecognizedArg)
+ {
+ // We recognized it, if it an incomplete long option, complete it anyway (getopt_long_only is
+ // happy with shortest unique string, but it's still a nice thing to do.) Otherwise return
+ // The string so the upper level code will know this is a full match and add the " ".
+ if (cur_opt_str && strlen (cur_opt_str) > 2
+ && cur_opt_str[0] == '-' && cur_opt_str[1] == '-'
+ && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0)
+ {
+ std::string full_name ("--");
+ full_name.append (opt_defs[opt_defs_index].long_option);
+ matches.AppendString(full_name.c_str());
+ return true;
+ }
+ else
+ {
+ matches.AppendString(input.GetArgumentAtIndex(cursor_index));
+ return true;
+ }
+ }
+ else
+ {
+ // FIXME - not handling wrong options yet:
+ // Check to see if they are writing a long option & complete it.
+ // I think we will only get in here if the long option table has two elements
+ // that are not unique up to this point. getopt_long_only does shortest unique match
+ // for long options already.
+
+ if (cur_opt_str && strlen (cur_opt_str) > 2
+ && cur_opt_str[0] == '-' && cur_opt_str[1] == '-')
+ {
+ for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
+ {
+ if (strstr(opt_defs[j].long_option, cur_opt_str + 2) == opt_defs[j].long_option)
+ {
+ std::string full_name ("--");
+ full_name.append (opt_defs[j].long_option);
+ // The options definitions table has duplicates because of the
+ // way the grouping information is stored, so only add once.
+ bool duplicate = false;
+ for (size_t k = 0; k < matches.GetSize(); k++)
+ {
+ if (matches.GetStringAtIndex(k) == full_name)
+ {
+ duplicate = true;
+ break;
+ }
+ }
+ if (!duplicate)
+ matches.AppendString(full_name.c_str());
+ }
+ }
+ }
+ return true;
+ }
+
+
+ }
+ else if (opt_arg_pos == cursor_index)
+ {
+ // Okay the cursor is on the completion of an argument.
+ // See if it has a completion, otherwise return no matches.
+
+ if (opt_defs_index != -1)
+ {
+ HandleOptionArgumentCompletion (input,
+ cursor_index,
+ strlen (input.GetArgumentAtIndex(cursor_index)),
+ opt_element_vector,
+ i,
+ match_start_point,
+ max_return_elements,
+ word_complete,
+ matches);
+ return true;
+ }
+ else
+ {
+ // No completion callback means no completions...
+ return true;
+ }
+
+ }
+ else
+ {
+ // Not the last element, keep going.
+ continue;
+ }
+ }
+ return false;
+}
+
+bool
+Options::HandleOptionArgumentCompletion
+(
+ Args &input,
+ int cursor_index,
+ int char_pos,
+ OptionElementVector &opt_element_vector,
+ int opt_element_index,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ lldb_private::StringList &matches
+)
+{
+ const OptionDefinition *opt_defs = GetDefinitions();
+ std::unique_ptr<SearchFilter> filter_ap;
+
+ int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
+ int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
+
+ // See if this is an enumeration type option, and if so complete it here:
+
+ OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
+ if (enum_values != NULL)
+ {
+ bool return_value = false;
+ std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos);
+ for (int i = 0; enum_values[i].string_value != NULL; i++)
+ {
+ if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value)
+ {
+ matches.AppendString (enum_values[i].string_value);
+ return_value = true;
+ }
+ }
+ return return_value;
+ }
+
+ // If this is a source file or symbol type completion, and there is a
+ // -shlib option somewhere in the supplied arguments, then make a search filter
+ // for that shared library.
+ // FIXME: Do we want to also have an "OptionType" so we don't have to match string names?
+
+ uint32_t completion_mask = opt_defs[opt_defs_index].completion_type;
+
+ if (completion_mask == 0)
+ {
+ lldb::CommandArgumentType option_arg_type = opt_defs[opt_defs_index].argument_type;
+ if (option_arg_type != eArgTypeNone)
+ {
+ CommandObject::ArgumentTableEntry *arg_entry = CommandObject::FindArgumentDataByType (opt_defs[opt_defs_index].argument_type);
+ if (arg_entry)
+ completion_mask = arg_entry->completion_type;
+ }
+ }
+
+ if (completion_mask & CommandCompletions::eSourceFileCompletion
+ || completion_mask & CommandCompletions::eSymbolCompletion)
+ {
+ for (size_t i = 0; i < opt_element_vector.size(); i++)
+ {
+ int cur_defs_index = opt_element_vector[i].opt_defs_index;
+ int cur_arg_pos = opt_element_vector[i].opt_arg_pos;
+ const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
+
+ // If this is the "shlib" option and there was an argument provided,
+ // restrict it to that shared library.
+ if (strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1)
+ {
+ const char *module_name = input.GetArgumentAtIndex(cur_arg_pos);
+ if (module_name)
+ {
+ FileSpec module_spec(module_name, false);
+ lldb::TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
+ // Search filters require a target...
+ if (target_sp)
+ filter_ap.reset (new SearchFilterByModule (target_sp, module_spec));
+ }
+ break;
+ }
+ }
+ }
+
+ return CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
+ completion_mask,
+ input.GetArgumentAtIndex (opt_arg_pos),
+ match_start_point,
+ max_return_elements,
+ filter_ap.get(),
+ word_complete,
+ matches);
+
+}
+
+
+void
+OptionGroupOptions::Append (OptionGroup* group)
+{
+ const OptionDefinition* group_option_defs = group->GetDefinitions ();
+ const uint32_t group_option_count = group->GetNumDefinitions();
+ for (uint32_t i=0; i<group_option_count; ++i)
+ {
+ m_option_infos.push_back (OptionInfo (group, i));
+ m_option_defs.push_back (group_option_defs[i]);
+ }
+}
+
+void
+OptionGroupOptions::Append (OptionGroup* group,
+ uint32_t src_mask,
+ uint32_t dst_mask)
+{
+ const OptionDefinition* group_option_defs = group->GetDefinitions ();
+ const uint32_t group_option_count = group->GetNumDefinitions();
+ for (uint32_t i=0; i<group_option_count; ++i)
+ {
+ if (group_option_defs[i].usage_mask & src_mask)
+ {
+ m_option_infos.push_back (OptionInfo (group, i));
+ m_option_defs.push_back (group_option_defs[i]);
+ m_option_defs.back().usage_mask = dst_mask;
+ }
+ }
+}
+
+void
+OptionGroupOptions::Finalize ()
+{
+ m_did_finalize = true;
+ OptionDefinition empty_option_def = { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL };
+ m_option_defs.push_back (empty_option_def);
+}
+
+Error
+OptionGroupOptions::SetOptionValue (uint32_t option_idx,
+ const char *option_value)
+{
+ // After calling OptionGroupOptions::Append(...), you must finalize the groups
+ // by calling OptionGroupOptions::Finlize()
+ assert (m_did_finalize);
+ assert (m_option_infos.size() + 1 == m_option_defs.size());
+ Error error;
+ if (option_idx < m_option_infos.size())
+ {
+ error = m_option_infos[option_idx].option_group->SetOptionValue (m_interpreter,
+ m_option_infos[option_idx].option_index,
+ option_value);
+
+ }
+ else
+ {
+ error.SetErrorString ("invalid option index"); // Shouldn't happen...
+ }
+ return error;
+}
+
+void
+OptionGroupOptions::OptionParsingStarting ()
+{
+ std::set<OptionGroup*> group_set;
+ OptionInfos::iterator pos, end = m_option_infos.end();
+ for (pos = m_option_infos.begin(); pos != end; ++pos)
+ {
+ OptionGroup* group = pos->option_group;
+ if (group_set.find(group) == group_set.end())
+ {
+ group->OptionParsingStarting (m_interpreter);
+ group_set.insert(group);
+ }
+ }
+}
+Error
+OptionGroupOptions::OptionParsingFinished ()
+{
+ std::set<OptionGroup*> group_set;
+ Error error;
+ OptionInfos::iterator pos, end = m_option_infos.end();
+ for (pos = m_option_infos.begin(); pos != end; ++pos)
+ {
+ OptionGroup* group = pos->option_group;
+ if (group_set.find(group) == group_set.end())
+ {
+ error = group->OptionParsingFinished (m_interpreter);
+ group_set.insert(group);
+ if (error.Fail())
+ return error;
+ }
+ }
+ return error;
+}
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp b/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp
new file mode 100644
index 0000000..e5cf63a
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/Property.cpp
@@ -0,0 +1,275 @@
+//===-- Property.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Interpreter/Property.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/UserSettingsController.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/OptionValues.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+Property::Property (const PropertyDefinition &definition) :
+ m_name (definition.name),
+ m_description (definition.description),
+ m_value_sp (),
+ m_is_global (definition.global)
+{
+ switch (definition.type)
+ {
+ case OptionValue::eTypeInvalid:
+ case OptionValue::eTypeProperties:
+ break;
+ case OptionValue::eTypeArch:
+ // "definition.default_uint_value" is not used
+ // "definition.default_cstr_value" as a string value that represents the default string value for the architecture/triple
+ m_value_sp.reset (new OptionValueArch(definition.default_cstr_value));
+ break;
+
+ case OptionValue::eTypeArgs:
+ // "definition.default_uint_value" is always a OptionValue::Type
+ m_value_sp.reset (new OptionValueArgs());
+ break;
+
+ case OptionValue::eTypeArray:
+ // "definition.default_uint_value" is always a OptionValue::Type
+ m_value_sp.reset (new OptionValueArray(OptionValue::ConvertTypeToMask((OptionValue::Type)definition.default_uint_value)));
+ break;
+
+ case OptionValue::eTypeBoolean:
+ // "definition.default_uint_value" is the default boolean value if
+ // "definition.default_cstr_value" is NULL, otherwise interpret
+ // "definition.default_cstr_value" as a string value that represents the default
+ // value.
+ if (definition.default_cstr_value)
+ m_value_sp.reset (new OptionValueBoolean(Args::StringToBoolean (definition.default_cstr_value, false, NULL)));
+ else
+ m_value_sp.reset (new OptionValueBoolean(definition.default_uint_value != 0));
+ break;
+
+ case OptionValue::eTypeDictionary:
+ // "definition.default_uint_value" is always a OptionValue::Type
+ m_value_sp.reset (new OptionValueDictionary(OptionValue::ConvertTypeToMask((OptionValue::Type)definition.default_uint_value)));
+ break;
+
+ case OptionValue::eTypeEnum:
+ // "definition.default_uint_value" is the default enumeration value if
+ // "definition.default_cstr_value" is NULL, otherwise interpret
+ // "definition.default_cstr_value" as a string value that represents the default
+ // value.
+ {
+ OptionValueEnumeration *enum_value = new OptionValueEnumeration(definition.enum_values, definition.default_uint_value);
+ m_value_sp.reset (enum_value);
+ if (definition.default_cstr_value)
+ {
+ if (enum_value->SetValueFromCString(definition.default_cstr_value).Success())
+ {
+ enum_value->SetDefaultValue(enum_value->GetCurrentValue());
+ // Call Clear() since we don't want the value to appear as
+ // having been set since we called SetValueFromCString() above.
+ // Clear will set the current value to the default and clear
+ // the boolean that says that the value has been set.
+ enum_value->Clear();
+ }
+ }
+ }
+ break;
+
+ case OptionValue::eTypeFileSpec:
+ // "definition.default_uint_value" represents if the "definition.default_cstr_value" should
+ // be resolved or not
+ m_value_sp.reset (new OptionValueFileSpec(FileSpec(definition.default_cstr_value, definition.default_uint_value != 0)));
+ break;
+
+ case OptionValue::eTypeFileSpecList:
+ // "definition.default_uint_value" is not used for a OptionValue::eTypeFileSpecList
+ m_value_sp.reset (new OptionValueFileSpecList());
+ break;
+
+ case OptionValue::eTypeFormat:
+ // "definition.default_uint_value" is the default format enumeration value if
+ // "definition.default_cstr_value" is NULL, otherwise interpret
+ // "definition.default_cstr_value" as a string value that represents the default
+ // value.
+ {
+ Format new_format = eFormatInvalid;
+ if (definition.default_cstr_value)
+ Args::StringToFormat (definition.default_cstr_value, new_format, NULL);
+ else
+ new_format = (Format)definition.default_uint_value;
+ m_value_sp.reset (new OptionValueFormat(new_format));
+ }
+ break;
+
+ case OptionValue::eTypePathMap:
+ // "definition.default_uint_value" tells us if notifications should occur for
+ // path mappings
+ m_value_sp.reset (new OptionValuePathMappings(definition.default_uint_value != 0));
+ break;
+
+ case OptionValue::eTypeRegex:
+ // "definition.default_uint_value" is used to the regular expression flags
+ // "definition.default_cstr_value" the default regular expression value
+ // value.
+ m_value_sp.reset (new OptionValueRegex(definition.default_cstr_value, definition.default_uint_value));
+ break;
+
+ case OptionValue::eTypeSInt64:
+ // "definition.default_uint_value" is the default integer value if
+ // "definition.default_cstr_value" is NULL, otherwise interpret
+ // "definition.default_cstr_value" as a string value that represents the default
+ // value.
+ m_value_sp.reset (new OptionValueSInt64(definition.default_cstr_value ? Args::StringToSInt64 (definition.default_cstr_value) : definition.default_uint_value));
+ break;
+
+ case OptionValue::eTypeUInt64:
+ // "definition.default_uint_value" is the default unsigned integer value if
+ // "definition.default_cstr_value" is NULL, otherwise interpret
+ // "definition.default_cstr_value" as a string value that represents the default
+ // value.
+ m_value_sp.reset (new OptionValueUInt64(definition.default_cstr_value ? Args::StringToUInt64 (definition.default_cstr_value) : definition.default_uint_value));
+ break;
+
+ case OptionValue::eTypeUUID:
+ // "definition.default_uint_value" is not used for a OptionValue::eTypeUUID
+ // "definition.default_cstr_value" can contain a default UUID value
+ {
+ UUID uuid;
+ if (definition.default_cstr_value)
+ uuid.SetFromCString (definition.default_cstr_value);
+ m_value_sp.reset (new OptionValueUUID(uuid));
+ }
+ break;
+
+ case OptionValue::eTypeString:
+ // "definition.default_uint_value" can contain the string option flags OR'ed together
+ // "definition.default_cstr_value" can contain a default string value
+ {
+ OptionValueString *string_value = new OptionValueString(definition.default_cstr_value);
+ if (definition.default_uint_value != 0)
+ string_value->GetOptions().Reset(definition.default_uint_value);
+ m_value_sp.reset (string_value);
+ }
+ break;
+ }
+}
+
+Property::Property (const ConstString &name,
+ const ConstString &desc,
+ bool is_global,
+ const lldb::OptionValueSP &value_sp) :
+ m_name (name),
+ m_description (desc),
+ m_value_sp (value_sp),
+ m_is_global (is_global)
+{
+}
+
+bool
+Property::DumpQualifiedName(Stream &strm) const
+{
+ if (m_name)
+ {
+ if (m_value_sp->DumpQualifiedName(strm))
+ strm.PutChar('.');
+ strm << m_name;
+ return true;
+ }
+ return false;
+}
+
+
+void
+Property::Dump (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) const
+{
+ if (m_value_sp)
+ {
+ const bool dump_desc = dump_mask & OptionValue::eDumpOptionDescription;
+ const bool transparent = m_value_sp->ValueIsTransparent ();
+ if (dump_desc || !transparent)
+ {
+ if ((dump_mask & OptionValue::eDumpOptionName) && m_name)
+ {
+ DumpQualifiedName(strm);
+ if (dump_mask & ~OptionValue::eDumpOptionName)
+ strm.PutChar(' ');
+ }
+ }
+ if (dump_desc)
+ {
+ const char *desc = GetDescription();
+ if (desc)
+ strm.Printf ("-- %s", desc);
+
+ if (transparent && (dump_mask == (OptionValue::eDumpOptionName | OptionValue::eDumpOptionDescription)))
+ strm.EOL();
+ }
+ m_value_sp->DumpValue(exe_ctx, strm, dump_mask);
+ }
+}
+
+
+void
+Property::DumpDescription (CommandInterpreter &interpreter,
+ Stream &strm,
+ uint32_t output_width,
+ bool display_qualified_name) const
+{
+ if (m_value_sp)
+ {
+ const char *desc = GetDescription();
+
+ if (desc)
+ {
+ StreamString qualified_name;
+ const OptionValueProperties *sub_properties = m_value_sp->GetAsProperties();
+ if (sub_properties)
+ {
+ strm.EOL();
+
+ if (m_value_sp->DumpQualifiedName(qualified_name))
+ strm.Printf("'%s' variables:\n\n", qualified_name.GetString().c_str());
+ sub_properties->DumpAllDescriptions(interpreter, strm);
+ }
+ else
+ {
+ if (desc)
+ {
+ if (display_qualified_name)
+ {
+ StreamString qualified_name;
+ DumpQualifiedName(qualified_name);
+ interpreter.OutputFormattedHelpText (strm,
+ qualified_name.GetString().c_str(),
+ "--",
+ desc,
+ output_width);
+ }
+ else
+ {
+ interpreter.OutputFormattedHelpText (strm,
+ m_name.GetCString(),
+ "--",
+ desc,
+ output_width);
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/PythonDataObjects.cpp b/contrib/llvm/tools/lldb/source/Interpreter/PythonDataObjects.cpp
new file mode 100644
index 0000000..2a1f348
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/PythonDataObjects.cpp
@@ -0,0 +1,430 @@
+//===-- PythonDataObjects.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 here.
+#ifdef LLDB_DISABLE_PYTHON
+
+// Python is disabled in this build
+
+#else
+
+#if defined (__APPLE__)
+#include <Python/Python.h>
+#else
+#include <Python.h>
+#endif
+
+#include <stdio.h>
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Host/File.h"
+#include "lldb/Interpreter/PythonDataObjects.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+//----------------------------------------------------------------------
+// PythonObject
+//----------------------------------------------------------------------
+PythonObject::PythonObject (const lldb::ScriptInterpreterObjectSP &script_object_sp) :
+ m_py_obj (NULL)
+{
+ if (script_object_sp)
+ Reset ((PyObject *)script_object_sp->GetObject());
+}
+
+void
+PythonObject::Dump (Stream &strm) const
+{
+ if (m_py_obj)
+ {
+ FILE *file = ::tmpfile();
+ if (file)
+ {
+ ::PyObject_Print (m_py_obj, file, 0);
+ const long length = ftell (file);
+ if (length)
+ {
+ ::rewind(file);
+ std::vector<char> file_contents (length,'\0');
+ const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file);
+ if (length_read > 0)
+ strm.Write (file_contents.data(), length_read);
+ }
+ ::fclose (file);
+ }
+ }
+ else
+ strm.PutCString ("NULL");
+}
+
+PythonString
+PythonObject::Repr ()
+{
+ if (!m_py_obj)
+ return PythonString ();
+ PyObject *repr = PyObject_Repr(m_py_obj);
+ if (!repr)
+ return PythonString ();
+ return PythonString(repr);
+}
+
+PythonString
+PythonObject::Str ()
+{
+ if (!m_py_obj)
+ return PythonString ();
+ PyObject *str = PyObject_Str(m_py_obj);
+ if (!str)
+ return PythonString ();
+ return PythonString(str);
+}
+
+//----------------------------------------------------------------------
+// PythonString
+//----------------------------------------------------------------------
+
+PythonString::PythonString (PyObject *py_obj) :
+ PythonObject(py_obj)
+{
+}
+
+PythonString::PythonString (const PythonObject &object) :
+ PythonObject(object.GetPythonObject())
+{
+}
+
+PythonString::PythonString (const lldb::ScriptInterpreterObjectSP &script_object_sp) :
+ PythonObject (script_object_sp)
+{
+}
+
+PythonString::PythonString (const char* string) :
+ PythonObject(PyString_FromString(string))
+{
+}
+
+PythonString::PythonString () :
+ PythonObject()
+{
+}
+
+PythonString::~PythonString ()
+{
+}
+
+bool
+PythonString::Reset (PyObject *py_obj)
+{
+ if (py_obj && PyString_Check(py_obj))
+ return PythonObject::Reset(py_obj);
+
+ PythonObject::Reset(NULL);
+ return py_obj == NULL;
+}
+
+const char*
+PythonString::GetString() const
+{
+ if (m_py_obj)
+ return PyString_AsString(m_py_obj);
+ return NULL;
+}
+
+size_t
+PythonString::GetSize() const
+{
+ if (m_py_obj)
+ return PyString_Size(m_py_obj);
+ return 0;
+}
+
+void
+PythonString::SetString (const char* string)
+{
+ PythonObject::Reset(PyString_FromString(string));
+}
+
+//----------------------------------------------------------------------
+// PythonInteger
+//----------------------------------------------------------------------
+
+PythonInteger::PythonInteger (PyObject *py_obj) :
+ PythonObject(py_obj)
+{
+}
+
+PythonInteger::PythonInteger (const PythonObject &object) :
+ PythonObject(object.GetPythonObject())
+{
+}
+
+PythonInteger::PythonInteger (const lldb::ScriptInterpreterObjectSP &script_object_sp) :
+ PythonObject (script_object_sp)
+{
+}
+
+PythonInteger::PythonInteger (int64_t value) :
+ PythonObject(PyInt_FromLong(value))
+{
+}
+
+
+PythonInteger::~PythonInteger ()
+{
+}
+
+bool
+PythonInteger::Reset (PyObject *py_obj)
+{
+ if (py_obj && PyInt_Check(py_obj))
+ return PythonObject::Reset(py_obj);
+
+ PythonObject::Reset(NULL);
+ return py_obj == NULL;
+}
+
+int64_t
+PythonInteger::GetInteger()
+{
+ if (m_py_obj)
+ return PyInt_AsLong(m_py_obj);
+ else
+ return UINT64_MAX;
+}
+
+void
+PythonInteger::SetInteger (int64_t value)
+{
+ PythonObject::Reset(PyInt_FromLong(value));
+}
+
+//----------------------------------------------------------------------
+// PythonList
+//----------------------------------------------------------------------
+
+PythonList::PythonList () :
+ PythonObject(PyList_New(0))
+{
+}
+
+PythonList::PythonList (uint32_t count) :
+ PythonObject(PyList_New(count))
+{
+}
+
+PythonList::PythonList (PyObject *py_obj) :
+ PythonObject(py_obj)
+{
+}
+
+
+PythonList::PythonList (const PythonObject &object) :
+ PythonObject(object.GetPythonObject())
+{
+}
+
+PythonList::PythonList (const lldb::ScriptInterpreterObjectSP &script_object_sp) :
+ PythonObject (script_object_sp)
+{
+}
+
+PythonList::~PythonList ()
+{
+}
+
+bool
+PythonList::Reset (PyObject *py_obj)
+{
+ if (py_obj && PyList_Check(py_obj))
+ return PythonObject::Reset(py_obj);
+
+ PythonObject::Reset(NULL);
+ return py_obj == NULL;
+}
+
+uint32_t
+PythonList::GetSize()
+{
+ if (m_py_obj)
+ return PyList_GET_SIZE(m_py_obj);
+ return 0;
+}
+
+PythonObject
+PythonList::GetItemAtIndex (uint32_t index)
+{
+ if (m_py_obj)
+ return PythonObject(PyList_GetItem(m_py_obj, index));
+ return NULL;
+}
+
+void
+PythonList::SetItemAtIndex (uint32_t index, const PythonObject & object)
+{
+ if (m_py_obj && object)
+ PyList_SetItem(m_py_obj, index, object.GetPythonObject());
+}
+
+void
+PythonList::AppendItem (const PythonObject &object)
+{
+ if (m_py_obj && object)
+ PyList_Append(m_py_obj, object.GetPythonObject());
+}
+
+//----------------------------------------------------------------------
+// PythonDictionary
+//----------------------------------------------------------------------
+
+PythonDictionary::PythonDictionary () :
+ PythonObject(PyDict_New())
+{
+}
+
+PythonDictionary::PythonDictionary (PyObject *py_obj) :
+ PythonObject(py_obj)
+{
+}
+
+
+PythonDictionary::PythonDictionary (const PythonObject &object) :
+ PythonObject(object.GetPythonObject())
+{
+}
+
+PythonDictionary::PythonDictionary (const lldb::ScriptInterpreterObjectSP &script_object_sp) :
+ PythonObject (script_object_sp)
+{
+}
+
+PythonDictionary::~PythonDictionary ()
+{
+}
+
+bool
+PythonDictionary::Reset (PyObject *py_obj)
+{
+ if (py_obj && PyDict_Check(py_obj))
+ return PythonObject::Reset(py_obj);
+
+ PythonObject::Reset(NULL);
+ return py_obj == NULL;
+}
+
+uint32_t
+PythonDictionary::GetSize()
+{
+ if (m_py_obj)
+ return PyDict_Size(m_py_obj);
+ return 0;
+}
+
+PythonObject
+PythonDictionary::GetItemForKey (const char *key) const
+{
+ if (key && key[0])
+ {
+ PythonString python_key(key);
+ return GetItemForKey(python_key);
+ }
+ return NULL;
+}
+
+
+PythonObject
+PythonDictionary::GetItemForKey (const PythonString &key) const
+{
+ if (m_py_obj && key)
+ return PythonObject(PyDict_GetItem(m_py_obj, key.GetPythonObject()));
+ return PythonObject();
+}
+
+
+const char *
+PythonDictionary::GetItemForKeyAsString (const PythonString &key, const char *fail_value) const
+{
+ if (m_py_obj && key)
+ {
+ PyObject *py_obj = PyDict_GetItem(m_py_obj, key.GetPythonObject());
+ if (py_obj && PyString_Check(py_obj))
+ return PyString_AsString(py_obj);
+ }
+ return fail_value;
+}
+
+int64_t
+PythonDictionary::GetItemForKeyAsInteger (const PythonString &key, int64_t fail_value) const
+{
+ if (m_py_obj && key)
+ {
+ PyObject *py_obj = PyDict_GetItem(m_py_obj, key.GetPythonObject());
+ if (py_obj)
+ {
+ if (PyInt_Check(py_obj))
+ return PyInt_AsLong(py_obj);
+
+ if (PyLong_Check(py_obj))
+ return PyLong_AsLong(py_obj);
+ }
+ }
+ return fail_value;
+}
+
+PythonList
+PythonDictionary::GetKeys () const
+{
+ if (m_py_obj)
+ return PythonList(PyDict_Keys(m_py_obj));
+ return PythonList();
+}
+
+PythonString
+PythonDictionary::GetKeyAtPosition (uint32_t pos) const
+{
+ PyObject *key, *value;
+ Py_ssize_t pos_iter = 0;
+
+ if (m_py_obj)
+ {
+ while (PyDict_Next(m_py_obj, &pos_iter, &key, &value))
+ {
+ if (pos-- == 0)
+ return PythonString(key);
+ }
+ }
+ return PythonString();
+}
+
+PythonObject
+PythonDictionary::GetValueAtPosition (uint32_t pos) const
+{
+ PyObject *key, *value;
+ Py_ssize_t pos_iter = 0;
+
+ if (!m_py_obj)
+ return NULL;
+
+ while (PyDict_Next(m_py_obj, &pos_iter, &key, &value)) {
+ if (pos-- == 0)
+ return PythonObject(value);
+ }
+ return PythonObject();
+}
+
+void
+PythonDictionary::SetItemForKey (const PythonString &key, const PythonObject &value)
+{
+ if (m_py_obj && key && value)
+ PyDict_SetItem(m_py_obj, key.GetPythonObject(), value.GetPythonObject());
+}
+
+#endif
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreter.cpp b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreter.cpp
new file mode 100644
index 0000000..6731473
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -0,0 +1,105 @@
+//===-- 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/lldb-python.h"
+
+#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 "lldb/Interpreter/ScriptInterpreterPython.h"
+#include "lldb/Utility/PseudoTerminal.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ScriptInterpreter::ScriptInterpreter (CommandInterpreter &interpreter, lldb::ScriptLanguage script_lang) :
+ m_interpreter (interpreter),
+ m_script_lang (script_lang)
+{
+}
+
+ScriptInterpreter::~ScriptInterpreter ()
+{
+}
+
+CommandInterpreter &
+ScriptInterpreter::GetCommandInterpreter ()
+{
+ return m_interpreter;
+}
+
+void
+ScriptInterpreter::CollectDataForBreakpointCommandCallback
+(
+ BreakpointOptions *bp_options,
+ CommandReturnObject &result
+)
+{
+ result.SetStatus (eReturnStatusFailed);
+ result.AppendError ("ScriptInterpreter::GetScriptCommands(StringList &) is not implemented.");
+}
+
+void
+ScriptInterpreter::CollectDataForWatchpointCommandCallback
+(
+ WatchpointOptions *bp_options,
+ CommandReturnObject &result
+)
+{
+ result.SetStatus (eReturnStatusFailed);
+ result.AppendError ("ScriptInterpreter::GetScriptCommands(StringList &) is not implemented.");
+}
+
+std::string
+ScriptInterpreter::LanguageToString (lldb::ScriptLanguage language)
+{
+ std::string return_value;
+
+ switch (language)
+ {
+ case eScriptLanguageNone:
+ return_value = "None";
+ break;
+ case eScriptLanguagePython:
+ return_value = "Python";
+ break;
+ }
+
+ return return_value;
+}
+
+std::unique_ptr<ScriptInterpreterLocker>
+ScriptInterpreter::AcquireInterpreterLock ()
+{
+ return std::unique_ptr<ScriptInterpreterLocker>(new ScriptInterpreterLocker());
+}
+
+void
+ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_callback)
+{
+#ifndef LLDB_DISABLE_PYTHON
+ ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback);
+#endif // #ifndef LLDB_DISABLE_PYTHON
+}
+
+void
+ScriptInterpreter::TerminateInterpreter ()
+{
+#ifndef LLDB_DISABLE_PYTHON
+ ScriptInterpreterPython::TerminateInterpreter ();
+#endif // #ifndef LLDB_DISABLE_PYTHON
+}
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterNone.cpp b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterNone.cpp
new file mode 100644
index 0000000..6a44114
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterNone.cpp
@@ -0,0 +1,43 @@
+//===-- 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/lldb-python.h"
+
+#include "lldb/Interpreter/ScriptInterpreterNone.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ScriptInterpreterNone::ScriptInterpreterNone (CommandInterpreter &interpreter) :
+ ScriptInterpreter (interpreter, eScriptLanguageNone)
+{
+}
+
+ScriptInterpreterNone::~ScriptInterpreterNone ()
+{
+}
+
+bool
+ScriptInterpreterNone::ExecuteOneLine (const char *command, CommandReturnObject *, const ExecuteScriptOptions&)
+{
+ m_interpreter.GetDebugger().GetErrorStream().PutCString ("error: there is no embedded script interpreter in this mode.\n");
+ return false;
+}
+
+void
+ScriptInterpreterNone::ExecuteInterpreterLoop ()
+{
+ m_interpreter.GetDebugger().GetErrorStream().PutCString ("error: there is no embedded script interpreter in this mode.\n");
+}
+
+
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp
new file mode 100644
index 0000000..9d9b8d9
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp
@@ -0,0 +1,3166 @@
+//===-- 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 here.
+#ifdef LLDB_DISABLE_PYTHON
+
+// Python is disabled in this build
+
+#else
+
+#if defined (__APPLE__)
+#include <Python/Python.h>
+#else
+#include <Python.h>
+#endif
+
+#include "lldb/Interpreter/ScriptInterpreterPython.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <string>
+
+#include "lldb/API/SBValue.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Breakpoint/WatchpointOptions.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = NULL;
+static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = NULL;
+static ScriptInterpreter::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = NULL;
+static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = NULL;
+static ScriptInterpreter::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = NULL;
+static ScriptInterpreter::SWIGPythonCalculateNumChildren g_swig_calc_children = NULL;
+static ScriptInterpreter::SWIGPythonGetChildAtIndex g_swig_get_child_index = NULL;
+static ScriptInterpreter::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = NULL;
+static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = NULL;
+static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = NULL;
+static ScriptInterpreter::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = NULL;
+static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = NULL;
+static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = NULL;
+static ScriptInterpreter::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = NULL;
+static ScriptInterpreter::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = NULL;
+static ScriptInterpreter::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = NULL;
+static ScriptInterpreter::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = NULL;
+static ScriptInterpreter::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = NULL;
+
+// these are the Pythonic implementations of the required callbacks
+// these are scripting-language specific, which is why they belong here
+// we still need to use function pointers to them instead of relying
+// on linkage-time resolution because the SWIG stuff and this file
+// get built at different times
+extern "C" bool
+LLDBSwigPythonBreakpointCallbackFunction (const char *python_function_name,
+ const char *session_dictionary_name,
+ const lldb::StackFrameSP& sb_frame,
+ const lldb::BreakpointLocationSP& sb_bp_loc);
+
+extern "C" bool
+LLDBSwigPythonWatchpointCallbackFunction (const char *python_function_name,
+ const char *session_dictionary_name,
+ const lldb::StackFrameSP& sb_frame,
+ const lldb::WatchpointSP& sb_wp);
+
+extern "C" bool
+LLDBSwigPythonCallTypeScript (const char *python_function_name,
+ void *session_dictionary,
+ const lldb::ValueObjectSP& valobj_sp,
+ void** pyfunct_wrapper,
+ std::string& retval);
+
+extern "C" void*
+LLDBSwigPythonCreateSyntheticProvider (const char *python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ValueObjectSP& valobj_sp);
+
+
+extern "C" uint32_t
+LLDBSwigPython_CalculateNumChildren (void *implementor);
+
+extern "C" void *
+LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx);
+
+extern "C" int
+LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name);
+
+extern "C" void *
+LLDBSWIGPython_CastPyObjectToSBValue (void* data);
+
+extern "C" bool
+LLDBSwigPython_UpdateSynthProviderInstance (void* implementor);
+
+extern "C" bool
+LLDBSwigPython_MightHaveChildrenSynthProviderInstance (void* implementor);
+
+extern "C" bool
+LLDBSwigPythonCallCommand (const char *python_function_name,
+ const char *session_dictionary_name,
+ lldb::DebuggerSP& debugger,
+ const char* args,
+ lldb_private::CommandReturnObject &cmd_retobj);
+
+extern "C" bool
+LLDBSwigPythonCallModuleInit (const char *python_module_name,
+ const char *session_dictionary_name,
+ lldb::DebuggerSP& debugger);
+
+extern "C" void*
+LLDBSWIGPythonCreateOSPlugin (const char *python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ProcessSP& process_sp);
+
+extern "C" bool
+LLDBSWIGPythonRunScriptKeywordProcess (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::ProcessSP& process,
+ std::string& output);
+
+extern "C" bool
+LLDBSWIGPythonRunScriptKeywordThread (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::ThreadSP& thread,
+ std::string& output);
+
+extern "C" bool
+LLDBSWIGPythonRunScriptKeywordTarget (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::TargetSP& target,
+ std::string& output);
+
+extern "C" bool
+LLDBSWIGPythonRunScriptKeywordFrame (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::StackFrameSP& frame,
+ std::string& output);
+
+static int
+_check_and_flush (FILE *stream)
+{
+ int prev_fail = ferror (stream);
+ return fflush (stream) || prev_fail ? EOF : 0;
+}
+
+ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *py_interpreter,
+ uint16_t on_entry,
+ uint16_t on_leave,
+ FILE* wait_msg_handle) :
+ ScriptInterpreterLocker (),
+ m_teardown_session( (on_leave & TearDownSession) == TearDownSession ),
+ m_python_interpreter(py_interpreter),
+ m_tmp_fh(wait_msg_handle)
+{
+ if (m_python_interpreter && !m_tmp_fh)
+ m_tmp_fh = (m_python_interpreter->m_dbg_stdout ? m_python_interpreter->m_dbg_stdout : stdout);
+
+ DoAcquireLock();
+ if ((on_entry & InitSession) == InitSession)
+ {
+ if (DoInitSession((on_entry & InitGlobals) == InitGlobals) == false)
+ {
+ // Don't teardown the session if we didn't init it.
+ m_teardown_session = false;
+ }
+ }
+}
+
+bool
+ScriptInterpreterPython::Locker::DoAcquireLock()
+{
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
+ m_GILState = PyGILState_Ensure();
+ if (log)
+ log->Printf("Ensured PyGILState. Previous state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : "");
+ return true;
+}
+
+bool
+ScriptInterpreterPython::Locker::DoInitSession(bool init_lldb_globals)
+{
+ if (!m_python_interpreter)
+ return false;
+ return m_python_interpreter->EnterSession (init_lldb_globals);
+}
+
+bool
+ScriptInterpreterPython::Locker::DoFreeLock()
+{
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
+ if (log)
+ log->Printf("Releasing PyGILState. Returning to state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : "");
+ PyGILState_Release(m_GILState);
+ return true;
+}
+
+bool
+ScriptInterpreterPython::Locker::DoTearDownSession()
+{
+ if (!m_python_interpreter)
+ return false;
+ m_python_interpreter->LeaveSession ();
+ return true;
+}
+
+ScriptInterpreterPython::Locker::~Locker()
+{
+ if (m_teardown_session)
+ DoTearDownSession();
+ DoFreeLock();
+}
+
+ScriptInterpreterPython::PythonInputReaderManager::PythonInputReaderManager (ScriptInterpreterPython *interpreter) :
+m_interpreter(interpreter),
+m_debugger_sp(),
+m_reader_sp(),
+m_error(false)
+{
+ if (m_interpreter == NULL)
+ {
+ m_error = true;
+ return;
+ }
+
+ m_debugger_sp = m_interpreter->GetCommandInterpreter().GetDebugger().shared_from_this();
+
+ if (!m_debugger_sp)
+ {
+ m_error = true;
+ return;
+ }
+
+ m_reader_sp = InputReaderSP(new InputReader(*m_debugger_sp.get()));
+
+ if (!m_reader_sp)
+ {
+ m_error = true;
+ return;
+ }
+
+ Error error (m_reader_sp->Initialize (ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback,
+ m_interpreter, // baton
+ eInputReaderGranularityLine, // token size, to pass to callback function
+ NULL, // end token
+ NULL, // prompt
+ true)); // echo input
+ if (error.Fail())
+ m_error = true;
+ else
+ {
+ m_debugger_sp->PushInputReader (m_reader_sp);
+ m_interpreter->m_embedded_thread_input_reader_sp = m_reader_sp;
+ }
+}
+
+ScriptInterpreterPython::PythonInputReaderManager::~PythonInputReaderManager()
+{
+ // Nothing to do if either m_interpreter or m_reader_sp is invalid.
+ if (!m_interpreter || !m_reader_sp)
+ return;
+
+ m_reader_sp->SetIsDone (true);
+ if (m_debugger_sp)
+ m_debugger_sp->PopInputReader(m_reader_sp);
+
+ // Only mess with m_interpreter's counterpart if, indeed, they are the same object.
+ if (m_reader_sp.get() == m_interpreter->m_embedded_thread_input_reader_sp.get())
+ {
+ m_interpreter->m_embedded_thread_pty.CloseSlaveFileDescriptor();
+ m_interpreter->m_embedded_thread_input_reader_sp.reset();
+ }
+}
+
+size_t
+ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback (void *baton,
+ InputReader &reader,
+ InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len)
+{
+ lldb::thread_t embedded_interpreter_thread;
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+
+ if (baton == NULL)
+ return 0;
+
+ ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
+
+ if (script_interpreter->m_script_lang != eScriptLanguagePython)
+ return 0;
+
+ switch (notification)
+ {
+ case eInputReaderActivate:
+ {
+ // Save terminal settings if we can
+ int input_fd = reader.GetDebugger().GetInputFile().GetDescriptor();
+ if (input_fd == File::kInvalidDescriptor)
+ input_fd = STDIN_FILENO;
+
+ script_interpreter->SaveTerminalState(input_fd);
+
+ char error_str[1024];
+ if (script_interpreter->m_embedded_thread_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str,
+ sizeof(error_str)))
+ {
+ if (log)
+ log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, succeeded in opening master pty (fd = %d).",
+ script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor());
+ {
+ StreamString run_string;
+ char error_str[1024];
+ const char *pty_slave_name = script_interpreter->m_embedded_thread_pty.GetSlaveName (error_str, sizeof (error_str));
+ if (pty_slave_name != NULL && PyThreadState_GetDict() != NULL)
+ {
+ ScriptInterpreterPython::Locker locker(script_interpreter,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | ScriptInterpreterPython::Locker::InitGlobals,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
+ run_string.Printf ("run_one_line (%s, 'save_stderr = sys.stderr')", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear ();
+
+ run_string.Printf ("run_one_line (%s, 'sys.stderr = sys.stdout')", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear ();
+
+ run_string.Printf ("run_one_line (%s, 'save_stdin = sys.stdin')", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear ();
+
+ run_string.Printf ("run_one_line (%s, \"sys.stdin = open ('%s', 'r')\")", script_interpreter->m_dictionary_name.c_str(),
+ pty_slave_name);
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear ();
+ }
+ }
+ embedded_interpreter_thread = Host::ThreadCreate ("<lldb.script-interpreter.noninteractive-python>",
+ ScriptInterpreterPython::PythonInputReaderManager::RunPythonInputReader,
+ script_interpreter, NULL);
+ if (IS_VALID_LLDB_HOST_THREAD(embedded_interpreter_thread))
+ {
+ if (log)
+ log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, succeeded in creating thread (thread_t = %p)", (void *)embedded_interpreter_thread);
+ Error detach_error;
+ Host::ThreadDetach (embedded_interpreter_thread, &detach_error);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, failed in creating thread");
+ reader.SetIsDone (true);
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, failed to open master pty ");
+ reader.SetIsDone (true);
+ }
+ }
+ break;
+
+ case eInputReaderDeactivate:
+ // When another input reader is pushed, don't leave the session...
+ //script_interpreter->LeaveSession ();
+ break;
+
+ case eInputReaderReactivate:
+// {
+// ScriptInterpreterPython::Locker locker(script_interpreter,
+// ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
+// ScriptInterpreterPython::Locker::FreeAcquiredLock);
+// }
+ break;
+
+ case eInputReaderAsynchronousOutputWritten:
+ break;
+
+ case eInputReaderInterrupt:
+ {
+ PyThreadState* state = _PyThreadState_Current;
+ if (!state)
+ state = script_interpreter->m_command_thread_state;
+ if (state)
+ {
+ long tid = state->thread_id;
+ _PyThreadState_Current = state;
+ int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);
+ if (log)
+ log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, tid = %ld, num_threads = %d, state = %p",
+ tid,num_threads,state);
+ }
+ else if (log)
+ log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, state = NULL");
+ }
+ break;
+
+ case eInputReaderEndOfFile:
+ reader.SetIsDone(true);
+ break;
+
+ case eInputReaderGotToken:
+ if (script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor() != -1)
+ {
+ if (log)
+ log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, GotToken, bytes='%s', byte_len = %lu", bytes,
+ bytes_len);
+ if (bytes && bytes_len)
+ ::write (script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor(), bytes, bytes_len);
+ ::write (script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor(), "\n", 1);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, GotToken, bytes='%s', byte_len = %lu, Master File Descriptor is bad.",
+ bytes,
+ bytes_len);
+ reader.SetIsDone (true);
+ }
+ break;
+
+ case eInputReaderDone:
+ {
+ StreamString run_string;
+ char error_str[1024];
+ const char *pty_slave_name = script_interpreter->m_embedded_thread_pty.GetSlaveName (error_str, sizeof (error_str));
+ if (pty_slave_name != NULL && PyThreadState_GetDict() != NULL)
+ {
+ ScriptInterpreterPython::Locker locker(script_interpreter,
+ ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
+ run_string.Printf ("run_one_line (%s, 'sys.stdin = save_stdin; sys.stderr = save_stderr')", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear();
+ }
+ // Restore terminal settings if they were validly saved
+ if (log)
+ log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Done, closing down input reader.");
+
+ script_interpreter->RestoreTerminalState ();
+
+ script_interpreter->m_embedded_thread_pty.CloseMasterFileDescriptor();
+ }
+ break;
+ }
+
+ return bytes_len;
+}
+
+ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interpreter) :
+ ScriptInterpreter (interpreter, eScriptLanguagePython),
+ m_embedded_thread_pty (),
+ m_embedded_python_pty (),
+ m_embedded_thread_input_reader_sp (),
+ m_embedded_python_input_reader_sp (),
+ m_dbg_stdout (interpreter.GetDebugger().GetOutputFile().GetStream()),
+ m_new_sysout (NULL),
+ m_old_sysout (NULL),
+ m_old_syserr (NULL),
+ m_run_one_line (NULL),
+ m_dictionary_name (interpreter.GetDebugger().GetInstanceName().AsCString()),
+ m_terminal_state (),
+ m_session_is_active (false),
+ m_valid_session (true),
+ m_command_thread_state (NULL)
+{
+
+ static int g_initialized = false;
+
+ if (!g_initialized)
+ {
+ g_initialized = true;
+ ScriptInterpreterPython::InitializePrivate ();
+ }
+
+ m_dictionary_name.append("_dict");
+ StreamString run_string;
+ run_string.Printf ("%s = dict()", m_dictionary_name.c_str());
+
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
+ PyRun_SimpleString (run_string.GetData());
+
+ run_string.Clear();
+
+ // Importing 'lldb' module calls SBDebugger::Initialize, which calls Debugger::Initialize, which increments a
+ // global debugger ref-count; therefore we need to check the ref-count before and after importing lldb, and if the
+ // ref-count increased we need to call Debugger::Terminate here to decrement the ref-count so that when the final
+ // call to Debugger::Terminate is made, the ref-count has the correct value.
+ //
+ // Bonus question: Why doesn't the ref-count always increase? Because sometimes lldb has already been imported, in
+ // which case the code inside it, including the call to SBDebugger::Initialize(), does not get executed.
+
+ int old_count = Debugger::TestDebuggerRefCount();
+
+ run_string.Printf ("run_one_line (%s, 'import copy, os, re, sys, uuid, lldb')", m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+
+ // WARNING: temporary code that loads Cocoa formatters - this should be done on a per-platform basis rather than loading the whole set
+ // and letting the individual formatter classes exploit APIs to check whether they can/cannot do their task
+ run_string.Clear();
+ run_string.Printf ("run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')", m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+
+ int new_count = Debugger::TestDebuggerRefCount();
+
+ if (new_count > old_count)
+ Debugger::Terminate();
+
+ run_string.Clear();
+ run_string.Printf ("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64 "; pydoc.pager = pydoc.plainpager')", m_dictionary_name.c_str(),
+ interpreter.GetDebugger().GetID());
+ PyRun_SimpleString (run_string.GetData());
+
+ if (m_dbg_stdout != NULL)
+ {
+ m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush);
+ }
+
+ // get the output file handle from the debugger (if any)
+ File& out_file = interpreter.GetDebugger().GetOutputFile();
+ if (out_file.IsValid())
+ ResetOutputFileHandle(out_file.GetStream());
+}
+
+ScriptInterpreterPython::~ScriptInterpreterPython ()
+{
+ Debugger &debugger = GetCommandInterpreter().GetDebugger();
+
+ if (m_embedded_thread_input_reader_sp.get() != NULL)
+ {
+ m_embedded_thread_input_reader_sp->SetIsDone (true);
+ m_embedded_thread_pty.CloseSlaveFileDescriptor();
+ const InputReaderSP reader_sp = m_embedded_thread_input_reader_sp;
+ debugger.PopInputReader (reader_sp);
+ m_embedded_thread_input_reader_sp.reset();
+ }
+
+ if (m_embedded_python_input_reader_sp.get() != NULL)
+ {
+ m_embedded_python_input_reader_sp->SetIsDone (true);
+ m_embedded_python_pty.CloseSlaveFileDescriptor();
+ const InputReaderSP reader_sp = m_embedded_python_input_reader_sp;
+ debugger.PopInputReader (reader_sp);
+ m_embedded_python_input_reader_sp.reset();
+ }
+
+ if (m_new_sysout)
+ {
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeLock);
+ Py_XDECREF ((PyObject*)m_new_sysout);
+ }
+}
+
+void
+ScriptInterpreterPython::ResetOutputFileHandle (FILE *fh)
+{
+ if (fh == NULL)
+ return;
+
+ m_dbg_stdout = fh;
+
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
+
+ m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush);
+}
+
+void
+ScriptInterpreterPython::SaveTerminalState (int fd)
+{
+ // Python mucks with the terminal state of STDIN. If we can possibly avoid
+ // this by setting the file handles up correctly prior to entering the
+ // interpreter we should. For now we save and restore the terminal state
+ // on the input file handle.
+ m_terminal_state.Save (fd, false);
+}
+
+void
+ScriptInterpreterPython::RestoreTerminalState ()
+{
+ // Python mucks with the terminal state of STDIN. If we can possibly avoid
+ // this by setting the file handles up correctly prior to entering the
+ // interpreter we should. For now we save and restore the terminal state
+ // on the input file handle.
+ m_terminal_state.Restore();
+}
+
+void
+ScriptInterpreterPython::LeaveSession ()
+{
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+ if (log)
+ log->PutCString("ScriptInterpreterPython::LeaveSession()");
+
+ // checking that we have a valid thread state - since we use our own threading and locking
+ // in some (rare) cases during cleanup Python may end up believing we have no thread state
+ // and PyImport_AddModule will crash if that is the case - since that seems to only happen
+ // when destroying the SBDebugger, we can make do without clearing up stdout and stderr
+
+ // rdar://problem/11292882
+ // When the current thread state is NULL, PyThreadState_Get() issues a fatal error.
+ if (PyThreadState_GetDict())
+ {
+ PyObject *sysmod = PyImport_AddModule ("sys");
+ PyObject *sysdict = PyModule_GetDict (sysmod);
+
+ if (m_new_sysout && sysmod && sysdict)
+ {
+ if (m_old_sysout)
+ PyDict_SetItemString (sysdict, "stdout", (PyObject*)m_old_sysout);
+ if (m_old_syserr)
+ PyDict_SetItemString (sysdict, "stderr", (PyObject*)m_old_syserr);
+ }
+ }
+
+ m_session_is_active = false;
+}
+
+bool
+ScriptInterpreterPython::EnterSession (bool init_lldb_globals)
+{
+ // If we have already entered the session, without having officially 'left' it, then there is no need to
+ // 'enter' it again.
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+ if (m_session_is_active)
+ {
+ if (log)
+ log->Printf("ScriptInterpreterPython::EnterSession(init_lldb_globals=%i) session is already active, returning without doing anything", init_lldb_globals);
+ return false;
+ }
+
+ if (log)
+ log->Printf("ScriptInterpreterPython::EnterSession(init_lldb_globals=%i)", init_lldb_globals);
+
+
+ m_session_is_active = true;
+
+ StreamString run_string;
+
+ if (init_lldb_globals)
+ {
+ run_string.Printf ( "run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID());
+ run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID());
+ run_string.PutCString ("; lldb.target = lldb.debugger.GetSelectedTarget()");
+ run_string.PutCString ("; lldb.process = lldb.target.GetProcess()");
+ run_string.PutCString ("; lldb.thread = lldb.process.GetSelectedThread ()");
+ run_string.PutCString ("; lldb.frame = lldb.thread.GetSelectedFrame ()");
+ run_string.PutCString ("')");
+ }
+ else
+ {
+ // If we aren't initing the globals, we should still always set the debugger (since that is always unique.)
+ run_string.Printf ( "run_one_line (%s, \"lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID());
+ run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID());
+ run_string.PutCString ("\")");
+ }
+
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear();
+
+ PyObject *sysmod = PyImport_AddModule ("sys");
+ PyObject *sysdict = PyModule_GetDict (sysmod);
+
+ if (m_new_sysout && sysmod && sysdict)
+ {
+ m_old_sysout = PyDict_GetItemString(sysdict, "stdout");
+ m_old_syserr = PyDict_GetItemString(sysdict, "stderr");
+ if (m_new_sysout)
+ {
+ PyDict_SetItemString (sysdict, "stdout", (PyObject*)m_new_sysout);
+ PyDict_SetItemString (sysdict, "stderr", (PyObject*)m_new_sysout);
+ }
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear ();
+
+ return true;
+}
+
+static PyObject*
+FindSessionDictionary (const char* dict_name)
+{
+ static std::map<ConstString,PyObject*> g_dict_map;
+
+ ConstString dict(dict_name);
+
+ std::map<ConstString,PyObject*>::iterator iter = g_dict_map.find(dict);
+
+ if (iter != g_dict_map.end())
+ return iter->second;
+
+ PyObject *main_mod = PyImport_AddModule ("__main__");
+ if (main_mod != NULL)
+ {
+ PyObject *main_dict = PyModule_GetDict (main_mod);
+ if ((main_dict != NULL)
+ && PyDict_Check (main_dict))
+ {
+ // Go through the main dictionary looking for the correct python script interpreter dictionary
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
+
+ while (PyDict_Next (main_dict, &pos, &key, &value))
+ {
+ // We have stolen references to the key and value objects in the dictionary; we need to increment
+ // them now so that Python's garbage collector doesn't collect them out from under us.
+ Py_INCREF (key);
+ Py_INCREF (value);
+ if (strcmp (PyString_AsString (key), dict_name) == 0)
+ {
+ g_dict_map[dict] = value;
+ return value;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+static std::string
+GenerateUniqueName (const char* base_name_wanted,
+ uint32_t& functions_counter,
+ void* name_token = NULL)
+{
+ StreamString sstr;
+
+ if (!base_name_wanted)
+ return std::string();
+
+ if (!name_token)
+ sstr.Printf ("%s_%d", base_name_wanted, functions_counter++);
+ else
+ sstr.Printf ("%s_%p", base_name_wanted, name_token);
+
+ return sstr.GetString();
+}
+
+bool
+ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObject *result, const ExecuteScriptOptions &options)
+{
+ if (!m_valid_session)
+ return false;
+
+ // We want to call run_one_line, passing in the dictionary and the command string. We cannot do this through
+ // PyRun_SimpleString here because the command string may contain escaped characters, and putting it inside
+ // another string to pass to PyRun_SimpleString messes up the escaping. So we use the following more complicated
+ // method to pass the command string directly down to Python.
+
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0),
+ ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
+
+ bool success = false;
+
+ if (command)
+ {
+ // Find the correct script interpreter dictionary in the main module.
+ PyObject *script_interpreter_dict = FindSessionDictionary(m_dictionary_name.c_str());
+ if (script_interpreter_dict != NULL)
+ {
+ PyObject *pfunc = (PyObject*)m_run_one_line;
+ PyObject *pmod = PyImport_AddModule ("lldb.embedded_interpreter");
+ if (pmod != NULL)
+ {
+ PyObject *pmod_dict = PyModule_GetDict (pmod);
+ if ((pmod_dict != NULL)
+ && PyDict_Check (pmod_dict))
+ {
+ if (!pfunc)
+ {
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
+
+ while (PyDict_Next (pmod_dict, &pos, &key, &value))
+ {
+ Py_INCREF (key);
+ Py_INCREF (value);
+ if (strcmp (PyString_AsString (key), "run_one_line") == 0)
+ {
+ pfunc = value;
+ break;
+ }
+ }
+ m_run_one_line = pfunc;
+ }
+
+ if (pfunc && PyCallable_Check (pfunc))
+ {
+ PyObject *pargs = Py_BuildValue("(Os)",script_interpreter_dict,command);
+ if (pargs != NULL)
+ {
+ PyObject *pvalue = NULL;
+ { // scope for PythonInputReaderManager
+ PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
+ pvalue = PyObject_CallObject (pfunc, pargs);
+ }
+ Py_XDECREF (pargs);
+ if (pvalue != NULL)
+ {
+ Py_XDECREF (pvalue);
+ success = true;
+ }
+ else if (options.GetMaskoutErrors() && PyErr_Occurred ())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ }
+ }
+ }
+ }
+ Py_INCREF (script_interpreter_dict);
+ }
+
+ if (success)
+ return true;
+
+ // The one-liner failed. Append the error message.
+ if (result)
+ result->AppendErrorWithFormat ("python failed attempting to evaluate '%s'\n", command);
+ return false;
+ }
+
+ if (result)
+ result->AppendError ("empty command passed to python\n");
+ return false;
+}
+
+size_t
+ScriptInterpreterPython::InputReaderCallback
+(
+ void *baton,
+ InputReader &reader,
+ InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len
+)
+{
+ lldb::thread_t embedded_interpreter_thread;
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+
+ if (baton == NULL)
+ return 0;
+
+ ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
+
+ if (script_interpreter->m_script_lang != eScriptLanguagePython)
+ return 0;
+
+ switch (notification)
+ {
+ case eInputReaderActivate:
+ {
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
+ if (!batch_mode)
+ {
+ out_stream->Printf ("Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.\n");
+ out_stream->Flush();
+ }
+
+ // Save terminal settings if we can
+ int input_fd = reader.GetDebugger().GetInputFile().GetDescriptor();
+ if (input_fd == File::kInvalidDescriptor)
+ input_fd = STDIN_FILENO;
+
+ script_interpreter->SaveTerminalState(input_fd);
+
+ {
+ ScriptInterpreterPython::Locker locker(script_interpreter,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | ScriptInterpreterPython::Locker::InitGlobals,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
+ }
+
+ char error_str[1024];
+ if (script_interpreter->m_embedded_python_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str,
+ sizeof(error_str)))
+ {
+ if (log)
+ log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, succeeded in opening master pty (fd = %d).",
+ script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor());
+ embedded_interpreter_thread = Host::ThreadCreate ("<lldb.script-interpreter.embedded-python-loop>",
+ ScriptInterpreterPython::RunEmbeddedPythonInterpreter,
+ script_interpreter, NULL);
+ if (IS_VALID_LLDB_HOST_THREAD(embedded_interpreter_thread))
+ {
+ if (log)
+ log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, succeeded in creating thread (thread_t = %p)", (void *)embedded_interpreter_thread);
+ Error detach_error;
+ Host::ThreadDetach (embedded_interpreter_thread, &detach_error);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, failed in creating thread");
+ reader.SetIsDone (true);
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, failed to open master pty ");
+ reader.SetIsDone (true);
+ }
+ }
+ break;
+
+ case eInputReaderDeactivate:
+ // When another input reader is pushed, don't leave the session...
+ //script_interpreter->LeaveSession ();
+ break;
+
+ case eInputReaderReactivate:
+ {
+ ScriptInterpreterPython::Locker locker (script_interpreter,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
+ }
+ break;
+
+ case eInputReaderAsynchronousOutputWritten:
+ break;
+
+ case eInputReaderInterrupt:
+ ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "raise KeyboardInterrupt\n", 24);
+ break;
+
+ case eInputReaderEndOfFile:
+ ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "quit()\n", 7);
+ break;
+
+ case eInputReaderGotToken:
+ if (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor() != -1)
+ {
+ if (log)
+ log->Printf ("ScriptInterpreterPython::InputReaderCallback, GotToken, bytes='%s', byte_len = %lu", bytes,
+ bytes_len);
+ if (bytes && bytes_len)
+ {
+ if ((int) bytes[0] == 4)
+ ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "quit()", 6);
+ else
+ ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), bytes, bytes_len);
+ }
+ ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "\n", 1);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("ScriptInterpreterPython::InputReaderCallback, GotToken, bytes='%s', byte_len = %lu, Master File Descriptor is bad.",
+ bytes,
+ bytes_len);
+ reader.SetIsDone (true);
+ }
+
+ break;
+
+ case eInputReaderDone:
+ {
+ Locker locker(script_interpreter,
+ ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
+ script_interpreter->LeaveSession ();
+ }
+
+ // Restore terminal settings if they were validly saved
+ if (log)
+ log->Printf ("ScriptInterpreterPython::InputReaderCallback, Done, closing down input reader.");
+
+ script_interpreter->RestoreTerminalState ();
+
+ script_interpreter->m_embedded_python_pty.CloseMasterFileDescriptor();
+ break;
+ }
+
+ return bytes_len;
+}
+
+
+void
+ScriptInterpreterPython::ExecuteInterpreterLoop ()
+{
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+ Debugger &debugger = GetCommandInterpreter().GetDebugger();
+
+ // At the moment, the only time the debugger does not have an input file handle is when this is called
+ // directly from Python, in which case it is both dangerous and unnecessary (not to mention confusing) to
+ // try to embed a running interpreter loop inside the already running Python interpreter loop, so we won't
+ // do it.
+
+ if (!debugger.GetInputFile().IsValid())
+ return;
+
+ InputReaderSP reader_sp (new InputReader(debugger));
+ 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.PushInputReader (reader_sp);
+ m_embedded_python_input_reader_sp = reader_sp;
+ }
+ }
+}
+
+bool
+ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
+ ScriptInterpreter::ScriptReturnType return_type,
+ void *ret_value,
+ const ExecuteScriptOptions &options)
+{
+
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0),
+ ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
+
+ PyObject *py_return = NULL;
+ PyObject *mainmod = PyImport_AddModule ("__main__");
+ PyObject *globals = PyModule_GetDict (mainmod);
+ PyObject *locals = NULL;
+ PyObject *py_error = NULL;
+ bool ret_success = false;
+ bool should_decrement_locals = false;
+ int success;
+
+ locals = FindSessionDictionary(m_dictionary_name.c_str());
+
+ if (locals == NULL)
+ {
+ locals = PyObject_GetAttrString (globals, m_dictionary_name.c_str());
+ should_decrement_locals = true;
+ }
+
+ if (locals == NULL)
+ {
+ locals = globals;
+ should_decrement_locals = false;
+ }
+
+ py_error = PyErr_Occurred();
+ if (py_error != NULL)
+ PyErr_Clear();
+
+ if (in_string != NULL)
+ {
+ { // scope for PythonInputReaderManager
+ PythonInputReaderManager py_input(options.GetEnableIO() ? this : 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 (locals != NULL
+ && should_decrement_locals)
+ Py_XDECREF (locals);
+
+ if (py_return != NULL)
+ {
+ switch (return_type)
+ {
+ case eScriptReturnTypeCharPtr: // "char *"
+ {
+ const char format[3] = "s#";
+ success = PyArg_Parse (py_return, format, (char **) ret_value);
+ break;
+ }
+ case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == Py_None
+ {
+ const char format[3] = "z";
+ success = PyArg_Parse (py_return, format, (char **) ret_value);
+ break;
+ }
+ case eScriptReturnTypeBool:
+ {
+ const char format[2] = "b";
+ success = PyArg_Parse (py_return, format, (bool *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeShortInt:
+ {
+ const char format[2] = "h";
+ success = PyArg_Parse (py_return, format, (short *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeShortIntUnsigned:
+ {
+ const char format[2] = "H";
+ success = PyArg_Parse (py_return, format, (unsigned short *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeInt:
+ {
+ const char format[2] = "i";
+ success = PyArg_Parse (py_return, format, (int *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeIntUnsigned:
+ {
+ const char format[2] = "I";
+ success = PyArg_Parse (py_return, format, (unsigned int *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongInt:
+ {
+ const char format[2] = "l";
+ success = PyArg_Parse (py_return, format, (long *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongIntUnsigned:
+ {
+ const char format[2] = "k";
+ success = PyArg_Parse (py_return, format, (unsigned long *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongLong:
+ {
+ const char format[2] = "L";
+ success = PyArg_Parse (py_return, format, (long long *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongLongUnsigned:
+ {
+ const char format[2] = "K";
+ success = PyArg_Parse (py_return, format, (unsigned long long *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeFloat:
+ {
+ const char format[2] = "f";
+ success = PyArg_Parse (py_return, format, (float *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeDouble:
+ {
+ const char format[2] = "d";
+ success = PyArg_Parse (py_return, format, (double *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeChar:
+ {
+ const char format[2] = "c";
+ success = PyArg_Parse (py_return, format, (char *) ret_value);
+ break;
+ }
+ }
+ Py_XDECREF (py_return);
+ if (success)
+ ret_success = true;
+ else
+ ret_success = false;
+ }
+ }
+
+ py_error = PyErr_Occurred();
+ if (py_error != NULL)
+ {
+ ret_success = false;
+ if (options.GetMaskoutErrors())
+ {
+ if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
+ PyErr_Print ();
+ PyErr_Clear();
+ }
+ }
+
+ return ret_success;
+}
+
+bool
+ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const ExecuteScriptOptions &options)
+{
+
+
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0),
+ ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
+
+ bool success = false;
+ PyObject *py_return = NULL;
+ PyObject *mainmod = PyImport_AddModule ("__main__");
+ PyObject *globals = PyModule_GetDict (mainmod);
+ PyObject *locals = NULL;
+ PyObject *py_error = NULL;
+ bool should_decrement_locals = false;
+
+ locals = FindSessionDictionary(m_dictionary_name.c_str());
+
+ if (locals == NULL)
+ {
+ locals = PyObject_GetAttrString (globals, m_dictionary_name.c_str());
+ should_decrement_locals = true;
+ }
+
+ if (locals == NULL)
+ {
+ locals = globals;
+ should_decrement_locals = false;
+ }
+
+ py_error = PyErr_Occurred();
+ if (py_error != NULL)
+ PyErr_Clear();
+
+ 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)
+ {
+ { // scope for PythonInputReaderManager
+ PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
+ py_return = PyEval_EvalCode (compiled_code, globals, locals);
+ }
+ if (py_return != NULL)
+ {
+ success = true;
+ Py_XDECREF (py_return);
+ }
+ if (locals && should_decrement_locals)
+ Py_XDECREF (locals);
+ }
+ }
+ }
+
+ py_error = PyErr_Occurred ();
+ if (py_error != NULL)
+ {
+ success = false;
+ if (options.GetMaskoutErrors())
+ {
+ if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
+ PyErr_Print ();
+ PyErr_Clear();
+ }
+ }
+
+ return success;
+}
+
+static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.";
+
+static const char *g_bkpt_command_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
+ "def function(frame,bp_loc,internal_dict):\n"
+ " \"\"\"frame: the SBFrame for the location at which you stopped\n"
+ " bp_loc: an SBBreakpointLocation for the breakpoint location information\n"
+ " internal_dict: an LLDB support object not to be used\"\"\"";
+
+size_t
+ScriptInterpreterPython::GenerateBreakpointOptionsCommandCallback
+(
+ void *baton,
+ InputReader &reader,
+ InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len
+)
+{
+ static StringList commands_in_progress;
+
+ switch (notification)
+ {
+ case eInputReaderActivate:
+ {
+
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
+ commands_in_progress.Clear();
+ if (!batch_mode)
+ {
+ out_stream->Printf ("%s\n", g_bkpt_command_reader_instructions);
+ if (reader.GetPrompt())
+ out_stream->Printf ("%s", reader.GetPrompt());
+ out_stream->Flush ();
+ }
+ }
+ break;
+
+ case eInputReaderDeactivate:
+ break;
+
+ case eInputReaderReactivate:
+ {
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
+ if (reader.GetPrompt() && !batch_mode)
+ {
+ out_stream->Printf ("%s", reader.GetPrompt());
+ out_stream->Flush ();
+ }
+ }
+ break;
+
+ case eInputReaderAsynchronousOutputWritten:
+ break;
+
+ case eInputReaderGotToken:
+ {
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
+ std::string temp_string (bytes, bytes_len);
+ commands_in_progress.AppendString (temp_string.c_str());
+ if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
+ {
+ out_stream->Printf ("%s", reader.GetPrompt());
+ out_stream->Flush ();
+ }
+ }
+ break;
+
+ case eInputReaderEndOfFile:
+ case eInputReaderInterrupt:
+ // Control-c (SIGINT) & control-d both mean finish & exit.
+ reader.SetIsDone(true);
+
+ // Control-c (SIGINT) ALSO means cancel; do NOT create a breakpoint command.
+ if (notification == eInputReaderInterrupt)
+ commands_in_progress.Clear();
+
+ // Fall through here...
+
+ case eInputReaderDone:
+ {
+ bool batch_mode = notification == eInputReaderDone ?
+ reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode() :
+ true;
+ BreakpointOptions *bp_options = (BreakpointOptions *)baton;
+ std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+ data_ap->user_source.AppendList (commands_in_progress);
+ if (data_ap.get())
+ {
+ ScriptInterpreter *interpreter = reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ if (interpreter)
+ {
+ if (interpreter->GenerateBreakpointCommandCallbackData (data_ap->user_source,
+ data_ap->script_source))
+ {
+ BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+ bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
+ }
+ else if (!batch_mode)
+ {
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ out_stream->Printf ("Warning: No command attached to breakpoint.\n");
+ out_stream->Flush();
+ }
+ }
+ else
+ {
+ if (!batch_mode)
+ {
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ out_stream->Printf ("Warning: Unable to find script intepreter; no command attached to breakpoint.\n");
+ out_stream->Flush();
+ }
+ }
+ }
+ }
+ break;
+
+ }
+
+ return bytes_len;
+}
+
+size_t
+ScriptInterpreterPython::GenerateWatchpointOptionsCommandCallback
+(
+ void *baton,
+ InputReader &reader,
+ InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len
+)
+{
+ static StringList commands_in_progress;
+
+ switch (notification)
+ {
+ case eInputReaderActivate:
+ {
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
+
+ commands_in_progress.Clear();
+ if (!batch_mode)
+ {
+ out_stream->Printf ("%s\n", g_reader_instructions);
+ if (reader.GetPrompt())
+ out_stream->Printf ("%s", reader.GetPrompt());
+ out_stream->Flush ();
+ }
+ }
+ break;
+
+ case eInputReaderDeactivate:
+ break;
+
+ case eInputReaderReactivate:
+ {
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
+ if (reader.GetPrompt() && !batch_mode)
+ {
+ out_stream->Printf ("%s", reader.GetPrompt());
+ out_stream->Flush ();
+ }
+ }
+ break;
+
+ case eInputReaderAsynchronousOutputWritten:
+ break;
+
+ case eInputReaderGotToken:
+ {
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
+ std::string temp_string (bytes, bytes_len);
+ commands_in_progress.AppendString (temp_string.c_str());
+ if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
+ {
+ out_stream->Printf ("%s", reader.GetPrompt());
+ out_stream->Flush ();
+ }
+ }
+ break;
+
+ case eInputReaderEndOfFile:
+ case eInputReaderInterrupt:
+ // Control-c (SIGINT) & control-d both mean finish & exit.
+ reader.SetIsDone(true);
+
+ // Control-c (SIGINT) ALSO means cancel; do NOT create a breakpoint command.
+ if (notification == eInputReaderInterrupt)
+ commands_in_progress.Clear();
+
+ // Fall through here...
+
+ case eInputReaderDone:
+ {
+ bool batch_mode = notification == eInputReaderDone ?
+ reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode() :
+ true;
+ WatchpointOptions *wp_options = (WatchpointOptions *)baton;
+ std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
+ data_ap->user_source.AppendList (commands_in_progress);
+ if (data_ap.get())
+ {
+ ScriptInterpreter *interpreter = reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ if (interpreter)
+ {
+ if (interpreter->GenerateWatchpointCommandCallbackData (data_ap->user_source,
+ data_ap->script_source))
+ {
+ BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
+ wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp);
+ }
+ else if (!batch_mode)
+ {
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ out_stream->Printf ("Warning: No command attached to breakpoint.\n");
+ out_stream->Flush();
+ }
+ }
+ else
+ {
+ if (!batch_mode)
+ {
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ out_stream->Printf ("Warning: Unable to find script intepreter; no command attached to breakpoint.\n");
+ out_stream->Flush();
+ }
+ }
+ }
+ }
+ break;
+
+ }
+
+ return bytes_len;
+}
+
+void
+ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
+ CommandReturnObject &result)
+{
+ Debugger &debugger = GetCommandInterpreter().GetDebugger();
+
+ InputReaderSP reader_sp (new InputReader (debugger));
+
+ 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.PushInputReader (reader_sp);
+ else
+ {
+ result.AppendError (err.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError("out of memory");
+ result.SetStatus (eReturnStatusFailed);
+ }
+}
+
+void
+ScriptInterpreterPython::CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options,
+ CommandReturnObject &result)
+{
+ Debugger &debugger = GetCommandInterpreter().GetDebugger();
+
+ InputReaderSP reader_sp (new InputReader (debugger));
+
+ if (reader_sp)
+ {
+ Error err = reader_sp->Initialize (
+ ScriptInterpreterPython::GenerateWatchpointOptionsCommandCallback,
+ wp_options, // baton
+ eInputReaderGranularityLine, // token size, for feeding data to callback function
+ "DONE", // end token
+ "> ", // prompt
+ true); // echo input
+
+ if (err.Success())
+ debugger.PushInputReader (reader_sp);
+ else
+ {
+ result.AppendError (err.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError("out of memory");
+ result.SetStatus (eReturnStatusFailed);
+ }
+}
+
+// Set a Python one-liner as the callback for the breakpoint.
+void
+ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
+ const char *oneliner)
+{
+ std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+
+ // It's necessary to set both user_source and script_source to the oneliner.
+ // The former is used to generate callback description (as in breakpoint command list)
+ // while the latter is used for Python to interpret during the actual callback.
+
+ data_ap->user_source.AppendString (oneliner);
+ data_ap->script_source.assign (oneliner);
+
+ if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source))
+ {
+ BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+ bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
+ }
+
+ return;
+}
+
+// Set a Python one-liner as the callback for the watchpoint.
+void
+ScriptInterpreterPython::SetWatchpointCommandCallback (WatchpointOptions *wp_options,
+ const char *oneliner)
+{
+ std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
+
+ // It's necessary to set both user_source and script_source to the oneliner.
+ // The former is used to generate callback description (as in watchpoint command list)
+ // while the latter is used for Python to interpret during the actual callback.
+
+ data_ap->user_source.AppendString (oneliner);
+ data_ap->script_source.assign (oneliner);
+
+ if (GenerateWatchpointCommandCallbackData (data_ap->user_source, data_ap->script_source))
+ {
+ BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
+ wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp);
+ }
+
+ return;
+}
+
+bool
+ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def)
+{
+ // Convert StringList to one long, newline delimited, const char *.
+ std::string function_def_string(function_def.CopyList());
+
+ return ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false));
+}
+
+bool
+ScriptInterpreterPython::GenerateFunction(const char *signature, const StringList &input)
+{
+ int num_lines = input.GetSize ();
+ if (num_lines == 0)
+ return false;
+
+ if (!signature || *signature == 0)
+ return false;
+
+ StreamString sstr;
+ StringList auto_generated_function;
+ auto_generated_function.AppendString (signature);
+ auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary
+ auto_generated_function.AppendString (" new_keys = internal_dict.keys()"); // Make a list of keys in the session dict
+ auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict
+ auto_generated_function.AppendString (" global_dict.update (internal_dict)"); // Add the session dictionary to the
+ // global dictionary.
+
+ // Wrap everything up inside the function, increasing the indentation.
+
+ auto_generated_function.AppendString(" if True:");
+ for (int i = 0; i < num_lines; ++i)
+ {
+ sstr.Clear ();
+ sstr.Printf (" %s", input.GetStringAtIndex (i));
+ auto_generated_function.AppendString (sstr.GetData());
+ }
+ auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict
+ auto_generated_function.AppendString (" internal_dict[key] = global_dict[key]"); // Update session dict values
+ auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict
+ auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict
+
+ // Verify that the results are valid Python.
+
+ if (!ExportFunctionDefinitionToInterpreter (auto_generated_function))
+ return false;
+
+ return true;
+
+}
+
+bool
+ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, std::string& output, void* name_token)
+{
+ static uint32_t num_created_functions = 0;
+ user_input.RemoveBlankLines ();
+ StreamString sstr;
+
+ // Check to see if we have any data; if not, just return.
+ if (user_input.GetSize() == 0)
+ return false;
+
+ // Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the
+ // ValueObject as parameter to the function.
+
+ std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_type_print_func", num_created_functions, name_token));
+ sstr.Printf ("def %s (valobj, internal_dict):", auto_generated_function_name.c_str());
+
+ if (!GenerateFunction(sstr.GetData(), user_input))
+ return false;
+
+ // Store the name of the auto-generated function to be called.
+ output.assign(auto_generated_function_name);
+ return true;
+}
+
+bool
+ScriptInterpreterPython::GenerateScriptAliasFunction (StringList &user_input, std::string &output)
+{
+ static uint32_t num_created_functions = 0;
+ user_input.RemoveBlankLines ();
+ StreamString sstr;
+
+ // Check to see if we have any data; if not, just return.
+ if (user_input.GetSize() == 0)
+ return false;
+
+ std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_cmd_alias_func", num_created_functions));
+
+ sstr.Printf ("def %s (debugger, args, result, internal_dict):", auto_generated_function_name.c_str());
+
+ if (!GenerateFunction(sstr.GetData(),user_input))
+ return false;
+
+ // Store the name of the auto-generated function to be called.
+ output.assign(auto_generated_function_name);
+ return true;
+}
+
+
+bool
+ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::string &output, void* name_token)
+{
+ static uint32_t num_created_classes = 0;
+ user_input.RemoveBlankLines ();
+ int num_lines = user_input.GetSize ();
+ StreamString sstr;
+
+ // Check to see if we have any data; if not, just return.
+ if (user_input.GetSize() == 0)
+ return false;
+
+ // Wrap all user input into a Python class
+
+ std::string auto_generated_class_name(GenerateUniqueName("lldb_autogen_python_type_synth_class",num_created_classes,name_token));
+
+ StringList auto_generated_class;
+
+ // Create the function name & definition string.
+
+ sstr.Printf ("class %s:", auto_generated_class_name.c_str());
+ auto_generated_class.AppendString (sstr.GetData());
+
+ // Wrap everything up inside the class, increasing the indentation.
+ // we don't need to play any fancy indentation tricks here because there is no
+ // surrounding code whose indentation we need to honor
+ for (int i = 0; i < num_lines; ++i)
+ {
+ sstr.Clear ();
+ sstr.Printf (" %s", user_input.GetStringAtIndex (i));
+ auto_generated_class.AppendString (sstr.GetData());
+ }
+
+
+ // Verify that the results are valid Python.
+ // (even though the method is ExportFunctionDefinitionToInterpreter, a class will actually be exported)
+ // (TODO: rename that method to ExportDefinitionToInterpreter)
+ if (!ExportFunctionDefinitionToInterpreter (auto_generated_class))
+ return false;
+
+ // Store the name of the auto-generated class
+
+ output.assign(auto_generated_class_name);
+ return true;
+}
+
+lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::OSPlugin_CreatePluginObject (const char *class_name, lldb::ProcessSP process_sp)
+{
+ if (class_name == NULL || class_name[0] == '\0')
+ return lldb::ScriptInterpreterObjectSP();
+
+ if (!process_sp)
+ return lldb::ScriptInterpreterObjectSP();
+
+ void* ret_val;
+
+ {
+ Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+ ret_val = g_swig_create_os_plugin (class_name,
+ m_dictionary_name.c_str(),
+ process_sp);
+ }
+
+ return MakeScriptObject(ret_val);
+}
+
+lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp)
+{
+ Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+
+ static char callee_name[] = "get_register_info";
+
+ if (!os_plugin_object_sp)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject();
+
+ if (implementor == NULL || implementor == Py_None)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ if (pmeth == NULL || pmeth == Py_None)
+ {
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyCallable_Check(pmeth) == 0)
+ {
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+
+ // right now we know this function exists and is callable..
+ PyObject* py_return = PyObject_CallMethod(implementor, callee_name, NULL);
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ return MakeScriptObject(py_return);
+}
+
+lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp)
+{
+ Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+
+ static char callee_name[] = "get_thread_info";
+
+ if (!os_plugin_object_sp)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject();
+
+ if (implementor == NULL || implementor == Py_None)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ if (pmeth == NULL || pmeth == Py_None)
+ {
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyCallable_Check(pmeth) == 0)
+ {
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+
+ // right now we know this function exists and is callable..
+ PyObject* py_return = PyObject_CallMethod(implementor, callee_name, NULL);
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ return MakeScriptObject(py_return);
+}
+
+// GetPythonValueFormatString provides a system independent type safe way to
+// convert a variable's type into a python value format. Python value formats
+// are defined in terms of builtin C types and could change from system to
+// as the underlying typedef for uint* types, size_t, off_t and other values
+// change.
+
+template <typename T>
+const char *GetPythonValueFormatString(T t)
+{
+ assert(!"Unhandled type passed to GetPythonValueFormatString(T), make a specialization of GetPythonValueFormatString() to support this type.");
+ return NULL;
+}
+template <> const char *GetPythonValueFormatString (char *) { return "s"; }
+template <> const char *GetPythonValueFormatString (char) { return "b"; }
+template <> const char *GetPythonValueFormatString (unsigned char) { return "B"; }
+template <> const char *GetPythonValueFormatString (short) { return "h"; }
+template <> const char *GetPythonValueFormatString (unsigned short) { return "H"; }
+template <> const char *GetPythonValueFormatString (int) { return "i"; }
+template <> const char *GetPythonValueFormatString (unsigned int) { return "I"; }
+template <> const char *GetPythonValueFormatString (long) { return "l"; }
+template <> const char *GetPythonValueFormatString (unsigned long) { return "k"; }
+template <> const char *GetPythonValueFormatString (long long) { return "L"; }
+template <> const char *GetPythonValueFormatString (unsigned long long) { return "K"; }
+template <> const char *GetPythonValueFormatString (float t) { return "f"; }
+template <> const char *GetPythonValueFormatString (double t) { return "d"; }
+
+lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::OSPlugin_RegisterContextData (lldb::ScriptInterpreterObjectSP os_plugin_object_sp,
+ lldb::tid_t tid)
+{
+ Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+
+ static char callee_name[] = "get_register_data";
+ static char *param_format = const_cast<char *>(GetPythonValueFormatString(tid));
+
+ if (!os_plugin_object_sp)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject();
+
+ if (implementor == NULL || implementor == Py_None)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ if (pmeth == NULL || pmeth == Py_None)
+ {
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyCallable_Check(pmeth) == 0)
+ {
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+
+ // right now we know this function exists and is callable..
+ PyObject* py_return = PyObject_CallMethod(implementor, callee_name, param_format, tid);
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ return MakeScriptObject(py_return);
+}
+
+lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP os_plugin_object_sp,
+ lldb::tid_t tid,
+ lldb::addr_t context)
+{
+ Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+
+ static char callee_name[] = "create_thread";
+ std::string param_format;
+ param_format += GetPythonValueFormatString(tid);
+ param_format += GetPythonValueFormatString(context);
+
+ if (!os_plugin_object_sp)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject();
+
+ if (implementor == NULL || implementor == Py_None)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ if (pmeth == NULL || pmeth == Py_None)
+ {
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyCallable_Check(pmeth) == 0)
+ {
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+
+ // right now we know this function exists and is callable..
+ PyObject* py_return = PyObject_CallMethod(implementor, callee_name, &param_format[0], tid, context);
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ return MakeScriptObject(py_return);
+}
+
+lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::CreateSyntheticScriptedProvider (const char *class_name,
+ lldb::ValueObjectSP valobj)
+{
+ if (class_name == NULL || class_name[0] == '\0')
+ return lldb::ScriptInterpreterObjectSP();
+
+ if (!valobj.get())
+ return lldb::ScriptInterpreterObjectSP();
+
+ ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
+ Target *target = exe_ctx.GetTargetPtr();
+
+ if (!target)
+ return lldb::ScriptInterpreterObjectSP();
+
+ Debugger &debugger = target->GetDebugger();
+ ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
+
+ if (!script_interpreter)
+ return lldb::ScriptInterpreterObjectSP();
+
+ void* ret_val;
+
+ {
+ Locker py_lock(this);
+ ret_val = g_swig_synthetic_script (class_name,
+ python_interpreter->m_dictionary_name.c_str(),
+ valobj);
+ }
+
+ return MakeScriptObject(ret_val);
+}
+
+bool
+ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, std::string& output, void* name_token)
+{
+ StringList input;
+ input.SplitIntoLines(oneliner, strlen(oneliner));
+ return GenerateTypeScriptFunction(input, output, name_token);
+}
+
+bool
+ScriptInterpreterPython::GenerateTypeSynthClass (const char* oneliner, std::string& output, void* name_token)
+{
+ StringList input;
+ input.SplitIntoLines(oneliner, strlen(oneliner));
+ return GenerateTypeSynthClass(input, output, name_token);
+}
+
+
+bool
+ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, std::string& output)
+{
+ static uint32_t num_created_functions = 0;
+ user_input.RemoveBlankLines ();
+ StreamString sstr;
+
+ if (user_input.GetSize() == 0)
+ return false;
+
+ std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_bp_callback_func_",num_created_functions));
+ sstr.Printf ("def %s (frame, bp_loc, internal_dict):", auto_generated_function_name.c_str());
+
+ if (!GenerateFunction(sstr.GetData(), user_input))
+ return false;
+
+ // Store the name of the auto-generated function to be called.
+ output.assign(auto_generated_function_name);
+ return true;
+}
+
+bool
+ScriptInterpreterPython::GenerateWatchpointCommandCallbackData (StringList &user_input, std::string& output)
+{
+ static uint32_t num_created_functions = 0;
+ user_input.RemoveBlankLines ();
+ StreamString sstr;
+
+ if (user_input.GetSize() == 0)
+ return false;
+
+ std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_wp_callback_func_",num_created_functions));
+ sstr.Printf ("def %s (frame, wp, internal_dict):", auto_generated_function_name.c_str());
+
+ if (!GenerateFunction(sstr.GetData(), user_input))
+ return false;
+
+ // Store the name of the auto-generated function to be called.
+ output.assign(auto_generated_function_name);
+ return true;
+}
+
+bool
+ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name,
+ lldb::ValueObjectSP valobj,
+ lldb::ScriptInterpreterObjectSP& callee_wrapper_sp,
+ std::string& retval)
+{
+
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+ if (!valobj.get())
+ {
+ retval.assign("<no object>");
+ return false;
+ }
+
+ void* old_callee = (callee_wrapper_sp ? callee_wrapper_sp->GetObject() : NULL);
+ void* new_callee = old_callee;
+
+ bool ret_val;
+ if (python_function_name
+ && *python_function_name)
+ {
+ {
+ Locker py_lock(this);
+ {
+ Timer scoped_timer ("g_swig_typescript_callback","g_swig_typescript_callback");
+ ret_val = g_swig_typescript_callback (python_function_name,
+ FindSessionDictionary(m_dictionary_name.c_str()),
+ valobj,
+ &new_callee,
+ retval);
+ }
+ }
+ }
+ else
+ {
+ retval.assign("<no function name>");
+ return false;
+ }
+
+ if (new_callee && old_callee != new_callee)
+ callee_wrapper_sp = MakeScriptObject(new_callee);
+
+ return ret_val;
+
+}
+
+bool
+ScriptInterpreterPython::BreakpointCallbackFunction
+(
+ void *baton,
+ StoppointCallbackContext *context,
+ user_id_t break_id,
+ user_id_t break_loc_id
+)
+{
+ BreakpointOptions::CommandData *bp_option_data = (BreakpointOptions::CommandData *) baton;
+ const char *python_function_name = bp_option_data->script_source.c_str();
+
+ if (!context)
+ return true;
+
+ ExecutionContext exe_ctx (context->exe_ctx_ref);
+ Target *target = exe_ctx.GetTargetPtr();
+
+ if (!target)
+ return true;
+
+ Debugger &debugger = target->GetDebugger();
+ ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
+
+ if (!script_interpreter)
+ return true;
+
+ if (python_function_name != NULL
+ && python_function_name[0] != '\0')
+ {
+ const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP());
+ BreakpointSP breakpoint_sp = target->GetBreakpointByID (break_id);
+ if (breakpoint_sp)
+ {
+ const BreakpointLocationSP bp_loc_sp (breakpoint_sp->FindLocationByID (break_loc_id));
+
+ if (stop_frame_sp && bp_loc_sp)
+ {
+ bool ret_val = true;
+ {
+ Locker py_lock(python_interpreter);
+ ret_val = g_swig_breakpoint_callback (python_function_name,
+ python_interpreter->m_dictionary_name.c_str(),
+ stop_frame_sp,
+ bp_loc_sp);
+ }
+ return ret_val;
+ }
+ }
+ }
+ // We currently always true so we stop in case anything goes wrong when
+ // trying to call the script function
+ return true;
+}
+
+bool
+ScriptInterpreterPython::WatchpointCallbackFunction
+(
+ void *baton,
+ StoppointCallbackContext *context,
+ user_id_t watch_id
+)
+{
+ WatchpointOptions::CommandData *wp_option_data = (WatchpointOptions::CommandData *) baton;
+ const char *python_function_name = wp_option_data->script_source.c_str();
+
+ if (!context)
+ return true;
+
+ ExecutionContext exe_ctx (context->exe_ctx_ref);
+ Target *target = exe_ctx.GetTargetPtr();
+
+ if (!target)
+ return true;
+
+ Debugger &debugger = target->GetDebugger();
+ ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
+
+ if (!script_interpreter)
+ return true;
+
+ if (python_function_name != NULL
+ && python_function_name[0] != '\0')
+ {
+ const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP());
+ WatchpointSP wp_sp = target->GetWatchpointList().FindByID (watch_id);
+ if (wp_sp)
+ {
+ if (stop_frame_sp && wp_sp)
+ {
+ bool ret_val = true;
+ {
+ Locker py_lock(python_interpreter);
+ ret_val = g_swig_watchpoint_callback (python_function_name,
+ python_interpreter->m_dictionary_name.c_str(),
+ stop_frame_sp,
+ wp_sp);
+ }
+ return ret_val;
+ }
+ }
+ }
+ // We currently always true so we stop in case anything goes wrong when
+ // trying to call the script function
+ return true;
+}
+
+lldb::thread_result_t
+ScriptInterpreterPython::RunEmbeddedPythonInterpreter (lldb::thread_arg_t baton)
+{
+ ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
+
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+
+ if (log)
+ log->Printf ("%p ScriptInterpreterPython::RunEmbeddedPythonInterpreter () thread starting...", baton);
+
+ char error_str[1024];
+ const char *pty_slave_name = script_interpreter->m_embedded_python_pty.GetSlaveName (error_str, sizeof (error_str));
+
+ if (pty_slave_name != NULL)
+ {
+ StreamString run_string;
+
+ // Ensure we have the GIL before running any Python code.
+ // Since we're only running a few one-liners and then dropping to the interpreter (which will release the GIL when needed),
+ // we can just release the GIL after finishing our work.
+ // If finer-grained locking is desirable, we can lock and unlock the GIL only when calling a python function.
+ Locker locker(script_interpreter,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | ScriptInterpreterPython::Locker::InitGlobals,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
+
+ run_string.Printf ("run_one_line (%s, 'save_stderr = sys.stderr')", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear ();
+
+ run_string.Printf ("run_one_line (%s, 'sys.stderr = sys.stdout')", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear ();
+
+ run_string.Printf ("run_one_line (%s, 'save_stdin = sys.stdin')", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear ();
+
+ run_string.Printf ("run_one_line (%s, \"sys.stdin = open ('%s', 'r')\")", script_interpreter->m_dictionary_name.c_str(),
+ pty_slave_name);
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear ();
+
+ // The following call drops into the embedded interpreter loop and stays there until the
+ // user chooses to exit from the Python interpreter.
+ // This embedded interpreter will, as any Python code that performs I/O, unlock the GIL before
+ // a system call that can hang, and lock it when the syscall has returned.
+
+ // We need to surround the call to the embedded interpreter with calls to PyGILState_Ensure and
+ // PyGILState_Release (using the Locker above). This is because Python has a global lock which must be held whenever we want
+ // to touch any Python objects. Otherwise, if the user calls Python code, the interpreter state will be off,
+ // and things could hang (it's happened before).
+
+ run_string.Printf ("run_python_interpreter (%s)", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear ();
+
+ run_string.Printf ("run_one_line (%s, 'sys.stdin = save_stdin')", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear();
+
+ run_string.Printf ("run_one_line (%s, 'sys.stderr = save_stderr')", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear();
+ }
+
+ if (script_interpreter->m_embedded_python_input_reader_sp)
+ script_interpreter->m_embedded_python_input_reader_sp->SetIsDone (true);
+
+ script_interpreter->m_embedded_python_pty.CloseSlaveFileDescriptor();
+
+ log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT);
+ if (log)
+ log->Printf ("%p ScriptInterpreterPython::RunEmbeddedPythonInterpreter () thread exiting...", baton);
+
+
+ // Clean up the input reader and make the debugger pop it off the stack.
+ Debugger &debugger = script_interpreter->GetCommandInterpreter().GetDebugger();
+ const InputReaderSP reader_sp = script_interpreter->m_embedded_python_input_reader_sp;
+ if (reader_sp)
+ {
+ debugger.PopInputReader (reader_sp);
+ script_interpreter->m_embedded_python_input_reader_sp.reset();
+ }
+
+ return NULL;
+}
+
+lldb::thread_result_t
+ScriptInterpreterPython::PythonInputReaderManager::RunPythonInputReader (lldb::thread_arg_t baton)
+{
+ ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
+
+ const InputReaderSP reader_sp = script_interpreter->m_embedded_thread_input_reader_sp;
+
+ if (reader_sp)
+ reader_sp->WaitOnReaderIsDone();
+
+ return NULL;
+}
+
+size_t
+ScriptInterpreterPython::CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor_sp)
+{
+ if (!implementor_sp)
+ return 0;
+
+ void* implementor = implementor_sp->GetObject();
+
+ if (!implementor)
+ return 0;
+
+ if (!g_swig_calc_children)
+ return 0;
+
+ uint32_t ret_val = 0;
+
+ {
+ Locker py_lock(this);
+ ret_val = g_swig_calc_children (implementor);
+ }
+
+ return ret_val;
+}
+
+lldb::ValueObjectSP
+ScriptInterpreterPython::GetChildAtIndex (const lldb::ScriptInterpreterObjectSP& implementor_sp, uint32_t idx)
+{
+ if (!implementor_sp)
+ return lldb::ValueObjectSP();
+
+ void* implementor = implementor_sp->GetObject();
+
+ if (!implementor)
+ return lldb::ValueObjectSP();
+
+ if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue)
+ return lldb::ValueObjectSP();
+
+ void* child_ptr = NULL;
+ lldb::SBValue* value_sb = NULL;
+ lldb::ValueObjectSP ret_val;
+
+ {
+ Locker py_lock(this);
+ child_ptr = g_swig_get_child_index (implementor,idx);
+ if (child_ptr != NULL && child_ptr != Py_None)
+ {
+ value_sb = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);
+ if (value_sb == NULL)
+ Py_XDECREF(child_ptr);
+ else
+ ret_val = value_sb->GetSP();
+ }
+ else
+ {
+ Py_XDECREF(child_ptr);
+ }
+ }
+
+ return ret_val;
+}
+
+int
+ScriptInterpreterPython::GetIndexOfChildWithName (const lldb::ScriptInterpreterObjectSP& implementor_sp, const char* child_name)
+{
+ if (!implementor_sp)
+ return UINT32_MAX;
+
+ void* implementor = implementor_sp->GetObject();
+
+ if (!implementor)
+ return UINT32_MAX;
+
+ if (!g_swig_get_index_child)
+ return UINT32_MAX;
+
+ int ret_val = UINT32_MAX;
+
+ {
+ Locker py_lock(this);
+ ret_val = g_swig_get_index_child (implementor, child_name);
+ }
+
+ return ret_val;
+}
+
+bool
+ScriptInterpreterPython::UpdateSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor_sp)
+{
+ bool ret_val = false;
+
+ if (!implementor_sp)
+ return ret_val;
+
+ void* implementor = implementor_sp->GetObject();
+
+ if (!implementor)
+ return ret_val;
+
+ if (!g_swig_update_provider)
+ return ret_val;
+
+ {
+ Locker py_lock(this);
+ ret_val = g_swig_update_provider (implementor);
+ }
+
+ return ret_val;
+}
+
+bool
+ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor_sp)
+{
+ bool ret_val = false;
+
+ if (!implementor_sp)
+ return ret_val;
+
+ void* implementor = implementor_sp->GetObject();
+
+ if (!implementor)
+ return ret_val;
+
+ if (!g_swig_mighthavechildren_provider)
+ return ret_val;
+
+ {
+ Locker py_lock(this);
+ ret_val = g_swig_mighthavechildren_provider (implementor);
+ }
+
+ return ret_val;
+}
+
+static std::string
+ReadPythonBacktrace (PyObject* py_backtrace)
+{
+ PyObject* traceback_module = NULL,
+ *stringIO_module = NULL,
+ *stringIO_builder = NULL,
+ *stringIO_buffer = NULL,
+ *printTB = NULL,
+ *printTB_args = NULL,
+ *printTB_result = NULL,
+ *stringIO_getvalue = NULL,
+ *printTB_string = NULL;
+
+ std::string retval("backtrace unavailable");
+
+ if (py_backtrace && py_backtrace != Py_None)
+ {
+ traceback_module = PyImport_ImportModule("traceback");
+ stringIO_module = PyImport_ImportModule("StringIO");
+
+ if (traceback_module && traceback_module != Py_None && stringIO_module && stringIO_module != Py_None)
+ {
+ stringIO_builder = PyObject_GetAttrString(stringIO_module, "StringIO");
+ if (stringIO_builder && stringIO_builder != Py_None)
+ {
+ stringIO_buffer = PyObject_CallObject(stringIO_builder, NULL);
+ if (stringIO_buffer && stringIO_buffer != Py_None)
+ {
+ printTB = PyObject_GetAttrString(traceback_module, "print_tb");
+ if (printTB && printTB != Py_None)
+ {
+ printTB_args = Py_BuildValue("OOO",py_backtrace,Py_None,stringIO_buffer);
+ printTB_result = PyObject_CallObject(printTB, printTB_args);
+ stringIO_getvalue = PyObject_GetAttrString(stringIO_buffer, "getvalue");
+ if (stringIO_getvalue && stringIO_getvalue != Py_None)
+ {
+ printTB_string = PyObject_CallObject (stringIO_getvalue,NULL);
+ if (printTB_string && printTB_string != Py_None && PyString_Check(printTB_string))
+ retval.assign(PyString_AsString(printTB_string));
+ }
+ }
+ }
+ }
+ }
+ }
+ Py_XDECREF(traceback_module);
+ Py_XDECREF(stringIO_module);
+ Py_XDECREF(stringIO_builder);
+ Py_XDECREF(stringIO_buffer);
+ Py_XDECREF(printTB);
+ Py_XDECREF(printTB_args);
+ Py_XDECREF(printTB_result);
+ Py_XDECREF(stringIO_getvalue);
+ Py_XDECREF(printTB_string);
+ return retval;
+}
+
+bool
+ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
+ Process* process,
+ std::string& output,
+ Error& error)
+{
+ bool ret_val;
+ if (!process)
+ {
+ error.SetErrorString("no process");
+ return false;
+ }
+ if (!impl_function || !impl_function[0])
+ {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+ if (!g_swig_run_script_keyword_process)
+ {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+ {
+ ProcessSP process_sp(process->shared_from_this());
+ Locker py_lock(this);
+ ret_val = g_swig_run_script_keyword_process (impl_function, m_dictionary_name.c_str(), process_sp, output);
+ if (!ret_val)
+ error.SetErrorString("python script evaluation failed");
+ }
+ return ret_val;
+}
+
+bool
+ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
+ Thread* thread,
+ std::string& output,
+ Error& error)
+{
+ bool ret_val;
+ if (!thread)
+ {
+ error.SetErrorString("no thread");
+ return false;
+ }
+ if (!impl_function || !impl_function[0])
+ {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+ if (!g_swig_run_script_keyword_thread)
+ {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+ {
+ ThreadSP thread_sp(thread->shared_from_this());
+ Locker py_lock(this);
+ ret_val = g_swig_run_script_keyword_thread (impl_function, m_dictionary_name.c_str(), thread_sp, output);
+ if (!ret_val)
+ error.SetErrorString("python script evaluation failed");
+ }
+ return ret_val;
+}
+
+bool
+ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
+ Target* target,
+ std::string& output,
+ Error& error)
+{
+ bool ret_val;
+ if (!target)
+ {
+ error.SetErrorString("no thread");
+ return false;
+ }
+ if (!impl_function || !impl_function[0])
+ {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+ if (!g_swig_run_script_keyword_target)
+ {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+ {
+ TargetSP target_sp(target->shared_from_this());
+ Locker py_lock(this);
+ ret_val = g_swig_run_script_keyword_target (impl_function, m_dictionary_name.c_str(), target_sp, output);
+ if (!ret_val)
+ error.SetErrorString("python script evaluation failed");
+ }
+ return ret_val;
+}
+
+bool
+ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
+ StackFrame* frame,
+ std::string& output,
+ Error& error)
+{
+ bool ret_val;
+ if (!frame)
+ {
+ error.SetErrorString("no frame");
+ return false;
+ }
+ if (!impl_function || !impl_function[0])
+ {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+ if (!g_swig_run_script_keyword_frame)
+ {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+ {
+ StackFrameSP frame_sp(frame->shared_from_this());
+ Locker py_lock(this);
+ ret_val = g_swig_run_script_keyword_frame (impl_function, m_dictionary_name.c_str(), frame_sp, output);
+ if (!ret_val)
+ error.SetErrorString("python script evaluation failed");
+ }
+ return ret_val;
+}
+
+uint64_t replace_all(std::string& str, const std::string& oldStr, const std::string& newStr)
+{
+ size_t pos = 0;
+ uint64_t matches = 0;
+ while((pos = str.find(oldStr, pos)) != std::string::npos)
+ {
+ matches++;
+ str.replace(pos, oldStr.length(), newStr);
+ pos += newStr.length();
+ }
+ return matches;
+}
+
+bool
+ScriptInterpreterPython::LoadScriptingModule (const char* pathname,
+ bool can_reload,
+ bool init_session,
+ lldb_private::Error& error)
+{
+ if (!pathname || !pathname[0])
+ {
+ error.SetErrorString("invalid pathname");
+ return false;
+ }
+
+ if (!g_swig_call_module_init)
+ {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+
+ lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
+
+ {
+ FileSpec target_file(pathname, true);
+ std::string basename(target_file.GetFilename().GetCString());
+
+ StreamString command_stream;
+
+ // Before executing Pyton code, lock the GIL.
+ Locker py_lock (this,
+ Locker::AcquireLock | (init_session ? Locker::InitSession : 0),
+ Locker::FreeAcquiredLock | (init_session ? Locker::TearDownSession : 0));
+
+ if (target_file.GetFileType() == FileSpec::eFileTypeInvalid ||
+ target_file.GetFileType() == FileSpec::eFileTypeUnknown)
+ {
+ // if not a valid file of any sort, check if it might be a filename still
+ // dot can't be used but / and \ can, and if either is found, reject
+ if (strchr(pathname,'\\') || strchr(pathname,'/'))
+ {
+ error.SetErrorString("invalid pathname");
+ return false;
+ }
+ basename = pathname; // not a filename, probably a package of some sort, let it go through
+ }
+ else if (target_file.GetFileType() == FileSpec::eFileTypeDirectory ||
+ target_file.GetFileType() == FileSpec::eFileTypeRegular ||
+ target_file.GetFileType() == FileSpec::eFileTypeSymbolicLink)
+ {
+ std::string directory(target_file.GetDirectory().GetCString());
+ replace_all(directory,"'","\\'");
+
+ // now make sure that Python has "directory" in the search path
+ StreamString command_stream;
+ command_stream.Printf("if not (sys.path.__contains__('%s')):\n sys.path.insert(1,'%s');\n\n",
+ directory.c_str(),
+ directory.c_str());
+ bool syspath_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false));
+ if (!syspath_retval)
+ {
+ error.SetErrorString("Python sys.path handling failed");
+ return false;
+ }
+
+ // strip .py or .pyc extension
+ ConstString extension = target_file.GetFileNameExtension();
+ if (extension)
+ {
+ if (::strcmp(extension.GetCString(), "py") == 0)
+ basename.resize(basename.length()-3);
+ else if(::strcmp(extension.GetCString(), "pyc") == 0)
+ basename.resize(basename.length()-4);
+ }
+ }
+ else
+ {
+ error.SetErrorString("no known way to import this module specification");
+ return false;
+ }
+
+ // check if the module is already import-ed
+ command_stream.Clear();
+ command_stream.Printf("sys.modules.__contains__('%s')",basename.c_str());
+ bool does_contain = false;
+ int refcount = 0;
+ // this call will succeed if the module was ever imported in any Debugger in the lifetime of the process
+ // in which this LLDB framework is living
+ bool was_imported_globally = (ExecuteOneLineWithReturn(command_stream.GetData(),
+ ScriptInterpreterPython::eScriptReturnTypeBool,
+ &does_contain,
+ ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)) && does_contain);
+ // this call will fail if the module was not imported in this Debugger before
+ command_stream.Clear();
+ command_stream.Printf("sys.getrefcount(%s)",basename.c_str());
+ bool was_imported_locally = (ExecuteOneLineWithReturn(command_stream.GetData(),
+ ScriptInterpreterPython::eScriptReturnTypeInt,
+ &refcount,
+ ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)) && refcount > 0);
+
+ bool was_imported = (was_imported_globally || was_imported_locally);
+
+ if (was_imported == true && can_reload == false)
+ {
+ error.SetErrorString("module already imported");
+ return false;
+ }
+
+ // now actually do the import
+ command_stream.Clear();
+
+ if (was_imported)
+ {
+ if (!was_imported_locally)
+ command_stream.Printf("import %s ; reload(%s)",basename.c_str(),basename.c_str());
+ else
+ command_stream.Printf("reload(%s)",basename.c_str());
+ }
+ else
+ command_stream.Printf("import %s",basename.c_str());
+
+ bool import_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false).SetMaskoutErrors(false));
+ PyObject* py_error = PyErr_Occurred(); // per Python docs: "you do not need to Py_DECREF()" the return of this function
+
+ if (py_error || !import_retval) // check for failure of the import
+ {
+ if (py_error) // if we have a Python error..
+ {
+ PyObject *type = NULL,*value = NULL,*traceback = NULL;
+ PyErr_Fetch (&type,&value,&traceback);
+
+ if (PyErr_GivenExceptionMatches (py_error, PyExc_ImportError)) // and it is an ImportError
+ {
+ if (value && value != Py_None)
+ error.SetErrorString(PyString_AsString(PyObject_Str(value)));
+ else
+ error.SetErrorString("ImportError raised by imported module");
+ }
+ else // any other error
+ {
+ // get the backtrace
+ std::string bt = ReadPythonBacktrace(traceback);
+
+ if (value && value != Py_None)
+ error.SetErrorStringWithFormat("Python error raised while importing module: %s - traceback: %s", PyString_AsString(PyObject_Str(value)),bt.c_str());
+ else
+ error.SetErrorStringWithFormat("Python raised an error while importing module - traceback: %s",bt.c_str());
+ }
+
+ Py_XDECREF(type);
+ Py_XDECREF(value);
+ Py_XDECREF(traceback);
+ }
+ else // we failed but have no error to explain why
+ {
+ error.SetErrorString("unknown error while importing module");
+ }
+
+ // anyway, clear the error indicator and return false
+ PyErr_Clear();
+ return false;
+ }
+
+ // if we are here, everything worked
+ // call __lldb_init_module(debugger,dict)
+ if (!g_swig_call_module_init (basename.c_str(),
+ m_dictionary_name.c_str(),
+ debugger_sp))
+ {
+ error.SetErrorString("calling __lldb_init_module failed");
+ return false;
+ }
+ return true;
+ }
+}
+
+lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::MakeScriptObject (void* object)
+{
+ return lldb::ScriptInterpreterObjectSP(new ScriptInterpreterPythonObject(object));
+}
+
+ScriptInterpreterPython::SynchronicityHandler::SynchronicityHandler (lldb::DebuggerSP debugger_sp,
+ ScriptedCommandSynchronicity synchro) :
+ m_debugger_sp(debugger_sp),
+ m_synch_wanted(synchro),
+ m_old_asynch(debugger_sp->GetAsyncExecution())
+{
+ if (m_synch_wanted == eScriptedCommandSynchronicitySynchronous)
+ m_debugger_sp->SetAsyncExecution(false);
+ else if (m_synch_wanted == eScriptedCommandSynchronicityAsynchronous)
+ m_debugger_sp->SetAsyncExecution(true);
+}
+
+ScriptInterpreterPython::SynchronicityHandler::~SynchronicityHandler()
+{
+ if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue)
+ m_debugger_sp->SetAsyncExecution(m_old_asynch);
+}
+
+bool
+ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function,
+ const char* args,
+ ScriptedCommandSynchronicity synchronicity,
+ lldb_private::CommandReturnObject& cmd_retobj,
+ Error& error)
+{
+ if (!impl_function)
+ {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+
+ if (!g_swig_call_command)
+ {
+ error.SetErrorString("no helper function to run scripted commands");
+ return false;
+ }
+
+ lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
+
+ if (!debugger_sp.get())
+ {
+ error.SetErrorString("invalid Debugger pointer");
+ return false;
+ }
+
+ bool ret_val = false;
+
+ std::string err_msg;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession,
+ Locker::FreeLock | Locker::TearDownSession);
+
+ SynchronicityHandler synch_handler(debugger_sp,
+ synchronicity);
+
+ // we need to save the thread state when we first start the command
+ // because we might decide to interrupt it while some action is taking
+ // place outside of Python (e.g. printing to screen, waiting for the network, ...)
+ // in that case, _PyThreadState_Current will be NULL - and we would be unable
+ // to set the asynchronous exception - not a desirable situation
+ m_command_thread_state = _PyThreadState_Current;
+
+ PythonInputReaderManager py_input(this);
+
+ ret_val = g_swig_call_command (impl_function,
+ m_dictionary_name.c_str(),
+ debugger_sp,
+ args,
+ cmd_retobj);
+ }
+
+ if (!ret_val)
+ error.SetErrorString("unable to execute script function");
+ else
+ error.Clear();
+
+ return ret_val;
+}
+
+// in Python, a special attribute __doc__ contains the docstring
+// for an object (function, method, class, ...) if any is defined
+// Otherwise, the attribute's value is None
+bool
+ScriptInterpreterPython::GetDocumentationForItem(const char* item, std::string& dest)
+{
+ dest.clear();
+ if (!item || !*item)
+ return false;
+ std::string command(item);
+ command += ".__doc__";
+
+ char* result_ptr = NULL; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully
+
+ if (ExecuteOneLineWithReturn (command.c_str(),
+ ScriptInterpreter::eScriptReturnTypeCharStrOrNone,
+ &result_ptr,
+ ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)))
+ {
+ if (result_ptr)
+ dest.assign(result_ptr);
+ return true;
+ }
+ else
+ {
+ StreamString str_stream;
+ str_stream.Printf("Function %s was not found. Containing module might be missing.",item);
+ dest.assign(str_stream.GetData());
+ return false;
+ }
+}
+
+std::unique_ptr<ScriptInterpreterLocker>
+ScriptInterpreterPython::AcquireInterpreterLock ()
+{
+ std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(this,
+ Locker::AcquireLock | Locker::InitSession,
+ Locker::FreeLock | Locker::TearDownSession));
+ return py_lock;
+}
+
+void
+ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_init_callback)
+{
+ g_swig_init_callback = python_swig_init_callback;
+ g_swig_breakpoint_callback = LLDBSwigPythonBreakpointCallbackFunction;
+ g_swig_watchpoint_callback = LLDBSwigPythonWatchpointCallbackFunction;
+ g_swig_typescript_callback = LLDBSwigPythonCallTypeScript;
+ g_swig_synthetic_script = LLDBSwigPythonCreateSyntheticProvider;
+ g_swig_calc_children = LLDBSwigPython_CalculateNumChildren;
+ g_swig_get_child_index = LLDBSwigPython_GetChildAtIndex;
+ g_swig_get_index_child = LLDBSwigPython_GetIndexOfChildWithName;
+ g_swig_cast_to_sbvalue = LLDBSWIGPython_CastPyObjectToSBValue;
+ g_swig_update_provider = LLDBSwigPython_UpdateSynthProviderInstance;
+ g_swig_mighthavechildren_provider = LLDBSwigPython_MightHaveChildrenSynthProviderInstance;
+ g_swig_call_command = LLDBSwigPythonCallCommand;
+ g_swig_call_module_init = LLDBSwigPythonCallModuleInit;
+ g_swig_create_os_plugin = LLDBSWIGPythonCreateOSPlugin;
+ g_swig_run_script_keyword_process = LLDBSWIGPythonRunScriptKeywordProcess;
+ g_swig_run_script_keyword_thread = LLDBSWIGPythonRunScriptKeywordThread;
+ g_swig_run_script_keyword_target = LLDBSWIGPythonRunScriptKeywordTarget;
+ g_swig_run_script_keyword_frame = LLDBSWIGPythonRunScriptKeywordFrame;
+}
+
+void
+ScriptInterpreterPython::InitializePrivate ()
+{
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+ // Python will muck with STDIN terminal state, so save off any current TTY
+ // settings so we can restore them.
+ TerminalState stdin_tty_state;
+ stdin_tty_state.Save(STDIN_FILENO, false);
+
+ PyGILState_STATE gstate;
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
+ bool threads_already_initialized = false;
+ if (PyEval_ThreadsInitialized ()) {
+ gstate = PyGILState_Ensure ();
+ if (log)
+ log->Printf("Ensured PyGILState. Previous state = %slocked\n", gstate == PyGILState_UNLOCKED ? "un" : "");
+ threads_already_initialized = true;
+ } else {
+ // InitThreads acquires the GIL if it hasn't been called before.
+ PyEval_InitThreads ();
+ }
+ Py_InitializeEx (0);
+
+ // Initialize SWIG after setting up python
+ assert (g_swig_init_callback != NULL);
+ g_swig_init_callback ();
+
+ // Update the path python uses to search for modules to include the current directory.
+
+ PyRun_SimpleString ("import sys");
+ PyRun_SimpleString ("sys.path.append ('.')");
+
+ // Find the module that owns this code and use that path we get to
+ // set the sys.path appropriately.
+
+ FileSpec file_spec;
+ char python_dir_path[PATH_MAX];
+ if (Host::GetLLDBPath (ePathTypePythonDir, file_spec))
+ {
+ std::string python_path("sys.path.insert(0,\"");
+ size_t orig_len = python_path.length();
+ if (file_spec.GetPath(python_dir_path, sizeof (python_dir_path)))
+ {
+ python_path.append (python_dir_path);
+ python_path.append ("\")");
+ PyRun_SimpleString (python_path.c_str());
+ python_path.resize (orig_len);
+ }
+
+ if (Host::GetLLDBPath (ePathTypeLLDBShlibDir, file_spec))
+ {
+ if (file_spec.GetPath(python_dir_path, sizeof (python_dir_path)))
+ {
+ python_path.append (python_dir_path);
+ python_path.append ("\")");
+ PyRun_SimpleString (python_path.c_str());
+ python_path.resize (orig_len);
+ }
+ }
+ }
+
+ PyRun_SimpleString ("sys.dont_write_bytecode = 1; import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line; from termios import *");
+
+ if (threads_already_initialized) {
+ if (log)
+ log->Printf("Releasing PyGILState. Returning to state = %slocked\n", gstate == PyGILState_UNLOCKED ? "un" : "");
+ PyGILState_Release (gstate);
+ } else {
+ // We initialized the threads in this function, just unlock the GIL.
+ PyEval_SaveThread();
+ }
+
+ stdin_tty_state.Restore();
+}
+
+//void
+//ScriptInterpreterPython::Terminate ()
+//{
+// // We are intentionally NOT calling Py_Finalize here (this would be the logical place to call it). Calling
+// // Py_Finalize here causes test suite runs to seg fault: The test suite runs in Python. It registers
+// // SBDebugger::Terminate to be called 'at_exit'. When the test suite Python harness finishes up, it calls
+// // Py_Finalize, which calls all the 'at_exit' registered functions. SBDebugger::Terminate calls Debugger::Terminate,
+// // which calls lldb::Terminate, which calls ScriptInterpreter::Terminate, which calls
+// // ScriptInterpreterPython::Terminate. So if we call Py_Finalize here, we end up with Py_Finalize being called from
+// // within Py_Finalize, which results in a seg fault.
+// //
+// // Since this function only gets called when lldb is shutting down and going away anyway, the fact that we don't
+// // actually call Py_Finalize should not cause any problems (everything should shut down/go away anyway when the
+// // process exits).
+// //
+//// Py_Finalize ();
+//}
+
+#endif // #ifdef LLDB_DISABLE_PYTHON
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py b/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py
new file mode 100644
index 0000000..0e57c1e
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Interpreter/embedded_interpreter.py
@@ -0,0 +1,103 @@
+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()" or temp_str.lower() == "exit()"):
+ 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 one_line (self, input):
+ line = self.process_input (input)
+ more = self.push(line)
+ if more:
+ self.write ("Input not a complete line.")
+ self.resetbuffer()
+ more = 0
+
+def run_python_interpreter (dict):
+ # Pass in the dictionary, for continuity from one session to the next.
+ repl = SimpleREPL('>>> ', dict)
+ repl.interact()
+
+def run_one_line (dict, input_string):
+ repl = SimpleREPL ('', dict)
+ repl.one_line (input_string)
+
OpenPOWER on IntegriCloud